From 9bd1ba7c4748a77d1e8dab0d898f79bedba22eac Mon Sep 17 00:00:00 2001 From: Bradley Bell Date: Fri, 19 Jan 2001 03:30:16 +0000 Subject: [PATCH] This commit was generated by cvs2svn to compensate for changes in r2, which included commits to RCS files with non-trunk default branches. --- 2d/2dsline.c | 184 + 2d/Makefile.am | 18 + 2d/Makefile.in | 313 ++ 2d/bitblt.c | 954 ++++ 2d/bitmap.c | 327 ++ 2d/bitmap.h | 70 + 2d/box.c | 125 + 2d/canvas.c | 147 + 2d/circle.c | 114 + 2d/clip.h | 158 + 2d/diff | 354 ++ 2d/disc.c | 95 + 2d/font.c | 1707 +++++++ 2d/gpixel.c | 76 + 2d/ibitblt.c | 192 + 2d/line.c | 320 ++ 2d/linear.asm | 485 ++ 2d/linear.h | 476 ++ 2d/palette.c | 229 + 2d/pcx.c | 315 ++ 2d/pixel.c | 97 + 2d/poly.c | 280 + 2d/rect.c | 70 + 2d/rle.c | 663 +++ 2d/scale.c | 463 ++ 2d/scalea.asm | 236 + 2d/scalea.h | 95 + 2d/scalec.c | 413 ++ 2d/tmerge.c | 61 + 2d/tmerge_a.asm | 283 ++ 3d/Makefile.am | 6 + 3d/Makefile.in | 303 ++ 3d/clipper.c | 226 + 3d/clipper.h | 44 + 3d/draw.c | 373 ++ 3d/globvars.c | 76 + 3d/globvars.h | 66 + 3d/instance.c | 131 + 3d/interp.asm | 1012 ++++ 3d/interp.c | 537 ++ 3d/matrix.c | 104 + 3d/points.c | 231 + 3d/rod.c | 223 + 3d/setup.c | 139 + AUTHORS | 2 + COPYING | 21 + ChangeLog | 22 + INSTALL | 17 + Makefile.am | 7 + Makefile.in | 363 ++ NEWS | 0 README | 96 + aclocal.m4 | 160 + arch/Makefile.am | 5 + arch/Makefile.in | 339 ++ arch/dos/allg_snd/allg_snd.c | 368 ++ arch/dos/allg_snd/internal.h | 529 ++ arch/dos/allg_snd/sound/allegro.h | 2716 ++++++++++ arch/dos/allg_snd/sound/config.c | 755 +++ arch/dos/allg_snd/sound/digmid.c | 998 ++++ arch/dos/allg_snd/sound/drv/adlib.c | 872 ++++ arch/dos/allg_snd/sound/drv/awedata.c | 1848 +++++++ arch/dos/allg_snd/sound/drv/dma.c | 269 + arch/dos/allg_snd/sound/drv/emu8k.c | 651 +++ arch/dos/allg_snd/sound/drv/emu8k.h | 121 + arch/dos/allg_snd/sound/drv/emu8kmid.c | 408 ++ arch/dos/allg_snd/sound/drv/fm_instr.h | 339 ++ arch/dos/allg_snd/sound/drv/gus.c | 318 ++ arch/dos/allg_snd/sound/drv/mpu.c | 164 + arch/dos/allg_snd/sound/drv/sb.c | 795 +++ arch/dos/allg_snd/sound/interndj.h | 210 + arch/dos/allg_snd/sound/midi.c | 1512 ++++++ arch/dos/allg_snd/sound/mixer.c | 975 ++++ arch/dos/allg_snd/sound/readme.d1 | 6 + arch/dos/allg_snd/sound/readme.txt | 323 ++ arch/dos/allg_snd/sound/snddrv.c | 42 + arch/dos/allg_snd/sound/sound.c | 1579 ++++++ arch/dos/bak/ipx.c | 936 ++++ arch/dos/bcd.c | 745 +++ arch/dos/comm/commlib.c | 300 ++ arch/dos/comm/dzcomm.c | 889 ++++ arch/dos/comm/dzqueue.c | 168 + arch/dos/comm/include/allegro.h | 45 + arch/dos/comm/include/asmdef.inc | 15 + arch/dos/comm/include/asmdefs.inc | 8 + arch/dos/comm/include/commlib.h | 58 + arch/dos/comm/include/internal.h | 1 + arch/dos/comm/irq.c | 157 + arch/dos/comm/irqwrap.S | 138 + arch/dos/digiallg.c | 1017 ++++ arch/dos/digimm.c | 996 ++++ arch/dos/disk.c | 17 + arch/dos/dosgr.c | 721 +++ arch/dos/dpmi.c | 473 ++ arch/dos/include/commlib.h | 59 + arch/dos/include/disk.h | 6 + arch/dos/include/dzcomm.h | 220 + arch/dos/include/joy.h | 188 + arch/dos/include/key.h | 270 + arch/dos/include/midiallg.h | 12 + arch/dos/include/mouse.h | 132 + arch/dos/include/serial.h | 2 + arch/dos/init.c | 366 ++ arch/dos/ipx.c | 908 ++++ arch/dos/ipx.h | 147 + arch/dos/joy2.asm | 471 ++ arch/dos/joyc.c | 803 +++ arch/dos/joydefs.c | 678 +++ arch/dos/key.c | 714 +++ arch/dos/midiallg.c | 148 + arch/dos/mm_snd/drv_sb.c | 518 ++ arch/dos/mm_snd/include/mdma.h | 42 + arch/dos/mm_snd/include/mikmod.h | 1 + arch/dos/mm_snd/include/mirq.h | 35 + arch/dos/mm_snd/include/mm_drv.h | 124 + arch/dos/mm_snd/include/mmio.h | 1 + arch/dos/mm_snd/include/mtypes.h | 75 + arch/dos/mm_snd/mdma.c | 543 ++ arch/dos/mm_snd/mirq.c | 102 + arch/dos/mm_snd/readme.txt | 2 + arch/dos/modex.asm | 829 +++ arch/dos/mono.c | 470 ++ arch/dos/mono.h | 120 + arch/dos/mouse.c | 657 +++ arch/dos/serial.c | 21 + arch/dos/sgrep.out | 3 + arch/dos/timer.asm | 496 ++ arch/dos/tweak.inc | 258 + arch/dos/vesa.c | 134 + arch/dos/vgaregs.inc | 62 + arch/linux/Makefile.am | 6 + arch/linux/Makefile.in | 302 ++ arch/linux/alsadigi.c | 918 ++++ arch/linux/findfile.c | 53 + arch/linux/hmiplay.c | 773 +++ arch/linux/hmistub.c | 2 + arch/linux/include/ipx_bsd.h | 6 + arch/linux/include/ipx_drv.h | 68 + arch/linux/include/ipx_hlpr.h | 28 + arch/linux/include/ipx_kali.h | 6 + arch/linux/include/ipx_ld.h | 49 + arch/linux/include/ipx_lin.h | 13 + arch/linux/include/ipx_udp.h | 6 + arch/linux/include/music.h | 33 + arch/linux/include/serial.h | 18 + arch/linux/include/ukali.h | 72 + arch/linux/init.c | 46 + arch/linux/ipx_bsd.c | 228 + arch/linux/ipx_kali.c | 112 + arch/linux/ipx_lin.c | 214 + arch/linux/ipx_udp.c | 591 +++ arch/linux/linuxnet.c | 366 ++ arch/linux/mono.c | 20 + arch/linux/serial.c | 216 + arch/linux/stHqFIq1 | Bin 0 -> 86016 bytes arch/linux/svgalib/event.c | 25 + arch/linux/svgalib/gr.c | 309 ++ arch/linux/svgalib/include/event.h | 9 + arch/linux/svgalib/include/key.h | 271 + arch/linux/svgalib/include/mouse.h | 127 + arch/linux/svgalib/init.c | 9 + arch/linux/svgalib/key.c | 383 ++ arch/linux/svgalib/mouse.c | 197 + arch/linux/timer.c | 20 + arch/linux/ukali.c | 257 + arch/ogl/include/loadgl.h | 1935 +++++++ arch/ogl/include/ogl_init.h | 160 + arch/sdl/Makefile.am | 4 + arch/sdl/Makefile.in | 299 ++ arch/sdl/init.c | 29 + arch/sdl/timer.c | 13 + arch/win32/d1x.ico | Bin 0 -> 2494 bytes arch/win32/d1x.rc | 220 + arch/win32/d3d.ico | Bin 0 -> 953 bytes arch/win32/d3dframe/d3denum.cpp | 641 +++ arch/win32/d3dframe/d3denum.h | 180 + arch/win32/d3dframe/d3dframe.cpp | 754 +++ arch/win32/d3dframe/d3dframe.h | 136 + arch/win32/d3dframe/d3dmath.cpp | 341 ++ arch/win32/d3dframe/d3dmath.h | 85 + arch/win32/d3dframe/d3dtextr.cpp | 788 +++ arch/win32/d3dframe/d3dtextr.h | 62 + arch/win32/d3dframe/d3dutil.cpp | 390 ++ arch/win32/d3dframe/d3dutil.h | 110 + arch/win32/d3dframe/ddenum.cpp | 314 ++ arch/win32/d3dframe/ddmm.h | 21 + arch/win32/d3dframe/ddutil.h | 24 + arch/win32/d3dframe/ddutil2.h | 24 + arch/win32/d3dframe/dsutil.h | 216 + arch/win32/d3dframe/lbprintf.h | 26 + arch/win32/d3dframe/resource.h | 32 + arch/win32/d3dframe/userdlg.cpp | 383 ++ arch/win32/debug.cpp | 1168 +++++ arch/win32/descent.ico | Bin 0 -> 766 bytes arch/win32/digi.c | 971 ++++ arch/win32/glinit.c | 8 + arch/win32/gr.c | 397 ++ arch/win32/hmpfile.c | 404 ++ arch/win32/include/d3dhelp.h | 11 + arch/win32/include/debug.h | 152 + arch/win32/include/hmpfile.h | 50 + arch/win32/include/joy.h | 121 + arch/win32/include/key.h | 271 + arch/win32/include/mouse.h | 138 + arch/win32/include/pch.h | 47 + arch/win32/include/resource.h | 27 + arch/win32/include/scene.h | 23 + arch/win32/include/serial.h | 15 + arch/win32/include/texture.h | 134 + arch/win32/include/winmain.h | 17 + arch/win32/include/wsipx.h | 58 + arch/win32/init.c | 198 + arch/win32/ipx_drv.h | 68 + arch/win32/ipx_win.c | 195 + arch/win32/joydefs.c | 145 + arch/win32/joyhh.c | 640 +++ arch/win32/key.c | 481 ++ arch/win32/mono.c | 13 + arch/win32/mouse.c | 620 +++ arch/win32/palw32.c | 225 + arch/win32/pch.cpp | 4 + arch/win32/scene.cpp | 810 +++ arch/win32/serial.c | 41 + arch/win32/texture.cpp | 533 ++ arch/win32/timer.c | 71 + arch/win32/win32.c | 335 ++ arch/win32/winmain.cpp | 690 +++ arch/win32/winnet.c | 353 ++ autogen.sh | 5 + cfile/Makefile.am | 4 + cfile/Makefile.in | 299 ++ cfile/cfile.c | 480 ++ cfile/nocfile.h | 38 + conf.h.in | 35 + config.guess | 1087 ++++ config.sub | 1215 +++++ configure | 2285 +++++++++ configure.in | 115 + iff/Makefile.am | 4 + iff/Makefile.in | 299 ++ iff/archive/iff15bpp.c | 92 + iff/archive/iff8bpp.c | 94 + iff/archive/iffmike.c | 488 ++ iff/archive/ifftest.c | 105 + iff/archive/ifftestv.c | 59 + iff/iff.c | 1259 +++++ include/3d.h | 253 + include/args.h | 55 + include/byteswap.h | 35 + include/cfile.h | 58 + include/checker.h | 34 + include/cmd.h | 21 + include/console.h | 46 + include/d.bat | 2 + include/d_delay.h | 13 + include/d_io.h | 18 + include/dtypes.h | 34 + include/dtypes.inc | 25 + include/error.h | 146 + include/findfile.h | 17 + include/fix.h | 2 + include/gr.h | 467 ++ include/grdef.h | 119 + include/hash.h | 33 + include/ibitblt.h | 60 + include/iff.h | 73 + include/ipx.h | 152 + include/loadgl.h | 1935 +++++++ include/lst.bat | 1 + include/m.bat | 1 + include/maths.h | 208 + include/modex.h | 17 + include/mono.h | 48 + include/ogl_init.h | 160 + include/pa_enabl.h | 35 + include/palette.h | 88 + include/pcx.h | 72 + include/psmacros.inc | 330 ++ include/pstypes.h | 51 + include/pstypes.inc | 25 + include/rle.h | 64 + include/strio.h | 8 + include/strutil.h | 33 + include/test.c | 15 + include/test.lnk | 5 + include/texmap.h | 181 + include/timer.h | 127 + include/u_dpmi.h | 131 + include/u_mem.h | 44 + include/vecmat.h | 585 +++ include/vesa.h | 12 + input/Makefile.am | 17 + input/Makefile.in | 344 ++ input/ggi/Makefile.am | 5 + input/ggi/Makefile.in | 300 ++ input/ggi/event.c | 127 + input/ggi/include/event.h | 14 + input/ggi/include/key.h | 273 + input/ggi/include/mouse.h | 127 + input/ggi/init.c | 11 + input/ggi/key.c | 495 ++ input/ggi/mouse.c | 158 + input/linux/Makefile.am | 4 + input/linux/Makefile.in | 299 ++ input/linux/include/joy.h | 150 + input/linux/include/joystick.h | 266 + input/linux/joydefs.c | 237 + input/linux/joystick.c | 376 ++ input/sdl/Makefile.am | 4 + input/sdl/Makefile.in | 299 ++ input/sdl/event.c | 54 + input/sdl/include/event.h | 9 + input/sdl/include/key.h | 271 + input/sdl/include/mouse.h | 127 + input/sdl/key.c | 616 +++ input/sdl/mouse.c | 234 + install-sh | 251 + libtool | 4240 ++++++++++++++++ ltconfig | 3022 +++++++++++ ltmain.sh | 3975 +++++++++++++++ main/Makefile.am | 31 + main/Makefile.in | 355 ++ main/ai.c | 1674 ++++++ main/ai.h | 336 ++ main/ai2.c | 2614 ++++++++++ main/aipath.c | 1843 +++++++ main/aistruct.h | 199 + main/automap.c | 1913 +++++++ main/automap.h | 36 + main/bm.c | 942 ++++ main/bm.h | 100 + main/bmread.c | 2468 +++++++++ main/bmread.h | 21 + main/cdrom.h | 13 + main/cmd.c | 62 + main/cntrlcen.c | 504 ++ main/cntrlcen.h | 77 + main/collide.c | 2660 ++++++++++ main/collide.h | 45 + main/compbit.h | 23 + main/config.c | 1106 ++++ main/config.h | 65 + main/console.c | 155 + main/controls.c | 197 + main/controls.h | 28 + main/credits.c | 511 ++ main/credits.h | 22 + main/crypt.c | 56 + main/desc_id.h | 29 + main/descent.cfg | 16 + main/desw.h | 153 + main/digi.h | 230 + main/dumpmine.c | 1155 +++++ main/editor/editor.h | 654 +++ main/editor/kdefs.h | 336 ++ main/editor/texpage.h | 31 + main/effects.c | 169 + main/effects.h | 66 + main/endlevel.c | 1676 ++++++ main/endlevel.h | 47 + main/escort.c | 1976 ++++++++ main/fireball.c | 1462 ++++++ main/fireball.h | 67 + main/fuelcen.c | 1128 +++++ main/fuelcen.h | 134 + main/fvi.c | 1352 +++++ main/fvi.h | 81 + main/fvi_a.h | 56 + main/game.c | 3311 ++++++++++++ main/game.h | 259 + main/gamecntl.c | 2558 ++++++++++ main/gamefont.c | 71 + main/gamefont.h | 50 + main/gamemine.c | 849 ++++ main/gamemine.h | 116 + main/gamepal.c | 179 + main/gamepal.h | 35 + main/gamerend.c | 1981 ++++++++ main/gamesave.c | 2310 +++++++++ main/gamesave.h | 38 + main/gameseg.c | 2207 ++++++++ main/gameseg.h | 130 + main/gameseq.c | 2427 +++++++++ main/gameseq.h | 127 + main/gamestat.h | 12 + main/gauges.c | 4007 +++++++++++++++ main/gauges.h | 98 + main/hostage.c | 65 + main/hostage.h | 32 + main/hud.c | 452 ++ main/inferno.c | 784 +++ main/inferno.h | 69 + main/inferno.ini | 47 + main/joydefs.h | 26 + main/kconfig.c | 3588 +++++++++++++ main/kconfig.h | 207 + main/kludge.c | 218 + main/kmatrix.c | 849 ++++ main/kmatrix.h | 23 + main/laser.c | 2286 +++++++++ main/laser.h | 142 + main/lighting.c | 678 +++ main/lighting.h | 46 + main/menu.c | 1535 ++++++ main/menu.h | 60 + main/mglobal.c | 101 + main/mission.c | 584 +++ main/mission.h | 60 + main/modem.h | 39 + main/morph.c | 468 ++ main/morph.h | 54 + main/movie.h | 40 + main/multi.c | 5414 ++++++++++++++++++++ main/multi.h | 418 ++ main/multibot.c | 1299 +++++ main/multibot.h | 51 + main/netmisc.c | 751 +++ main/netmisc.h | 50 + main/network.c | 6476 ++++++++++++++++++++++++ main/network.h | 143 + main/newdemo.c | 3366 ++++++++++++ main/newdemo.h | 111 + main/newmenu.c | 3286 ++++++++++++ main/newmenu.h | 136 + main/object.c | 2443 +++++++++ main/object.h | 433 ++ main/old/3dfx.c | 598 +++ main/old/3dfx_des.h | 92 + main/old/arcade.h | 36 + main/old/cdmix32.c | 190 + main/old/cdrom.c | 92 + main/old/coindev.c | 99 + main/old/coindev.h | 97 + main/old/descentw.c | 1204 +++++ main/old/digiobj.c | 910 ++++ main/old/files.h | 83 + main/old/iglasses.c | 345 ++ main/old/iglasses.h | 26 + main/old/joydefs.c | 930 ++++ main/old/joydefsw.c | 594 +++ main/old/modem.c | 2720 ++++++++++ main/old/movie.c | 1279 +++++ main/old/newmodel.c | 74 + main/old/rbtest.c | 52 + main/old/settings.h | 26 + main/old/terrain.c | 487 ++ main/old/windigi.c | 825 +++ main/old/winferno.c | 736 +++ main/old/winmodem.c | 2568 ++++++++++ main/old/winvideo.c | 19 + main/paging.c | 514 ++ main/paging.h | 21 + main/physics.c | 1149 +++++ main/physics.h | 52 + main/piggy.c | 1723 +++++++ main/piggy.h | 93 + main/player.h | 193 + main/playsave.c | 808 +++ main/playsave.h | 42 + main/polyobj.c | 759 +++ main/polyobj.h | 91 + main/powerup.c | 701 +++ main/powerup.h | 118 + main/render.c | 2215 ++++++++ main/render.h | 91 + main/robot.c | 240 + main/robot.h | 173 + main/scores.c | 485 ++ main/scores.h | 44 + main/screens.h | 93 + main/segment.h | 238 + main/segpoint.h | 23 + main/slew.c | 172 + main/slew.h | 37 + main/songs.c | 385 ++ main/songs.h | 61 + main/sounds.h | 148 + main/state.c | 1592 ++++++ main/state.h | 30 + main/switch.c | 638 +++ main/switch.h | 72 + main/terrain.h | 23 + main/test.txt | 1 + main/texmerge.c | 374 ++ main/texmerge.h | 25 + main/text.c | 161 + main/text.h | 751 +++ main/textures.h | 26 + main/titles.c | 1323 +++++ main/titles.h | 33 + main/vclip.c | 102 + main/vclip.h | 54 + main/vers_id.h | 8 + main/wall.c | 1543 ++++++ main/wall.h | 225 + main/weapon.c | 1300 +++++ main/weapon.h | 220 + maths/Makefile.am | 14 + maths/Makefile.in | 307 ++ maths/fix.asm | 1406 +++++ maths/fixc.c | 558 ++ maths/rand.c | 27 + maths/tables.c | 1034 ++++ maths/vecmat.c | 936 ++++ maths/vecmata.asm | 1790 +++++++ mem/Makefile.am | 4 + mem/Makefile.in | 299 ++ mem/mem.c | 690 +++ misc/Makefile.am | 12 + misc/Makefile.in | 307 ++ misc/args.c | 148 + misc/byteswap.c | 32 + misc/byteswap.h | 44 + misc/d_delay.c | 41 + misc/d_glob.c | 93 + misc/d_io.c | 72 + misc/error.c | 185 + misc/errtest.c | 18 + misc/fileutil.c | 128 + misc/fileutil.h | 47 + misc/hash.c | 119 + misc/parsarg.c | 132 + misc/parsarg.h | 48 + misc/parstest.c | 19 + misc/strio.c | 62 + misc/strutil.c | 154 + missing | 190 + mkinstalldirs | 40 + readme.txt | 75 + sound/Makefile.am | 3 + sound/Makefile.in | 298 ++ sound/sdl_cdrom.c | 120 + sound/sdl_digi.c | 842 +++ stamp-h.in | 0 texmap/Makefile.am | 17 + texmap/Makefile.in | 309 ++ texmap/ntmap.c | 1182 +++++ texmap/scanline.c | 960 ++++ texmap/scanline.h | 47 + texmap/texmapl.h | 139 + texmap/tmap_flt.asm | 170 + texmap/tmap_inc.asm | 173 + texmap/tmap_lin.asm | 270 + texmap/tmap_ll.asm | 487 ++ texmap/tmap_per.asm | 1350 +++++ texmap/tmapfade.asm | 144 + texmap/tmapflat.c | 320 ++ texmap/tmappent.S | 614 +++ texmap/tmapppro.S | 609 +++ thinking.txt | 2 + unused/bios/d.bat | 1 + unused/bios/dd.bat | 1 + unused/bios/dpmi.c | 365 ++ unused/bios/dpmi.h | 64 + unused/bios/error.c | 211 + unused/bios/error.h | 72 + unused/bios/findfile.c | 111 + unused/bios/findfile.h | 37 + unused/bios/ipx.c | 758 +++ unused/bios/ipx.h | 55 + unused/bios/joy.asm | 252 + unused/bios/joy.h | 134 + unused/bios/joyc.c | 603 +++ unused/bios/key.asm | 906 ++++ unused/bios/key.c | 537 ++ unused/bios/key.h | 199 + unused/bios/keys.inc | 284 ++ unused/bios/make0000.bat | 5 + unused/bios/make0001.bat | 5 + unused/bios/make0100.bat | 5 + unused/bios/mono.c | 399 ++ unused/bios/mouse.asm | 316 ++ unused/bios/mouse.c | 558 ++ unused/bios/mouse.h | 71 + unused/bios/oldkey.asm | 1060 ++++ unused/bios/rbaudio.c | 711 +++ unused/bios/rbaudio.h | 58 + unused/bios/rbaudio.new | 736 +++ unused/bios/speaker.c | 19 + unused/bios/swiftcfg.h | 84 + unused/bios/testj.c | 111 + unused/bios/testk.c | 101 + unused/bios/testk.lnk | 4 + unused/bios/testm.c | 122 + unused/bios/testm.lnk | 4 + unused/bios/testms.c | 77 + unused/bios/testt.c | 57 + unused/bios/timer.asm | 551 ++ unused/bios/timer.h | 61 + unused/bios/timerp.c | 19 + unused/bios/x | 3 + unused/bios/x.bat | 1 + unused/bios/x.c | 4 + unused/bios/y.bat | 11 + unused/lib/fix.h | 147 + unused/lib/rbaudio.h | 58 + unused/novga/files.rc | 0 unused/novga/novesa.c | 117 + unused/pa_null/pa_enabl.h | 35 + unused/pa_null/poly_acc.c | 325 ++ unused/pa_null/poly_acc.h | 76 + unused/readme.txt | 2 + unused/ui/barbox.c | 111 + unused/ui/button.c | 199 + unused/ui/checkbox.c | 127 + unused/ui/file.c | 584 +++ unused/ui/func.c | 110 + unused/ui/func.h | 34 + unused/ui/gadget.c | 339 ++ unused/ui/harderr.c | 17 + unused/ui/icon.c | 148 + unused/ui/inputbox.c | 162 + unused/ui/keypad.c | 549 ++ unused/ui/keypress.c | 141 + unused/ui/keytrap.c | 38 + unused/ui/listbox.c | 400 ++ unused/ui/medfunc.c | 115 + unused/ui/menu.c | 124 + unused/ui/menubar.c | 825 +++ unused/ui/message.c | 194 + unused/ui/mouse.c | 308 ++ unused/ui/number.c | 116 + unused/ui/popup.c | 149 + unused/ui/radio.c | 151 + unused/ui/scroll.c | 242 + unused/ui/ui.c | 96 + unused/ui/ui.h | 403 ++ unused/ui/uidraw.c | 119 + unused/ui/userbox.c | 138 + unused/ui/window.c | 625 +++ unused/vga/dd.bat | 1 + unused/vga/framebuf.c | 334 ++ unused/vga/framebuf.jas | 320 ++ unused/vga/fxdpmi.h | 56 + unused/vga/fxvesa.h | 41 + unused/vga/grx.h | 389 ++ unused/vga/modex.asm | 770 +++ unused/vga/new/palette.c | 484 ++ unused/vga/new/vga.c | 622 +++ unused/vga/palette.c | 486 ++ unused/vga/tweak.inc | 235 + unused/vga/vesa.asm | 925 ++++ unused/vga/vga.c | 622 +++ unused/vga/vga.h | 87 + unused/vga/vga.jas | 611 +++ unused/vga/vgaregs.inc | 42 + unused/vga/xyz.bat | 10 + unused/win95/comm.c | 769 +++ unused/win95/comm.h | 91 + unused/win95/dd.bat | 1 + unused/win95/dd.c | 796 +++ unused/win95/dd.h | 200 + unused/win95/ddgfx.c | 295 ++ unused/win95/ddgr.c | 761 +++ unused/win95/ddraw.c | 1006 ++++ unused/win95/direct3d.c | 252 + unused/win95/direct3d.h | 37 + unused/win95/ds.c | 513 ++ unused/win95/ds.h | 60 + unused/win95/error.c | 211 + unused/win95/error.h | 72 + unused/win95/findfile.c | 91 + unused/win95/gfx.c | 123 + unused/win95/global.h | 38 + unused/win95/iforce.c | 125 + unused/win95/iforce.h | 34 + unused/win95/ipx.c | 746 +++ unused/win95/joyc.c | 913 ++++ unused/win95/key.c | 428 ++ unused/win95/midifile.h | 267 + unused/win95/midiseq.h | 127 + unused/win95/mono.c | 417 ++ unused/win95/mouse.c | 350 ++ unused/win95/palette.c | 665 +++ unused/win95/rbaudio.c | 672 +++ unused/win95/swift.c | 67 + unused/win95/tactile.c | 144 + unused/win95/tactile.h | 111 + unused/win95/timer.c | 152 + unused/win95/winapp.c | 304 ++ unused/win95/winapp.h | 43 + unused/win95/winckpit.asm | 128 + unused/win95/winmidi.c | 1045 ++++ unused/win95/winmidi.h | 39 + unused/win95/winmono.c | 152 + unused/win95/winregs.c | 269 + unused/win95/winregs.h | 29 + unused/win95/xtapi.c | 1033 ++++ unused/win95/xtapi.h | 83 + video/Makefile.am | 4 + video/Makefile.in | 299 ++ video/ggi_gr.c | 328 ++ video/ogl.c | 1325 +++++ video/ogl_glx.c | 243 + video/ogl_gr.c | 625 +++ video/ogl_wgl.c | 457 ++ video/sdl_gr.c | 452 ++ 697 files changed, 275705 insertions(+) create mode 100644 2d/2dsline.c create mode 100644 2d/Makefile.am create mode 100644 2d/Makefile.in create mode 100644 2d/bitblt.c create mode 100644 2d/bitmap.c create mode 100644 2d/bitmap.h create mode 100644 2d/box.c create mode 100644 2d/canvas.c create mode 100644 2d/circle.c create mode 100644 2d/clip.h create mode 100644 2d/diff create mode 100644 2d/disc.c create mode 100644 2d/font.c create mode 100644 2d/gpixel.c create mode 100644 2d/ibitblt.c create mode 100644 2d/line.c create mode 100644 2d/linear.asm create mode 100644 2d/linear.h create mode 100644 2d/palette.c create mode 100644 2d/pcx.c create mode 100644 2d/pixel.c create mode 100644 2d/poly.c create mode 100644 2d/rect.c create mode 100644 2d/rle.c create mode 100644 2d/scale.c create mode 100644 2d/scalea.asm create mode 100644 2d/scalea.h create mode 100644 2d/scalec.c create mode 100644 2d/tmerge.c create mode 100644 2d/tmerge_a.asm create mode 100644 3d/Makefile.am create mode 100644 3d/Makefile.in create mode 100644 3d/clipper.c create mode 100644 3d/clipper.h create mode 100644 3d/draw.c create mode 100644 3d/globvars.c create mode 100644 3d/globvars.h create mode 100644 3d/instance.c create mode 100644 3d/interp.asm create mode 100644 3d/interp.c create mode 100644 3d/matrix.c create mode 100644 3d/points.c create mode 100644 3d/rod.c create mode 100644 3d/setup.c create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 NEWS create mode 100644 README create mode 100644 aclocal.m4 create mode 100644 arch/Makefile.am create mode 100644 arch/Makefile.in create mode 100644 arch/dos/allg_snd/allg_snd.c create mode 100644 arch/dos/allg_snd/internal.h create mode 100644 arch/dos/allg_snd/sound/allegro.h create mode 100644 arch/dos/allg_snd/sound/config.c create mode 100644 arch/dos/allg_snd/sound/digmid.c create mode 100644 arch/dos/allg_snd/sound/drv/adlib.c create mode 100644 arch/dos/allg_snd/sound/drv/awedata.c create mode 100644 arch/dos/allg_snd/sound/drv/dma.c create mode 100644 arch/dos/allg_snd/sound/drv/emu8k.c create mode 100644 arch/dos/allg_snd/sound/drv/emu8k.h create mode 100644 arch/dos/allg_snd/sound/drv/emu8kmid.c create mode 100644 arch/dos/allg_snd/sound/drv/fm_instr.h create mode 100644 arch/dos/allg_snd/sound/drv/gus.c create mode 100644 arch/dos/allg_snd/sound/drv/mpu.c create mode 100644 arch/dos/allg_snd/sound/drv/sb.c create mode 100644 arch/dos/allg_snd/sound/interndj.h create mode 100644 arch/dos/allg_snd/sound/midi.c create mode 100644 arch/dos/allg_snd/sound/mixer.c create mode 100644 arch/dos/allg_snd/sound/readme.d1 create mode 100644 arch/dos/allg_snd/sound/readme.txt create mode 100644 arch/dos/allg_snd/sound/snddrv.c create mode 100644 arch/dos/allg_snd/sound/sound.c create mode 100644 arch/dos/bak/ipx.c create mode 100644 arch/dos/bcd.c create mode 100644 arch/dos/comm/commlib.c create mode 100644 arch/dos/comm/dzcomm.c create mode 100644 arch/dos/comm/dzqueue.c create mode 100644 arch/dos/comm/include/allegro.h create mode 100644 arch/dos/comm/include/asmdef.inc create mode 100644 arch/dos/comm/include/asmdefs.inc create mode 100644 arch/dos/comm/include/commlib.h create mode 100644 arch/dos/comm/include/internal.h create mode 100644 arch/dos/comm/irq.c create mode 100644 arch/dos/comm/irqwrap.S create mode 100644 arch/dos/digiallg.c create mode 100644 arch/dos/digimm.c create mode 100644 arch/dos/disk.c create mode 100644 arch/dos/dosgr.c create mode 100644 arch/dos/dpmi.c create mode 100644 arch/dos/include/commlib.h create mode 100644 arch/dos/include/disk.h create mode 100644 arch/dos/include/dzcomm.h create mode 100644 arch/dos/include/joy.h create mode 100644 arch/dos/include/key.h create mode 100644 arch/dos/include/midiallg.h create mode 100644 arch/dos/include/mouse.h create mode 100644 arch/dos/include/serial.h create mode 100644 arch/dos/init.c create mode 100644 arch/dos/ipx.c create mode 100644 arch/dos/ipx.h create mode 100644 arch/dos/joy2.asm create mode 100644 arch/dos/joyc.c create mode 100644 arch/dos/joydefs.c create mode 100644 arch/dos/key.c create mode 100644 arch/dos/midiallg.c create mode 100644 arch/dos/mm_snd/drv_sb.c create mode 100644 arch/dos/mm_snd/include/mdma.h create mode 100644 arch/dos/mm_snd/include/mikmod.h create mode 100644 arch/dos/mm_snd/include/mirq.h create mode 100644 arch/dos/mm_snd/include/mm_drv.h create mode 100644 arch/dos/mm_snd/include/mmio.h create mode 100644 arch/dos/mm_snd/include/mtypes.h create mode 100644 arch/dos/mm_snd/mdma.c create mode 100644 arch/dos/mm_snd/mirq.c create mode 100644 arch/dos/mm_snd/readme.txt create mode 100644 arch/dos/modex.asm create mode 100644 arch/dos/mono.c create mode 100644 arch/dos/mono.h create mode 100644 arch/dos/mouse.c create mode 100644 arch/dos/serial.c create mode 100644 arch/dos/sgrep.out create mode 100644 arch/dos/timer.asm create mode 100644 arch/dos/tweak.inc create mode 100644 arch/dos/vesa.c create mode 100644 arch/dos/vgaregs.inc create mode 100644 arch/linux/Makefile.am create mode 100644 arch/linux/Makefile.in create mode 100644 arch/linux/alsadigi.c create mode 100644 arch/linux/findfile.c create mode 100644 arch/linux/hmiplay.c create mode 100644 arch/linux/hmistub.c create mode 100644 arch/linux/include/ipx_bsd.h create mode 100644 arch/linux/include/ipx_drv.h create mode 100644 arch/linux/include/ipx_hlpr.h create mode 100644 arch/linux/include/ipx_kali.h create mode 100644 arch/linux/include/ipx_ld.h create mode 100644 arch/linux/include/ipx_lin.h create mode 100644 arch/linux/include/ipx_udp.h create mode 100644 arch/linux/include/music.h create mode 100644 arch/linux/include/serial.h create mode 100644 arch/linux/include/ukali.h create mode 100644 arch/linux/init.c create mode 100644 arch/linux/ipx_bsd.c create mode 100644 arch/linux/ipx_kali.c create mode 100644 arch/linux/ipx_lin.c create mode 100644 arch/linux/ipx_udp.c create mode 100644 arch/linux/linuxnet.c create mode 100644 arch/linux/mono.c create mode 100644 arch/linux/serial.c create mode 100644 arch/linux/stHqFIq1 create mode 100644 arch/linux/svgalib/event.c create mode 100644 arch/linux/svgalib/gr.c create mode 100644 arch/linux/svgalib/include/event.h create mode 100644 arch/linux/svgalib/include/key.h create mode 100644 arch/linux/svgalib/include/mouse.h create mode 100644 arch/linux/svgalib/init.c create mode 100644 arch/linux/svgalib/key.c create mode 100644 arch/linux/svgalib/mouse.c create mode 100644 arch/linux/timer.c create mode 100644 arch/linux/ukali.c create mode 100644 arch/ogl/include/loadgl.h create mode 100644 arch/ogl/include/ogl_init.h create mode 100644 arch/sdl/Makefile.am create mode 100644 arch/sdl/Makefile.in create mode 100644 arch/sdl/init.c create mode 100644 arch/sdl/timer.c create mode 100644 arch/win32/d1x.ico create mode 100644 arch/win32/d1x.rc create mode 100644 arch/win32/d3d.ico create mode 100644 arch/win32/d3dframe/d3denum.cpp create mode 100644 arch/win32/d3dframe/d3denum.h create mode 100644 arch/win32/d3dframe/d3dframe.cpp create mode 100644 arch/win32/d3dframe/d3dframe.h create mode 100644 arch/win32/d3dframe/d3dmath.cpp create mode 100644 arch/win32/d3dframe/d3dmath.h create mode 100644 arch/win32/d3dframe/d3dtextr.cpp create mode 100644 arch/win32/d3dframe/d3dtextr.h create mode 100644 arch/win32/d3dframe/d3dutil.cpp create mode 100644 arch/win32/d3dframe/d3dutil.h create mode 100644 arch/win32/d3dframe/ddenum.cpp create mode 100644 arch/win32/d3dframe/ddmm.h create mode 100644 arch/win32/d3dframe/ddutil.h create mode 100644 arch/win32/d3dframe/ddutil2.h create mode 100644 arch/win32/d3dframe/dsutil.h create mode 100644 arch/win32/d3dframe/lbprintf.h create mode 100644 arch/win32/d3dframe/resource.h create mode 100644 arch/win32/d3dframe/userdlg.cpp create mode 100644 arch/win32/debug.cpp create mode 100644 arch/win32/descent.ico create mode 100644 arch/win32/digi.c create mode 100644 arch/win32/glinit.c create mode 100644 arch/win32/gr.c create mode 100644 arch/win32/hmpfile.c create mode 100644 arch/win32/include/d3dhelp.h create mode 100644 arch/win32/include/debug.h create mode 100644 arch/win32/include/hmpfile.h create mode 100644 arch/win32/include/joy.h create mode 100644 arch/win32/include/key.h create mode 100644 arch/win32/include/mouse.h create mode 100644 arch/win32/include/pch.h create mode 100644 arch/win32/include/resource.h create mode 100644 arch/win32/include/scene.h create mode 100644 arch/win32/include/serial.h create mode 100644 arch/win32/include/texture.h create mode 100644 arch/win32/include/winmain.h create mode 100644 arch/win32/include/wsipx.h create mode 100644 arch/win32/init.c create mode 100644 arch/win32/ipx_drv.h create mode 100644 arch/win32/ipx_win.c create mode 100644 arch/win32/joydefs.c create mode 100644 arch/win32/joyhh.c create mode 100644 arch/win32/key.c create mode 100644 arch/win32/mono.c create mode 100644 arch/win32/mouse.c create mode 100644 arch/win32/palw32.c create mode 100644 arch/win32/pch.cpp create mode 100644 arch/win32/scene.cpp create mode 100644 arch/win32/serial.c create mode 100644 arch/win32/texture.cpp create mode 100644 arch/win32/timer.c create mode 100644 arch/win32/win32.c create mode 100644 arch/win32/winmain.cpp create mode 100644 arch/win32/winnet.c create mode 100644 autogen.sh create mode 100644 cfile/Makefile.am create mode 100644 cfile/Makefile.in create mode 100644 cfile/cfile.c create mode 100644 cfile/nocfile.h create mode 100644 conf.h.in create mode 100644 config.guess create mode 100644 config.sub create mode 100644 configure create mode 100644 configure.in create mode 100644 iff/Makefile.am create mode 100644 iff/Makefile.in create mode 100644 iff/archive/iff15bpp.c create mode 100644 iff/archive/iff8bpp.c create mode 100644 iff/archive/iffmike.c create mode 100644 iff/archive/ifftest.c create mode 100644 iff/archive/ifftestv.c create mode 100644 iff/iff.c create mode 100644 include/3d.h create mode 100644 include/args.h create mode 100644 include/byteswap.h create mode 100644 include/cfile.h create mode 100644 include/checker.h create mode 100644 include/cmd.h create mode 100644 include/console.h create mode 100644 include/d.bat create mode 100644 include/d_delay.h create mode 100644 include/d_io.h create mode 100644 include/dtypes.h create mode 100644 include/dtypes.inc create mode 100644 include/error.h create mode 100644 include/findfile.h create mode 100644 include/fix.h create mode 100644 include/gr.h create mode 100644 include/grdef.h create mode 100644 include/hash.h create mode 100644 include/ibitblt.h create mode 100644 include/iff.h create mode 100644 include/ipx.h create mode 100644 include/loadgl.h create mode 100644 include/lst.bat create mode 100644 include/m.bat create mode 100644 include/maths.h create mode 100644 include/modex.h create mode 100644 include/mono.h create mode 100644 include/ogl_init.h create mode 100644 include/pa_enabl.h create mode 100644 include/palette.h create mode 100644 include/pcx.h create mode 100644 include/psmacros.inc create mode 100644 include/pstypes.h create mode 100644 include/pstypes.inc create mode 100644 include/rle.h create mode 100644 include/strio.h create mode 100644 include/strutil.h create mode 100644 include/test.c create mode 100644 include/test.lnk create mode 100644 include/texmap.h create mode 100644 include/timer.h create mode 100644 include/u_dpmi.h create mode 100644 include/u_mem.h create mode 100644 include/vecmat.h create mode 100644 include/vesa.h create mode 100644 input/Makefile.am create mode 100644 input/Makefile.in create mode 100644 input/ggi/Makefile.am create mode 100644 input/ggi/Makefile.in create mode 100644 input/ggi/event.c create mode 100644 input/ggi/include/event.h create mode 100644 input/ggi/include/key.h create mode 100644 input/ggi/include/mouse.h create mode 100644 input/ggi/init.c create mode 100644 input/ggi/key.c create mode 100644 input/ggi/mouse.c create mode 100644 input/linux/Makefile.am create mode 100644 input/linux/Makefile.in create mode 100644 input/linux/include/joy.h create mode 100644 input/linux/include/joystick.h create mode 100644 input/linux/joydefs.c create mode 100644 input/linux/joystick.c create mode 100644 input/sdl/Makefile.am create mode 100644 input/sdl/Makefile.in create mode 100644 input/sdl/event.c create mode 100644 input/sdl/include/event.h create mode 100644 input/sdl/include/key.h create mode 100644 input/sdl/include/mouse.h create mode 100644 input/sdl/key.c create mode 100644 input/sdl/mouse.c create mode 100644 install-sh create mode 100644 libtool create mode 100644 ltconfig create mode 100644 ltmain.sh create mode 100644 main/Makefile.am create mode 100644 main/Makefile.in create mode 100644 main/ai.c create mode 100644 main/ai.h create mode 100644 main/ai2.c create mode 100644 main/aipath.c create mode 100644 main/aistruct.h create mode 100644 main/automap.c create mode 100644 main/automap.h create mode 100644 main/bm.c create mode 100644 main/bm.h create mode 100644 main/bmread.c create mode 100644 main/bmread.h create mode 100644 main/cdrom.h create mode 100644 main/cmd.c create mode 100644 main/cntrlcen.c create mode 100644 main/cntrlcen.h create mode 100644 main/collide.c create mode 100644 main/collide.h create mode 100644 main/compbit.h create mode 100644 main/config.c create mode 100644 main/config.h create mode 100644 main/console.c create mode 100644 main/controls.c create mode 100644 main/controls.h create mode 100644 main/credits.c create mode 100644 main/credits.h create mode 100644 main/crypt.c create mode 100644 main/desc_id.h create mode 100644 main/descent.cfg create mode 100644 main/desw.h create mode 100644 main/digi.h create mode 100644 main/dumpmine.c create mode 100644 main/editor/editor.h create mode 100644 main/editor/kdefs.h create mode 100644 main/editor/texpage.h create mode 100644 main/effects.c create mode 100644 main/effects.h create mode 100644 main/endlevel.c create mode 100644 main/endlevel.h create mode 100644 main/escort.c create mode 100644 main/fireball.c create mode 100644 main/fireball.h create mode 100644 main/fuelcen.c create mode 100644 main/fuelcen.h create mode 100644 main/fvi.c create mode 100644 main/fvi.h create mode 100644 main/fvi_a.h create mode 100644 main/game.c create mode 100644 main/game.h create mode 100644 main/gamecntl.c create mode 100644 main/gamefont.c create mode 100644 main/gamefont.h create mode 100644 main/gamemine.c create mode 100644 main/gamemine.h create mode 100644 main/gamepal.c create mode 100644 main/gamepal.h create mode 100644 main/gamerend.c create mode 100644 main/gamesave.c create mode 100644 main/gamesave.h create mode 100644 main/gameseg.c create mode 100644 main/gameseg.h create mode 100644 main/gameseq.c create mode 100644 main/gameseq.h create mode 100644 main/gamestat.h create mode 100644 main/gauges.c create mode 100644 main/gauges.h create mode 100644 main/hostage.c create mode 100644 main/hostage.h create mode 100644 main/hud.c create mode 100644 main/inferno.c create mode 100644 main/inferno.h create mode 100644 main/inferno.ini create mode 100644 main/joydefs.h create mode 100644 main/kconfig.c create mode 100644 main/kconfig.h create mode 100644 main/kludge.c create mode 100644 main/kmatrix.c create mode 100644 main/kmatrix.h create mode 100644 main/laser.c create mode 100644 main/laser.h create mode 100644 main/lighting.c create mode 100644 main/lighting.h create mode 100644 main/menu.c create mode 100644 main/menu.h create mode 100644 main/mglobal.c create mode 100644 main/mission.c create mode 100644 main/mission.h create mode 100644 main/modem.h create mode 100644 main/morph.c create mode 100644 main/morph.h create mode 100644 main/movie.h create mode 100644 main/multi.c create mode 100644 main/multi.h create mode 100644 main/multibot.c create mode 100644 main/multibot.h create mode 100644 main/netmisc.c create mode 100644 main/netmisc.h create mode 100644 main/network.c create mode 100644 main/network.h create mode 100644 main/newdemo.c create mode 100644 main/newdemo.h create mode 100644 main/newmenu.c create mode 100644 main/newmenu.h create mode 100644 main/object.c create mode 100644 main/object.h create mode 100644 main/old/3dfx.c create mode 100644 main/old/3dfx_des.h create mode 100644 main/old/arcade.h create mode 100644 main/old/cdmix32.c create mode 100644 main/old/cdrom.c create mode 100644 main/old/coindev.c create mode 100644 main/old/coindev.h create mode 100644 main/old/descentw.c create mode 100644 main/old/digiobj.c create mode 100644 main/old/files.h create mode 100644 main/old/iglasses.c create mode 100644 main/old/iglasses.h create mode 100644 main/old/joydefs.c create mode 100644 main/old/joydefsw.c create mode 100644 main/old/modem.c create mode 100644 main/old/movie.c create mode 100644 main/old/newmodel.c create mode 100644 main/old/rbtest.c create mode 100644 main/old/settings.h create mode 100644 main/old/terrain.c create mode 100644 main/old/windigi.c create mode 100644 main/old/winferno.c create mode 100644 main/old/winmodem.c create mode 100644 main/old/winvideo.c create mode 100644 main/paging.c create mode 100644 main/paging.h create mode 100644 main/physics.c create mode 100644 main/physics.h create mode 100644 main/piggy.c create mode 100644 main/piggy.h create mode 100644 main/player.h create mode 100644 main/playsave.c create mode 100644 main/playsave.h create mode 100644 main/polyobj.c create mode 100644 main/polyobj.h create mode 100644 main/powerup.c create mode 100644 main/powerup.h create mode 100644 main/render.c create mode 100644 main/render.h create mode 100644 main/robot.c create mode 100644 main/robot.h create mode 100644 main/scores.c create mode 100644 main/scores.h create mode 100644 main/screens.h create mode 100644 main/segment.h create mode 100644 main/segpoint.h create mode 100644 main/slew.c create mode 100644 main/slew.h create mode 100644 main/songs.c create mode 100644 main/songs.h create mode 100644 main/sounds.h create mode 100644 main/state.c create mode 100644 main/state.h create mode 100644 main/switch.c create mode 100644 main/switch.h create mode 100644 main/terrain.h create mode 100644 main/test.txt create mode 100644 main/texmerge.c create mode 100644 main/texmerge.h create mode 100644 main/text.c create mode 100644 main/text.h create mode 100644 main/textures.h create mode 100644 main/titles.c create mode 100644 main/titles.h create mode 100644 main/vclip.c create mode 100644 main/vclip.h create mode 100644 main/vers_id.h create mode 100644 main/wall.c create mode 100644 main/wall.h create mode 100644 main/weapon.c create mode 100644 main/weapon.h create mode 100644 maths/Makefile.am create mode 100644 maths/Makefile.in create mode 100644 maths/fix.asm create mode 100644 maths/fixc.c create mode 100644 maths/rand.c create mode 100644 maths/tables.c create mode 100644 maths/vecmat.c create mode 100644 maths/vecmata.asm create mode 100644 mem/Makefile.am create mode 100644 mem/Makefile.in create mode 100644 mem/mem.c create mode 100644 misc/Makefile.am create mode 100644 misc/Makefile.in create mode 100644 misc/args.c create mode 100644 misc/byteswap.c create mode 100644 misc/byteswap.h create mode 100644 misc/d_delay.c create mode 100644 misc/d_glob.c create mode 100644 misc/d_io.c create mode 100644 misc/error.c create mode 100644 misc/errtest.c create mode 100644 misc/fileutil.c create mode 100644 misc/fileutil.h create mode 100644 misc/hash.c create mode 100644 misc/parsarg.c create mode 100644 misc/parsarg.h create mode 100644 misc/parstest.c create mode 100644 misc/strio.c create mode 100644 misc/strutil.c create mode 100644 missing create mode 100644 mkinstalldirs create mode 100644 readme.txt create mode 100644 sound/Makefile.am create mode 100644 sound/Makefile.in create mode 100644 sound/sdl_cdrom.c create mode 100644 sound/sdl_digi.c create mode 100644 stamp-h.in create mode 100644 texmap/Makefile.am create mode 100644 texmap/Makefile.in create mode 100644 texmap/ntmap.c create mode 100644 texmap/scanline.c create mode 100644 texmap/scanline.h create mode 100644 texmap/texmapl.h create mode 100644 texmap/tmap_flt.asm create mode 100644 texmap/tmap_inc.asm create mode 100644 texmap/tmap_lin.asm create mode 100644 texmap/tmap_ll.asm create mode 100644 texmap/tmap_per.asm create mode 100644 texmap/tmapfade.asm create mode 100644 texmap/tmapflat.c create mode 100644 texmap/tmappent.S create mode 100644 texmap/tmapppro.S create mode 100644 thinking.txt create mode 100644 unused/bios/d.bat create mode 100644 unused/bios/dd.bat create mode 100644 unused/bios/dpmi.c create mode 100644 unused/bios/dpmi.h create mode 100644 unused/bios/error.c create mode 100644 unused/bios/error.h create mode 100644 unused/bios/findfile.c create mode 100644 unused/bios/findfile.h create mode 100644 unused/bios/ipx.c create mode 100644 unused/bios/ipx.h create mode 100644 unused/bios/joy.asm create mode 100644 unused/bios/joy.h create mode 100644 unused/bios/joyc.c create mode 100644 unused/bios/key.asm create mode 100644 unused/bios/key.c create mode 100644 unused/bios/key.h create mode 100644 unused/bios/keys.inc create mode 100644 unused/bios/make0000.bat create mode 100644 unused/bios/make0001.bat create mode 100644 unused/bios/make0100.bat create mode 100644 unused/bios/mono.c create mode 100644 unused/bios/mouse.asm create mode 100644 unused/bios/mouse.c create mode 100644 unused/bios/mouse.h create mode 100644 unused/bios/oldkey.asm create mode 100644 unused/bios/rbaudio.c create mode 100644 unused/bios/rbaudio.h create mode 100644 unused/bios/rbaudio.new create mode 100644 unused/bios/speaker.c create mode 100644 unused/bios/swiftcfg.h create mode 100644 unused/bios/testj.c create mode 100644 unused/bios/testk.c create mode 100644 unused/bios/testk.lnk create mode 100644 unused/bios/testm.c create mode 100644 unused/bios/testm.lnk create mode 100644 unused/bios/testms.c create mode 100644 unused/bios/testt.c create mode 100644 unused/bios/timer.asm create mode 100644 unused/bios/timer.h create mode 100644 unused/bios/timerp.c create mode 100644 unused/bios/x create mode 100644 unused/bios/x.bat create mode 100644 unused/bios/x.c create mode 100644 unused/bios/y.bat create mode 100644 unused/lib/fix.h create mode 100644 unused/lib/rbaudio.h create mode 100644 unused/novga/files.rc create mode 100644 unused/novga/novesa.c create mode 100644 unused/pa_null/pa_enabl.h create mode 100644 unused/pa_null/poly_acc.c create mode 100644 unused/pa_null/poly_acc.h create mode 100644 unused/readme.txt create mode 100644 unused/ui/barbox.c create mode 100644 unused/ui/button.c create mode 100644 unused/ui/checkbox.c create mode 100644 unused/ui/file.c create mode 100644 unused/ui/func.c create mode 100644 unused/ui/func.h create mode 100644 unused/ui/gadget.c create mode 100644 unused/ui/harderr.c create mode 100644 unused/ui/icon.c create mode 100644 unused/ui/inputbox.c create mode 100644 unused/ui/keypad.c create mode 100644 unused/ui/keypress.c create mode 100644 unused/ui/keytrap.c create mode 100644 unused/ui/listbox.c create mode 100644 unused/ui/medfunc.c create mode 100644 unused/ui/menu.c create mode 100644 unused/ui/menubar.c create mode 100644 unused/ui/message.c create mode 100644 unused/ui/mouse.c create mode 100644 unused/ui/number.c create mode 100644 unused/ui/popup.c create mode 100644 unused/ui/radio.c create mode 100644 unused/ui/scroll.c create mode 100644 unused/ui/ui.c create mode 100644 unused/ui/ui.h create mode 100644 unused/ui/uidraw.c create mode 100644 unused/ui/userbox.c create mode 100644 unused/ui/window.c create mode 100644 unused/vga/dd.bat create mode 100644 unused/vga/framebuf.c create mode 100644 unused/vga/framebuf.jas create mode 100644 unused/vga/fxdpmi.h create mode 100644 unused/vga/fxvesa.h create mode 100644 unused/vga/grx.h create mode 100644 unused/vga/modex.asm create mode 100644 unused/vga/new/palette.c create mode 100644 unused/vga/new/vga.c create mode 100644 unused/vga/palette.c create mode 100644 unused/vga/tweak.inc create mode 100644 unused/vga/vesa.asm create mode 100644 unused/vga/vga.c create mode 100644 unused/vga/vga.h create mode 100644 unused/vga/vga.jas create mode 100644 unused/vga/vgaregs.inc create mode 100644 unused/vga/xyz.bat create mode 100644 unused/win95/comm.c create mode 100644 unused/win95/comm.h create mode 100644 unused/win95/dd.bat create mode 100644 unused/win95/dd.c create mode 100644 unused/win95/dd.h create mode 100644 unused/win95/ddgfx.c create mode 100644 unused/win95/ddgr.c create mode 100644 unused/win95/ddraw.c create mode 100644 unused/win95/direct3d.c create mode 100644 unused/win95/direct3d.h create mode 100644 unused/win95/ds.c create mode 100644 unused/win95/ds.h create mode 100644 unused/win95/error.c create mode 100644 unused/win95/error.h create mode 100644 unused/win95/findfile.c create mode 100644 unused/win95/gfx.c create mode 100644 unused/win95/global.h create mode 100644 unused/win95/iforce.c create mode 100644 unused/win95/iforce.h create mode 100644 unused/win95/ipx.c create mode 100644 unused/win95/joyc.c create mode 100644 unused/win95/key.c create mode 100644 unused/win95/midifile.h create mode 100644 unused/win95/midiseq.h create mode 100644 unused/win95/mono.c create mode 100644 unused/win95/mouse.c create mode 100644 unused/win95/palette.c create mode 100644 unused/win95/rbaudio.c create mode 100644 unused/win95/swift.c create mode 100644 unused/win95/tactile.c create mode 100644 unused/win95/tactile.h create mode 100644 unused/win95/timer.c create mode 100644 unused/win95/winapp.c create mode 100644 unused/win95/winapp.h create mode 100644 unused/win95/winckpit.asm create mode 100644 unused/win95/winmidi.c create mode 100644 unused/win95/winmidi.h create mode 100644 unused/win95/winmono.c create mode 100644 unused/win95/winregs.c create mode 100644 unused/win95/winregs.h create mode 100644 unused/win95/xtapi.c create mode 100644 unused/win95/xtapi.h create mode 100644 video/Makefile.am create mode 100644 video/Makefile.in create mode 100644 video/ggi_gr.c create mode 100644 video/ogl.c create mode 100644 video/ogl_glx.c create mode 100644 video/ogl_gr.c create mode 100644 video/ogl_wgl.c create mode 100644 video/sdl_gr.c diff --git a/2d/2dsline.c b/2d/2dsline.c new file mode 100644 index 00000000..6e28cfd8 --- /dev/null +++ b/2d/2dsline.c @@ -0,0 +1,184 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#include +#include + +#include "u_mem.h" + +#include "gr.h" +#include "grdef.h" + +#ifdef __MSDOS__ +#include "modex.h" +#include "vesa.h" +#endif + +int Gr_scanline_darkening_level = GR_FADE_LEVELS; + +#ifndef NO_ASM +# ifdef __WATCOMC__ +void gr_linear_darken( ubyte * dest, int darkening_level, int count, ubyte * fade_table ); +# pragma aux gr_linear_darken parm [edi] [eax] [ecx] [edx] modify exact [eax ebx ecx edx edi] = \ +" xor ebx, ebx " \ +" mov bh, al " \ +"gld_loop: mov bl, [edi] " \ +" mov al, [ebx+edx] " \ +" mov [edi], al " \ +" inc edi " \ +" dec ecx " \ +" jnz gld_loop " + +# elif defined __GNUC__ +static inline void gr_linear_darken( ubyte * dest, int darkening_level, int count, ubyte * fade_table ) { + int dummy[4]; + __asm__ __volatile__ ( +" xorl %%ebx, %%ebx;" +" movb %%al, %%bh;" +"0: movb (%%edi), %%bl;" +" movb (%%ebx, %%edx), %%al;" +" movb %%al, (%%edi);" +" incl %%edi;" +" decl %%ecx;" +" jnz 0b" + : "=D" (dummy[0]), "=a" (dummy[1]), "=c" (dummy[2]), "=d" (dummy[3]) + : "0" (dest), "1" (darkening_level), "2" (count), "3" (fade_table) + : "%ebx"); +} +# elif defined _MSC_VER +__inline void gr_linear_darken( ubyte * dest, int darkening_level, int count, ubyte * fade_table ) +{ + __asm { + mov edi,[dest] + mov eax,[darkening_level] + mov ecx,[count] + mov edx,[fade_table] + xor ebx, ebx + mov bh, al +gld_loop: + mov bl,[edi] + mov al,[ebx+edx] + mov [edi],al + inc edi + dec ecx + jnz gld_loop + } +} +# else +// Unknown compiler. So we use C rather than inline assembler. +# define USE_C_GR_LINEAR_DARKEN 1 +# endif + +#else // No Assembler. So we use C. +# define USE_C_GR_LINEAR_DARKEN 1 +void gr_linear_stosd( ubyte * dest, unsigned char color, unsigned int nbytes) { + memset(dest,color,nbytes); +} +#endif + +#ifdef USE_C_GR_LINEAR_DARKEN +void gr_linear_darken(ubyte * dest, int darkening_level, int count, ubyte * fade_table) { + register int i; + + for (i=0;i= GR_FADE_LEVELS ) { +#ifdef __MSDOS__ + switch(TYPE) + { + case BM_LINEAR: +#endif + gr_linear_stosd( DATA + ROWSIZE*y + x1, (unsigned char)COLOR, x2-x1+1); +#ifdef __MSDOS__ + break; + case BM_MODEX: + gr_modex_uscanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR ); + break; + case BM_SVGA: + gr_vesa_scanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR ); + break; + } +#endif + } else { +#ifdef __MSDOS__ + switch(TYPE) + { + case BM_LINEAR: +#endif + gr_linear_darken( DATA + ROWSIZE*y + x1, Gr_scanline_darkening_level, x2-x1+1, gr_fade_table); +#ifdef __MSDOS__ + break; + case BM_MODEX: + gr_modex_uscanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR ); + break; + case BM_SVGA: + gr_vesa_scanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR ); + break; + } +#endif + } +} + +void gr_scanline( int x1, int x2, int y ) +{ + if ((y<0)||(y>MAXY)) return; + + if (x2 < x1 ) x2 ^= x1 ^= x2; + + if (x1 > MAXX) return; + if (x2 < MINX) return; + + if (x1 < MINX) x1 = MINX; + if (x2 > MAXX) x2 = MAXX; + + if (Gr_scanline_darkening_level >= GR_FADE_LEVELS ) { +#ifdef __MSDOS__ + switch(TYPE) + { + case BM_LINEAR: +#endif + gr_linear_stosd( DATA + ROWSIZE*y + x1, (unsigned char)COLOR, x2-x1+1); +#ifdef __MSDOS__ + break; + case BM_MODEX: + gr_modex_uscanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR ); + break; + case BM_SVGA: + gr_vesa_scanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR ); + break; + } +#endif + } else { +#ifdef __MSDOS__ + switch(TYPE) + { + case BM_LINEAR: +#endif + gr_linear_darken( DATA + ROWSIZE*y + x1, Gr_scanline_darkening_level, x2-x1+1, gr_fade_table); +#ifdef __MSDOS__ + break; + case BM_MODEX: + gr_modex_uscanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR ); + break; + case BM_SVGA: + gr_vesa_scanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR ); + break; + } +#endif + } +} diff --git a/2d/Makefile.am b/2d/Makefile.am new file mode 100644 index 00000000..3629b8fa --- /dev/null +++ b/2d/Makefile.am @@ -0,0 +1,18 @@ +noinst_LIBRARIES = lib2d.a +INCLUDES = -I $(top_srcdir)/includes + +lib2d_a_SOURCES = \ +2dsline.c box.c disc.c ibitblt.c pcx.c rect.c scalec.c \ +bitblt.c canvas.c font.c line.c pixel.c rle.c tmerge.c \ +bitmap.c circle.c gpixel.c palette.c poly.c + +if USE_ASM + SUFFIXES = .asm + %.o: %.asm + $(NASM) $(NASMFLAGS) $< -o $@ + + lib2d_a_SOURCES += linear.asm tmerge_a.asm + lib2d_a_LIBADD += linear.o tmerge_a.o + 2dsline.c: linear.o tmerge_a.o +endif + diff --git a/2d/Makefile.in b/2d/Makefile.in new file mode 100644 index 00000000..e3502c2a --- /dev/null +++ b/2d/Makefile.in @@ -0,0 +1,313 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +CFLAGS = @CFLAGS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +NASM = @NASM@ +NASMFLAGS = @NASMFLAGS@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_LIBS = @SDL_LIBS@ +VERSION = @VERSION@ + +noinst_LIBRARIES = lib2d.a +INCLUDES = -I $(top_srcdir)/includes + +lib2d_a_SOURCES = 2dsline.c box.c disc.c ibitblt.c pcx.c rect.c scalec.c bitblt.c canvas.c font.c line.c pixel.c rle.c tmerge.c bitmap.c circle.c gpixel.c palette.c poly.c + +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../conf.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +lib2d_a_LIBADD = +lib2d_a_OBJECTS = 2dsline.o box.o disc.o ibitblt.o pcx.o rect.o \ +scalec.o bitblt.o canvas.o font.o line.o pixel.o rle.o tmerge.o \ +bitmap.o circle.o gpixel.o palette.o poly.o +AR = ar +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +DEP_FILES = .deps/2dsline.P .deps/bitblt.P .deps/bitmap.P .deps/box.P \ +.deps/canvas.P .deps/circle.P .deps/disc.P .deps/font.P .deps/gpixel.P \ +.deps/ibitblt.P .deps/line.P .deps/palette.P .deps/pcx.P .deps/pixel.P \ +.deps/poly.P .deps/rect.P .deps/rle.P .deps/scalec.P .deps/tmerge.P +SOURCES = $(lib2d_a_SOURCES) +OBJECTS = $(lib2d_a_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu 2d/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +lib2d.a: $(lib2d_a_OBJECTS) $(lib2d_a_DEPENDENCIES) + -rm -f lib2d.a + $(AR) cru lib2d.a $(lib2d_a_OBJECTS) $(lib2d_a_LIBADD) + $(RANLIB) lib2d.a + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = 2d + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu 2d/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile $(LIBRARIES) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ + mostlyclean-tags mostlyclean-depend mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \ + clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-noinstLIBRARIES distclean-compile \ + distclean-tags distclean-depend distclean-generic \ + clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +@USE_ASM_TRUE@ SUFFIXES = .asm +@USE_ASM_TRUE@ %.o: %.asm +@USE_ASM_TRUE@ $(NASM) $(NASMFLAGS) $< -o $@ + +@USE_ASM_TRUE@ lib2d_a_SOURCES += linear.asm tmerge_a.asm +@USE_ASM_TRUE@ lib2d_a_LIBADD += linear.o tmerge_a.o +@USE_ASM_TRUE@ 2dsline.c: linear.o tmerge_a.o + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/2d/bitblt.c b/2d/bitblt.c new file mode 100644 index 00000000..40177b0b --- /dev/null +++ b/2d/bitblt.c @@ -0,0 +1,954 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#include +#include +#include "u_mem.h" +#include "gr.h" +#include "grdef.h" +#include "rle.h" +#include "error.h" + +#ifdef OGL +#include "ogl_init.h" +#endif + +int gr_bitblt_dest_step_shift = 0; +int gr_bitblt_double = 0; +ubyte *gr_bitblt_fade_table=NULL; + +void gr_bm_ubitblt00_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); +void gr_bm_ubitblt00m_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); +void gr_bm_ubitblt0x_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest, int masked); + +void gr_bm_ubitblt01(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); +void gr_bm_ubitblt02(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); + +#include "linear.h" +#include "modex.h" +#include "vesa.h" + +#ifdef NO_ASM +void gr_linear_movsd( ubyte * source, ubyte * dest, unsigned int nbytes) { + memcpy(dest,source,nbytes); +} + +void gr_linear_rep_movsdm(ubyte *src, ubyte *dest, int num_pixels) { + register ubyte c; + while (num_pixels--) + if ((c=*src++)!=255) + *dest++=c; + else dest++; +} + +void gr_linear_rep_movsdm_faded(ubyte * src, ubyte * dest, int num_pixels, ubyte fade_value ) { + register ubyte c; + while (num_pixels--) + if ((c=*src++)!=255) + *dest++=gr_fade_table[((int)fade_value<<8)|(int)c]; + else dest++; +} +void gr_linear_rep_movsd_2x(ubyte * source, ubyte * dest, uint nbytes ) { + register ubyte c; + while (nbytes--) { + if (nbytes&1) + *dest++=*source++; + else { + c=*source++; + *((unsigned short *)dest)++=((short)c<<8)|(short)c; + } + } +} +#endif +#ifdef D1XD3D +#include "d3dhelp.h" +#endif + +void gr_ubitmap00( int x, int y, grs_bitmap *bm ) +{ + register int y1; + int dest_rowsize; + + unsigned char * dest; + unsigned char * src; + + dest_rowsize=grd_curcanv->cv_bitmap.bm_rowsize << gr_bitblt_dest_step_shift; + dest = &(grd_curcanv->cv_bitmap.bm_data[ dest_rowsize*y+x ]); + + src = bm->bm_data; + + for (y1=0; y1 < bm->bm_h; y1++ ) { + if (gr_bitblt_double) + gr_linear_rep_movsd_2x( src, dest, bm->bm_w ); + else + gr_linear_movsd( src, dest, bm->bm_w ); + src += bm->bm_rowsize; + dest+= (int)(dest_rowsize); + } +} + +void gr_ubitmap00m( int x, int y, grs_bitmap *bm ) +{ + register int y1; + int dest_rowsize; + + unsigned char * dest; + unsigned char * src; + + dest_rowsize=grd_curcanv->cv_bitmap.bm_rowsize << gr_bitblt_dest_step_shift; + dest = &(grd_curcanv->cv_bitmap.bm_data[ dest_rowsize*y+x ]); + + src = bm->bm_data; + + if (gr_bitblt_fade_table==NULL) { + for (y1=0; y1 < bm->bm_h; y1++ ) { + gr_linear_rep_movsdm( src, dest, bm->bm_w ); + src += bm->bm_rowsize; + dest+= (int)(dest_rowsize); + } + } else { + for (y1=0; y1 < bm->bm_h; y1++ ) { + gr_linear_rep_movsdm_faded( src, dest, bm->bm_w, gr_bitblt_fade_table[y1+y] ); + src += bm->bm_rowsize; + dest+= (int)(dest_rowsize); + } + } +} + +//" jmp aligned4 " +//" mov eax, edi " +//" and eax, 11b " +//" jz aligned4 " +//" mov ebx, 4 " +//" sub ebx, eax " +//" sub ecx, ebx " +//"alignstart: " +//" mov al, [esi] " +//" add esi, 4 " +//" mov [edi], al " +//" inc edi " +//" dec ebx " +//" jne alignstart " +//"aligned4: " + +#ifdef __MSDOS__ +// From Linear to ModeX +void gr_bm_ubitblt01(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) +{ + ubyte * dbits; + ubyte * sbits; + int sstep,dstep; + int y,plane; + int w1; + + if ( w < 4 ) return; + + sstep = src->bm_rowsize; + dstep = dest->bm_rowsize << gr_bitblt_dest_step_shift; + + if (!gr_bitblt_double) { + for (plane=0; plane<4; plane++ ) { + gr_modex_setplane( (plane+dx)&3 ); + sbits = src->bm_data + (src->bm_rowsize * sy) + sx + plane; + dbits = &gr_video_memory[(dest->bm_rowsize * dy) + ((plane+dx)/4) ]; + w1 = w >> 2; + if ( (w&3) > plane ) w1++; + for (y=dy; y < dy+h; y++ ) { + modex_copy_scanline( sbits, dbits, w1 ); + dbits += dstep; + sbits += sstep; + } + } + } else { + for (plane=0; plane<4; plane++ ) { + gr_modex_setplane( (plane+dx)&3 ); + sbits = src->bm_data + (src->bm_rowsize * sy) + sx + plane/2; + dbits = &gr_video_memory[(dest->bm_rowsize * dy) + ((plane+dx)/4) ]; + w1 = w >> 2; + if ( (w&3) > plane ) w1++; + for (y=dy; y < dy+h; y++ ) { + modex_copy_scanline_2x( sbits, dbits, w1 ); + dbits += dstep; + sbits += sstep; + } + } + } +} + + +// From Linear to ModeX masked +void gr_bm_ubitblt01m(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) +{ + //ubyte * dbits1; + //ubyte * sbits1; + + ubyte * dbits; + ubyte * sbits; + + int x; +// int y; + + sbits = src->bm_data + (src->bm_rowsize * sy) + sx; + dbits = &gr_video_memory[(dest->bm_rowsize * dy) + dx/4]; + + for (x=dx; x < dx+w; x++ ) { + gr_modex_setplane( x&3 ); + + //sbits1 = sbits; + //dbits1 = dbits; + //for (y=0; y < h; y++ ) { + // *dbits1 = *sbits1; + // sbits1 += src_bm_rowsize; + // dbits1 += dest_bm_rowsize; + // } + modex_copy_column_m(sbits, dbits, h, src->bm_rowsize, dest->bm_rowsize << gr_bitblt_dest_step_shift ); + + sbits++; + if ( (x&3)==3 ) + dbits++; + } +} + +#endif + + +void gr_ubitmap012( int x, int y, grs_bitmap *bm ) +{ + register int x1, y1; + unsigned char * src; + + src = bm->bm_data; + + for (y1=y; y1 < (y+bm->bm_h); y1++ ) { + for (x1=x; x1 < (x+bm->bm_w); x1++ ) { + gr_setcolor( *src++ ); + gr_upixel( x1, y1 ); + } + } +} + +void gr_ubitmap012m( int x, int y, grs_bitmap *bm ) +{ + register int x1, y1; + unsigned char * src; + + src = bm->bm_data; + + for (y1=y; y1 < (y+bm->bm_h); y1++ ) { + for (x1=x; x1 < (x+bm->bm_w); x1++ ) { + if ( *src != 255 ) { + gr_setcolor( *src ); + gr_upixel( x1, y1 ); + } + src++; + } + } +} + + +void gr_ubitmapGENERIC(int x, int y, grs_bitmap * bm) +{ + register int x1, y1; + + for (y1=0; y1 < bm->bm_h; y1++ ) { + for (x1=0; x1 < bm->bm_w; x1++ ) { + gr_setcolor( gr_gpixel(bm,x1,y1) ); + gr_upixel( x+x1, y+y1 ); + } + } +} + +void gr_ubitmapGENERICm(int x, int y, grs_bitmap * bm) +{ + register int x1, y1; + ubyte c; + + for (y1=0; y1 < bm->bm_h; y1++ ) { + for (x1=0; x1 < bm->bm_w; x1++ ) { + c = gr_gpixel(bm,x1,y1); + if ( c != 255 ) { + gr_setcolor( c ); + gr_upixel( x+x1, y+y1 ); + } + } + } +} + +void gr_ubitmap( int x, int y, grs_bitmap *bm ) +{ int source, dest; + + source = bm->bm_type; + dest = TYPE; + + if (source==BM_LINEAR) { + switch( dest ) + { + case BM_LINEAR: + if ( bm->bm_flags & BM_FLAG_RLE ) + gr_bm_ubitblt00_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap ); + else + gr_ubitmap00( x, y, bm ); + return; +#ifdef OGL + case BM_OGL: + ogl_ubitmapm(x,y,bm); + return; +#endif +#ifdef D1XD3D + case BM_DIRECTX: + Assert ((int)grd_curcanv->cv_bitmap.bm_data == BM_D3D_RENDER || (int)grd_curcanv->cv_bitmap.bm_data == BM_D3D_DISPLAY); + Win32_BlitLinearToDirectX_bm(bm, 0, 0, bm->bm_w, bm->bm_h, x, y, 0); + return; +#endif +#ifdef __MSDOS__ + case BM_SVGA: + if ( bm->bm_flags & BM_FLAG_RLE ) + gr_bm_ubitblt0x_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap, 0 ); + else + gr_bm_ubitblt02( bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap); + return; + case BM_MODEX: + gr_bm_ubitblt01(bm->bm_w, bm->bm_h, x+XOFFSET, y+YOFFSET, 0, 0, bm, &grd_curcanv->cv_bitmap); + return; +#endif + default: + gr_ubitmap012( x, y, bm ); + return; + } + } else { + gr_ubitmapGENERIC(x, y, bm); + } +} + +void gr_ubitmapm( int x, int y, grs_bitmap *bm ) +{ int source, dest; + + + source = bm->bm_type; + dest = TYPE; + + if (source==BM_LINEAR) { + switch( dest ) + { + case BM_LINEAR: + if ( bm->bm_flags & BM_FLAG_RLE ) + gr_bm_ubitblt00m_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap ); + else + gr_ubitmap00m( x, y, bm ); + return; +#ifdef OGL + case BM_OGL: + ogl_ubitmapm(x,y,bm); + return; +#endif +#ifdef D1XD3D + case BM_DIRECTX: + if (bm->bm_w < 35 && bm->bm_h < 35) { + // ugly hack needed for reticle + if ( bm->bm_flags & BM_FLAG_RLE ) + gr_bm_ubitblt0x_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap, 1 ); + else + gr_ubitmapGENERICm(x, y, bm); + return; + } + Assert ((int)grd_curcanv->cv_bitmap.bm_data == BM_D3D_RENDER || (int)grd_curcanv->cv_bitmap.bm_data == BM_D3D_DISPLAY); + Win32_BlitLinearToDirectX_bm(bm, 0, 0, bm->bm_w, bm->bm_h, x, y, 1); + return; +#endif +#ifdef __MSDOS__ + case BM_SVGA: + gr_ubitmapGENERICm(x, y, bm); + return; + case BM_MODEX: + gr_bm_ubitblt01m(bm->bm_w, bm->bm_h, x+XOFFSET, y+YOFFSET, 0, 0, bm, &grd_curcanv->cv_bitmap); + return; +#endif + default: + gr_ubitmap012m( x, y, bm ); + return; + } + } else { + gr_ubitmapGENERICm(x, y, bm); + } +} + + +#ifdef __MSDOS__ +// From linear to SVGA +void gr_bm_ubitblt02(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) +{ + unsigned char * sbits; + + unsigned int offset, EndingOffset, VideoLocation; + + int sbpr, dbpr, y1, page, BytesToMove; + + sbpr = src->bm_rowsize; + + dbpr = dest->bm_rowsize << gr_bitblt_dest_step_shift; + + VideoLocation = (unsigned int)dest->bm_data + (dest->bm_rowsize * dy) + dx; + + sbits = src->bm_data + ( sbpr*sy ) + sx; + + for (y1=0; y1 < h; y1++ ) { + + page = VideoLocation >> 16; + offset = VideoLocation & 0xFFFF; + + gr_vesa_setpage( page ); + + EndingOffset = offset+w-1; + + if ( EndingOffset <= 0xFFFF ) + { + if ( gr_bitblt_double ) + gr_linear_rep_movsd_2x( (void *)sbits, (void *)(offset+gr_video_memory), w ); + else + gr_linear_movsd( (void *)sbits, (void *)(offset+gr_video_memory), w ); + + VideoLocation += dbpr; + sbits += sbpr; + } + else + { + BytesToMove = 0xFFFF-offset+1; + + if ( gr_bitblt_double ) + gr_linear_rep_movsd_2x( (void *)sbits, (void *)(offset+gr_video_memory), BytesToMove ); + else + gr_linear_movsd( (void *)sbits, (void *)(offset+gr_video_memory), BytesToMove ); + + page++; + gr_vesa_setpage(page); + + if ( gr_bitblt_double ) + gr_linear_rep_movsd_2x( (void *)(sbits+BytesToMove/2), (void *)gr_video_memory, EndingOffset - 0xFFFF ); + else + gr_linear_movsd( (void *)(sbits+BytesToMove), (void *)gr_video_memory, EndingOffset - 0xFFFF ); + + VideoLocation += dbpr; + sbits += sbpr; + } + } +} + +// From SVGA to linear +void gr_bm_ubitblt20(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) +{ + unsigned char * dbits; + + unsigned int offset, offset1, offset2; + + int sbpr, dbpr, y1, page; + + dbpr = dest->bm_rowsize; + + sbpr = src->bm_rowsize; + + for (y1=0; y1 < h; y1++ ) { + + offset2 = (unsigned int)src->bm_data + (sbpr * (y1+sy)) + sx; + dbits = dest->bm_data + (dbpr * (y1+dy)) + dx; + + page = offset2 >> 16; + offset = offset2 & 0xFFFF; + offset1 = offset+w-1; + gr_vesa_setpage( page ); + + if ( offset1 > 0xFFFF ) { + // Overlaps two pages + while( offset <= 0xFFFF ) + *dbits++ = gr_video_memory[offset++]; + offset1 -= (0xFFFF+1); + offset = 0; + page++; + gr_vesa_setpage(page); + } + while( offset <= offset1 ) + *dbits++ = gr_video_memory[offset++]; + + } +} +#endif // __MSDOS__ +//@extern int Interlacing_on; + +// From Linear to Linear +void gr_bm_ubitblt00(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) +{ + unsigned char * dbits; + unsigned char * sbits; + //int src_bm_rowsize_2, dest_bm_rowsize_2; + int dstep; + + int i; + + sbits = src->bm_data + (src->bm_rowsize * sy) + sx; + dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx; + + dstep = dest->bm_rowsize << gr_bitblt_dest_step_shift; + + // No interlacing, copy the whole buffer. + if (gr_bitblt_double) + for (i=0; i < h; i++ ) { + gr_linear_rep_movsd_2x( sbits, dbits, w ); + sbits += src->bm_rowsize; + dbits += dstep; + } + else + for (i=0; i < h; i++ ) { + gr_linear_movsd( sbits, dbits, w ); + //memcpy(dbits, sbits, w); + sbits += src->bm_rowsize; + dbits += dstep; + } +} + +// From Linear to Linear Masked +void gr_bm_ubitblt00m(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) +{ + unsigned char * dbits; + unsigned char * sbits; + //int src_bm_rowsize_2, dest_bm_rowsize_2; + + int i; + + sbits = src->bm_data + (src->bm_rowsize * sy) + sx; + dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx; + + // No interlacing, copy the whole buffer. + + if (gr_bitblt_fade_table==NULL) { + for (i=0; i < h; i++ ) { + gr_linear_rep_movsdm( sbits, dbits, w ); + sbits += src->bm_rowsize; + dbits += dest->bm_rowsize; + } + } else { + for (i=0; i < h; i++ ) { + gr_linear_rep_movsdm_faded( sbits, dbits, w, gr_bitblt_fade_table[dy+i] ); + sbits += src->bm_rowsize; + dbits += dest->bm_rowsize; + } + } +} + + +void gr_bm_bitblt(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) +{ + int dx1=dx, dx2=dx+dest->bm_w-1; + int dy1=dy, dy2=dy+dest->bm_h-1; + + int sx1=sx, sx2=sx+src->bm_w-1; + int sy1=sy, sy2=sy+src->bm_h-1; + + if ((dx1 >= dest->bm_w ) || (dx2 < 0)) return; + if ((dy1 >= dest->bm_h ) || (dy2 < 0)) return; + if ( dx1 < 0 ) { sx1 += -dx1; dx1 = 0; } + if ( dy1 < 0 ) { sy1 += -dy1; dy1 = 0; } + if ( dx2 >= dest->bm_w ) { dx2 = dest->bm_w-1; } + if ( dy2 >= dest->bm_h ) { dy2 = dest->bm_h-1; } + + if ((sx1 >= src->bm_w ) || (sx2 < 0)) return; + if ((sy1 >= src->bm_h ) || (sy2 < 0)) return; + if ( sx1 < 0 ) { dx1 += -sx1; sx1 = 0; } + if ( sy1 < 0 ) { dy1 += -sy1; sy1 = 0; } + if ( sx2 >= src->bm_w ) { sx2 = src->bm_w-1; } + if ( sy2 >= src->bm_h ) { sy2 = src->bm_h-1; } + + // Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2) + if ( dx2-dx1+1 < w ) + w = dx2-dx1+1; + if ( dy2-dy1+1 < h ) + h = dy2-dy1+1; + if ( sx2-sx1+1 < w ) + w = sx2-sx1+1; + if ( sy2-sy1+1 < h ) + h = sy2-sy1+1; + + gr_bm_ubitblt(w,h, dx1, dy1, sx1, sy1, src, dest ); +} + +void gr_bm_ubitblt(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) +{ + register int x1, y1; + + if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_LINEAR )) + { + if ( src->bm_flags & BM_FLAG_RLE ) + gr_bm_ubitblt00_rle( w, h, dx, dy, sx, sy, src, dest ); + else + gr_bm_ubitblt00( w, h, dx, dy, sx, sy, src, dest ); + return; + } + +#ifdef OGL + if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_OGL )) + { + ogl_ubitblt(w, h, dx, dy, sx, sy, src, dest); + return; + } + if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_LINEAR )) + { + ogl_ubitblt_tolinear(w, h, dx, dy, sx, sy, src, dest); + return; + } + if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_OGL )) + { + ogl_ubitblt_copy(w, h, dx, dy, sx, sy, src, dest); + return; + } +#endif + +#ifdef D1XD3D + if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_DIRECTX )) + { + Assert ((int)dest->bm_data == BM_D3D_RENDER || (int)dest->bm_data == BM_D3D_DISPLAY); + Win32_BlitLinearToDirectX_bm (src, sx, sy, w, h, dx, dy, 0); + return; + } + if ( (src->bm_type == BM_DIRECTX) && (dest->bm_type == BM_LINEAR )) + { + return; + } + if ( (src->bm_type == BM_DIRECTX) && (dest->bm_type == BM_DIRECTX )) + { + return; + } +#endif + + if ( (src->bm_flags & BM_FLAG_RLE ) && (src->bm_type == BM_LINEAR) ) { + gr_bm_ubitblt0x_rle(w, h, dx, dy, sx, sy, src, dest, 0 ); + return; + } +#ifdef __MSDOS__ + if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_SVGA )) + { + gr_bm_ubitblt02( w, h, dx, dy, sx, sy, src, dest ); + return; + } + + if ( (src->bm_type == BM_SVGA) && (dest->bm_type == BM_LINEAR )) + { + gr_bm_ubitblt20( w, h, dx, dy, sx, sy, src, dest ); + return; + } + + if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_MODEX )) + { + gr_bm_ubitblt01( w, h, dx+XOFFSET, dy+YOFFSET, sx, sy, src, dest ); + return; + } +#endif + for (y1=0; y1 < h; y1++ ) { + for (x1=0; x1 < w; x1++ ) { + gr_bm_pixel( dest, dx+x1, dy+y1, gr_gpixel(src,sx+x1,sy+y1) ); + } + } +} + +// Clipped bitmap ... + +void gr_bitmap( int x, int y, grs_bitmap *bm ) +{ + int dx1=x, dx2=x+bm->bm_w-1; + int dy1=y, dy2=y+bm->bm_h-1; + int sx=0, sy=0; + + if ((dx1 >= grd_curcanv->cv_bitmap.bm_w ) || (dx2 < 0)) return; + if ((dy1 >= grd_curcanv->cv_bitmap.bm_h) || (dy2 < 0)) return; + if ( dx1 < 0 ) { sx = -dx1; dx1 = 0; } + if ( dy1 < 0 ) { sy = -dy1; dy1 = 0; } + if ( dx2 >= grd_curcanv->cv_bitmap.bm_w ) { dx2 = grd_curcanv->cv_bitmap.bm_w-1; } + if ( dy2 >= grd_curcanv->cv_bitmap.bm_h ) { dy2 = grd_curcanv->cv_bitmap.bm_h-1; } + + // Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2) + + gr_bm_ubitblt(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap ); + +} + +void gr_bitmapm( int x, int y, grs_bitmap *bm ) +{ + int dx1=x, dx2=x+bm->bm_w-1; + int dy1=y, dy2=y+bm->bm_h-1; + int sx=0, sy=0; + + if ((dx1 >= grd_curcanv->cv_bitmap.bm_w ) || (dx2 < 0)) return; + if ((dy1 >= grd_curcanv->cv_bitmap.bm_h) || (dy2 < 0)) return; + if ( dx1 < 0 ) { sx = -dx1; dx1 = 0; } + if ( dy1 < 0 ) { sy = -dy1; dy1 = 0; } + if ( dx2 >= grd_curcanv->cv_bitmap.bm_w ) { dx2 = grd_curcanv->cv_bitmap.bm_w-1; } + if ( dy2 >= grd_curcanv->cv_bitmap.bm_h ) { dy2 = grd_curcanv->cv_bitmap.bm_h-1; } + + // Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2) + + if ( (bm->bm_type == BM_LINEAR) && (grd_curcanv->cv_bitmap.bm_type == BM_LINEAR )) + { + if ( bm->bm_flags & BM_FLAG_RLE ) + gr_bm_ubitblt00m_rle(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap ); + else + gr_bm_ubitblt00m(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap ); + return; + } + + gr_bm_ubitbltm(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap ); + +} + +void gr_bm_ubitbltm(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) +{ + register int x1, y1; + ubyte c; + +#ifdef OGL + if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_OGL )) + { + ogl_ubitblt(w, h, dx, dy, sx, sy, src, dest); + return; + } + if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_LINEAR )) + { + ogl_ubitblt_tolinear(w, h, dx, dy, sx, sy, src, dest); + return; + } + if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_OGL )) + { + ogl_ubitblt_copy(w, h, dx, dy, sx, sy, src, dest); + return; + } +#endif +#ifdef D1XD3D + if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_DIRECTX )) + { + Assert ((int)dest->bm_data == BM_D3D_RENDER || (int)dest->bm_data == BM_D3D_DISPLAY); + Win32_BlitLinearToDirectX_bm (src, sx, sy, w, h, dx, dy, 1); + return; + } + if ( (src->bm_type == BM_DIRECTX) && (dest->bm_type == BM_DIRECTX )) + { + Assert ((int)src->bm_data == BM_D3D_RENDER || (int)src->bm_data == BM_D3D_DISPLAY); +// Win32_BlitDirectXToDirectX (w, h, dx, dy, sx, sy, src->bm_data, dest->bm_data, 0); + return; + } +#endif + + + for (y1=0; y1 < h; y1++ ) { + for (x1=0; x1 < w; x1++ ) { + if ((c=gr_gpixel(src,sx+x1,sy+y1))!=255) + gr_bm_pixel( dest, dx+x1, dy+y1,c ); + } + } + +} + +//-NOT-used // From linear to SVGA +//-NOT-used void gr_bm_ubitblt02_2x(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) +//-NOT-used { +//-NOT-used unsigned char * sbits; +//-NOT-used +//-NOT-used unsigned int offset, EndingOffset, VideoLocation; +//-NOT-used +//-NOT-used int sbpr, dbpr, y1, page, BytesToMove; +//-NOT-used +//-NOT-used sbpr = src->bm_rowsize; +//-NOT-used +//-NOT-used dbpr = dest->bm_rowsize << gr_bitblt_dest_step_shift; +//-NOT-used +//-NOT-used VideoLocation = (unsigned int)dest->bm_data + (dest->bm_rowsize * dy) + dx; +//-NOT-used +//-NOT-used sbits = src->bm_data + ( sbpr*sy ) + sx; +//-NOT-used +//-NOT-used for (y1=0; y1 < h; y1++ ) { +//-NOT-used +//-NOT-used page = VideoLocation >> 16; +//-NOT-used offset = VideoLocation & 0xFFFF; +//-NOT-used +//-NOT-used gr_vesa_setpage( page ); +//-NOT-used +//-NOT-used EndingOffset = offset+w-1; +//-NOT-used +//-NOT-used if ( EndingOffset <= 0xFFFF ) +//-NOT-used { +//-NOT-used gr_linear_rep_movsd_2x( (void *)sbits, (void *)(offset+gr_video_memory), w ); +//-NOT-used +//-NOT-used VideoLocation += dbpr; +//-NOT-used sbits += sbpr; +//-NOT-used } +//-NOT-used else +//-NOT-used { +//-NOT-used BytesToMove = 0xFFFF-offset+1; +//-NOT-used +//-NOT-used gr_linear_rep_movsd_2x( (void *)sbits, (void *)(offset+gr_video_memory), BytesToMove ); +//-NOT-used +//-NOT-used page++; +//-NOT-used gr_vesa_setpage(page); +//-NOT-used +//-NOT-used gr_linear_rep_movsd_2x( (void *)(sbits+BytesToMove/2), (void *)gr_video_memory, EndingOffset - 0xFFFF ); +//-NOT-used +//-NOT-used VideoLocation += dbpr; +//-NOT-used sbits += sbpr; +//-NOT-used } +//-NOT-used +//-NOT-used +//-NOT-used } +//-NOT-used } + + +//-NOT-used // From Linear to Linear +//-NOT-used void gr_bm_ubitblt00_2x(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) +//-NOT-used { +//-NOT-used unsigned char * dbits; +//-NOT-used unsigned char * sbits; +//-NOT-used //int src_bm_rowsize_2, dest_bm_rowsize_2; +//-NOT-used +//-NOT-used int i; +//-NOT-used +//-NOT-used sbits = src->bm_data + (src->bm_rowsize * sy) + sx; +//-NOT-used dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx; +//-NOT-used +//-NOT-used // No interlacing, copy the whole buffer. +//-NOT-used for (i=0; i < h; i++ ) { +//-NOT-used gr_linear_rep_movsd_2x( sbits, dbits, w ); +//-NOT-used +//-NOT-used sbits += src->bm_rowsize; +//-NOT-used dbits += dest->bm_rowsize << gr_bitblt_dest_step_shift; +//-NOT-used } +//-NOT-used } + +void gr_bm_ubitblt00_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) +{ + unsigned char * dbits; + unsigned char * sbits; + + int i; + + sbits = &src->bm_data[4 + src->bm_h]; + for (i=0; ibm_data[4+i]; + + dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx; + + // No interlacing, copy the whole buffer. + for (i=0; i < h; i++ ) { + gr_rle_expand_scanline( dbits, sbits, sx, sx+w-1 ); + sbits += (int)src->bm_data[4+i+sy]; + dbits += dest->bm_rowsize << gr_bitblt_dest_step_shift; + } +} + +void gr_bm_ubitblt00m_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) +{ + unsigned char * dbits; + unsigned char * sbits; + + int i; + + sbits = &src->bm_data[4 + src->bm_h]; + for (i=0; ibm_data[4+i]; + + dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx; + + // No interlacing, copy the whole buffer. + for (i=0; i < h; i++ ) { + gr_rle_expand_scanline_masked( dbits, sbits, sx, sx+w-1 ); + sbits += (int)src->bm_data[4+i+sy]; + dbits += dest->bm_rowsize << gr_bitblt_dest_step_shift; + } +} + +// in rle.c + +extern void gr_rle_expand_scanline_generic( grs_bitmap * dest, int dx, int dy, ubyte *src, + int x1, int x2, int masked ); + + +void gr_bm_ubitblt0x_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, + grs_bitmap * dest, int masked ) +{ + int i; + register int y1; + unsigned char * sbits; + + sbits = &src->bm_data[4 + src->bm_h]; + for (i=0; ibm_data[4+i]; + + for (y1=0; y1 < h; y1++ ) { + gr_rle_expand_scanline_generic( dest, dx, dy+y1, sbits, sx, sx+w-1, + masked ); + sbits += (int)src->bm_data[4+y1+sy]; + } +} + +// rescalling bitmaps, 10/14/99 Jan Bobrowski jb@wizard.ae.krakow.pl + +inline void scale_line(byte *in, byte *out, int ilen, int olen) +{ + int a = olen/ilen, b = olen%ilen; + int c = 0, i; + byte *end = out + olen; + while(out= ilen) { + c -= ilen; + goto inside; + } + while(--i>=0) { +inside: + *out++ = *in; + } + in++; + } +} + +void gr_bitmap_scale_to(grs_bitmap *src, grs_bitmap *dst) +{ + byte *s = src->bm_data; + byte *d = dst->bm_data; + int h = src->bm_h; + int a = dst->bm_h/h, b = dst->bm_h%h; + int c = 0, i, y; + + for(y=0; y= h) { + c -= h; + goto inside; + } + while(--i>=0) { +inside: + scale_line(s, d, src->bm_w, dst->bm_w); + d += dst->bm_rowsize; + } + s += src->bm_rowsize; + } +} + +void show_fullscr(grs_bitmap *bm) +{ + grs_bitmap * const scr = &grd_curcanv->cv_bitmap; + + if(scr->bm_type != BM_LINEAR) { + grs_bitmap *tmp = gr_create_bitmap(scr->bm_w, scr->bm_h); + gr_bitmap_scale_to(bm, tmp); + gr_bitmap(0, 0, tmp); + gr_free_bitmap(tmp); + return; + } + gr_bitmap_scale_to(bm, scr); +} diff --git a/2d/bitmap.c b/2d/bitmap.c new file mode 100644 index 00000000..740e4855 --- /dev/null +++ b/2d/bitmap.c @@ -0,0 +1,327 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#include +#include +#include + +#include "u_mem.h" + + +#include "gr.h" +#include "grdef.h" +#include "u_dpmi.h" +#include "bitmap.h" +#include "error.h" + +#ifdef OGL +#include "ogl_init.h" +#endif + +void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq ); + +void gr_set_bitmap_data (grs_bitmap *bm, unsigned char *data) +{ +#ifdef OGL +// if (bm->bm_data!=data) + ogl_freebmtexture(bm); +#endif + bm->bm_data = data; +#ifdef D1XD3D + Assert (bm->iMagic == BM_MAGIC_NUMBER); + Win32_SetTextureBits (bm, data, bm->bm_flags & BM_FLAG_RLE); +#endif +} + +void gr_init_bitmap( grs_bitmap *bm, int mode, int x, int y, int w, int h, int bytesperline, unsigned char * data ) // TODO: virtualize +{ +#ifdef D1XD3D + Assert (bm->iMagic != BM_MAGIC_NUMBER || bm->pvSurface == NULL); +#endif + + bm->bm_x = x; + bm->bm_y = y; + bm->bm_w = w; + bm->bm_h = h; + bm->bm_flags = 0; + bm->bm_type = mode; + bm->bm_rowsize = bytesperline; + + bm->bm_data = NULL; +#ifdef D1XD3D + bm->iMagic = BM_MAGIC_NUMBER; + bm->pvSurface = NULL; +#endif + +#ifdef D1XD3D + Win32_CreateTexture (bm); +#endif +#ifdef OGL + bm->bm_parent=NULL;bm->gltexture=NULL; +#endif + +// if (data != 0) + gr_set_bitmap_data (bm, data); +/* + else + gr_set_bitmap_data (bm, d_malloc (w * h)); +*/ + +#ifdef BITMAP_SELECTOR + bm->bm_selector = 0; +#endif +} + +void gr_init_bitmap_alloc( grs_bitmap *bm, int mode, int x, int y, int w, int h, int bytesperline) +{ + gr_init_bitmap(bm, mode, x, y, w, h, bytesperline, 0); + gr_set_bitmap_data(bm, d_malloc(w * h)); +} + +void gr_init_bitmap_data (grs_bitmap *bm) // TODO: virtulize +{ + bm->bm_data = NULL; +#ifdef D1XD3D + Assert (bm->iMagic != BM_MAGIC_NUMBER); + bm->iMagic = BM_MAGIC_NUMBER; + bm->pvSurface = NULL; +#endif +#ifdef OGL +// ogl_freebmtexture(bm);//not what we want here. + bm->bm_parent=NULL;bm->gltexture=NULL; +#endif +} + +void gr_free_bitmap(grs_bitmap *bm ) +{ + gr_free_bitmap_data (bm); + if (bm!=NULL) + d_free(bm); +} + +void gr_free_bitmap_data (grs_bitmap *bm) // TODO: virtulize +{ +#ifdef D1XD3D + Assert (bm->iMagic == BM_MAGIC_NUMBER); + + Win32_FreeTexture (bm); + bm->iMagic = 0; + if (bm->bm_data == BM_D3D_RENDER) + bm->bm_data = NULL; +#endif +#ifdef OGL + ogl_freebmtexture(bm); +#endif + if (bm->bm_data != NULL) + d_free (bm->bm_data); + bm->bm_data = NULL; +} + +void gr_init_sub_bitmap (grs_bitmap *bm, grs_bitmap *bmParent, int x, int y, int w, int h ) // TODO: virtualize +{ + bm->bm_x = x + bmParent->bm_x; + bm->bm_y = y + bmParent->bm_y; + bm->bm_w = w; + bm->bm_h = h; + bm->bm_flags = bmParent->bm_flags; + bm->bm_type = bmParent->bm_type; + bm->bm_rowsize = bmParent->bm_rowsize; + +#ifdef OGL + bm->gltexture=bmParent->gltexture; + bm->bm_parent=bmParent; +#endif +#ifdef D1XD3D + Assert (bmParent->iMagic == BM_MAGIC_NUMBER); + bm->iMagic = BM_MAGIC_NUMBER; + bm->pvSurface = bmParent->pvSurface; + if (bm->bm_type == BM_DIRECTX) + { + bm->bm_data = bmParent->bm_data; + } + else +#endif + { + bm->bm_data = bmParent->bm_data+(unsigned int)((y*bmParent->bm_rowsize)+x); + } + +} + +void gr_free_sub_bitmap(grs_bitmap *bm ) +{ + if (bm!=NULL) + { +#ifdef D1XD3D + bm->iMagic = 0; +#endif + d_free(bm); + } +} + + +grs_bitmap *gr_create_bitmap(int w, int h ) +{ + return gr_create_bitmap_raw (w, h, d_malloc(w * h)); +} + +grs_bitmap *gr_create_bitmap_raw(int w, int h, unsigned char * raw_data ) +{ + grs_bitmap *new; + + new = (grs_bitmap *)d_malloc( sizeof(grs_bitmap) ); + gr_init_bitmap (new, 0, 0, 0, w, h, w, raw_data); + + return new; +} + + +grs_bitmap *gr_create_sub_bitmap(grs_bitmap *bm, int x, int y, int w, int h ) +{ + grs_bitmap *new; + + new = (grs_bitmap *)d_malloc( sizeof(grs_bitmap) ); + gr_init_sub_bitmap (new, bm, x, y, w, h); + + return new; +} + +void gr_set_bitmap_flags (grs_bitmap *pbm, int flags) +{ +#ifdef D1XD3D + Assert (pbm->iMagic == BM_MAGIC_NUMBER); + + if (pbm->pvSurface) + { + if ((flags & BM_FLAG_TRANSPARENT) != (pbm->bm_flags & BM_FLAG_TRANSPARENT)) + { + Win32_SetTransparent (pbm->pvSurface, flags & BM_FLAG_TRANSPARENT); + } + } +#endif + pbm->bm_flags = flags; +} + +void gr_set_transparent (grs_bitmap *pbm, int bTransparent) +{ + if (bTransparent) + { + gr_set_bitmap_flags (pbm, pbm->bm_flags | BM_FLAG_TRANSPARENT); + } + else + { + gr_set_bitmap_flags (pbm, pbm->bm_flags & ~BM_FLAG_TRANSPARENT); + } +} + +void gr_set_super_transparent (grs_bitmap *pbm, int bTransparent) +{ + if (bTransparent) + { + gr_set_bitmap_flags (pbm, pbm->bm_flags & ~BM_FLAG_SUPER_TRANSPARENT); + } + else + { + gr_set_bitmap_flags (pbm, pbm->bm_flags | BM_FLAG_SUPER_TRANSPARENT); + } +} + +void gr_remap_bitmap( grs_bitmap * bmp, ubyte * palette, int transparent_color, int super_transparent_color ) +{ + ubyte colormap[256]; + int freq[256]; + + // This should be build_colormap_asm, but we're not using invert table, so... + build_colormap_good( palette, colormap, freq ); + + if ( (super_transparent_color>=0) && (super_transparent_color<=255)) + colormap[super_transparent_color] = 254; + + if ( (transparent_color>=0) && (transparent_color<=255)) + colormap[transparent_color] = 255; + + decode_data_asm(bmp->bm_data, bmp->bm_w * bmp->bm_h, colormap, freq ); + + if ( (transparent_color>=0) && (transparent_color<=255) && (freq[transparent_color]>0) ) + gr_set_transparent (bmp, 1); + + if ( (super_transparent_color>=0) && (super_transparent_color<=255) && (freq[super_transparent_color]>0) ) + gr_set_super_transparent (bmp, 0); +} + +void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq ) +{ + int i, r, g, b; + + for (i=0; i<256; i++ ) { + r = *palette++; + g = *palette++; + b = *palette++; + *colormap++ = gr_find_closest_color( r, g, b ); + *freq++ = 0; + } +} + + +void gr_remap_bitmap_good( grs_bitmap * bmp, ubyte * palette, int transparent_color, int super_transparent_color ) +{ + ubyte colormap[256]; + int freq[256]; + + build_colormap_good( palette, colormap, freq ); + + if ( (super_transparent_color>=0) && (super_transparent_color<=255)) + colormap[super_transparent_color] = 254; + + if ( (transparent_color>=0) && (transparent_color<=255)) + colormap[transparent_color] = 255; + + decode_data_asm(bmp->bm_data, bmp->bm_w * bmp->bm_h, colormap, freq ); + + if ( (transparent_color>=0) && (transparent_color<=255) && (freq[transparent_color]>0) ) + gr_set_transparent (bmp, 1); + + if ( (super_transparent_color>=0) && (super_transparent_color<=255) && (freq[super_transparent_color]>0) ) + gr_set_super_transparent (bmp, 1); +} + +#ifdef BITMAP_SELECTOR +int gr_bitmap_assign_selector( grs_bitmap * bmp ) +{ + if (!dpmi_allocate_selector( bmp->bm_data, bmp->bm_w*bmp->bm_h, &bmp->bm_selector )) { + bmp->bm_selector = 0; + return 1; + } + return 0; +} +#endif + +void gr_bitmap_check_transparency( grs_bitmap * bmp ) +{ + int x, y; + ubyte * data; + + data = bmp->bm_data; + + for (y=0; ybm_h; y++ ) { + for (x=0; xbm_w; x++ ) { + if (*data++ == 255 ) { + gr_set_transparent (bmp, 1); + return; + } + } + data += bmp->bm_rowsize - bmp->bm_w; + } + + bmp->bm_flags = 0; + +} diff --git a/2d/bitmap.h b/2d/bitmap.h new file mode 100644 index 00000000..1c4d1f04 --- /dev/null +++ b/2d/bitmap.h @@ -0,0 +1,70 @@ +#ifndef _BITMAP_H +#define _BITMAP_H + +#ifndef NO_ASM +#ifdef __WATCOMC__ +void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count ); +#pragma aux decode_data_asm parm [esi] [ecx] [edi] [ebx] modify exact [esi edi eax ebx ecx] = \ +"again_ddn:" \ + "xor eax,eax" \ + "mov al,[esi]" \ + "inc dword ptr [ebx+eax*4]" \ + "mov al,[edi+eax]" \ + "mov [esi],al" \ + "inc esi" \ + "dec ecx" \ + "jne again_ddn" +#elif defined __GNUC__ +static inline void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count ) { + int dummy[4]; + __asm__ __volatile__ ( + "xorl %%eax,%%eax;" +"0:;" + "movb (%%esi), %%al;" + "incl (%%ebx, %%eax, 4);" + "movb (%%edi, %%eax), %%al;" + "movb %%al, (%%esi);" + "incl %%esi;" + "decl %%ecx;" + "jne 0b" + : "=S" (dummy[0]), "=c" (dummy[1]), "=D" (dummy[2]), "=b" (dummy[3]) + : "0" (data), "1" (num_pixels), "2" (colormap), "3" (count) + : "%eax"); +} +#elif defined _MSC_VER +__inline void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count ) +{ + __asm { + mov esi,[data] + mov ecx,[num_pixels] + mov edi,[colormap] + mov ebx,[count] +again_ddn: + xor eax,eax + mov al,[esi] + inc dword ptr [ebx+eax*4] + mov al,[edi+eax] + mov [esi],al + inc esi + dec ecx + jne again_ddn + } +} +#else +#define NO_ASM 1 // We really do want no assembler... +#endif +#endif + +#ifdef NO_ASM +static void decode_data_asm(ubyte *data, int num_pixels, ubyte *colormap, int *count) +{ + int i; + + for (i = 0; i < num_pixels; i++) { + count[*data]++; + *data = colormap[*data]; + data++; + } +} +#endif +#endif diff --git a/2d/box.c b/2d/box.c new file mode 100644 index 00000000..54b4aaeb --- /dev/null +++ b/2d/box.c @@ -0,0 +1,125 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#include +#include "u_mem.h" + + +#include "gr.h" +#include "grdef.h" + +void gr_ubox0(int left,int top,int right,int bot) +{ + int i, d; + + unsigned char * ptr1; + unsigned char * ptr2; + + ptr1 = DATA + ROWSIZE *top+left; + + ptr2 = ptr1; + d = right - left; + + for (i=top; i<=bot; i++ ) + { + ptr2[0] = (unsigned char) COLOR; + ptr2[d] = (unsigned char) COLOR; + ptr2 += ROWSIZE; + } + + ptr2 = ptr1; + d = (bot - top)*ROWSIZE; + + for (i=1; i<(right-left); i++ ) + { + ptr2[i+0] = (unsigned char) COLOR; + ptr2[i+d] = (unsigned char) COLOR; + } +} + +void gr_box0(int left,int top,int right,int bot) +{ + if (top > MAXY ) return; + if (bot < MINY ) return; + if (left > MAXX ) return; + if (right < MINX ) return; + + if (top < MINY) top = MINY; + if (bot > MAXY ) bot = MAXY; + if (left < MINX) left = MINX; + if (right > MAXX ) right = MAXX; + + gr_ubox0(left,top,right,bot); + +} + + +void gr_ubox12(int left,int top,int right,int bot) +{ + int i; + + for (i=top; i<=bot; i++ ) + { + gr_upixel( left, i ); + gr_upixel( right, i ); + } + + gr_uscanline( left, right, top ); + + gr_uscanline( left, right, bot ); +} + +void gr_box12(int left,int top,int right,int bot) +{ + if (top > MAXY ) return; + if (bot < MINY ) return; + if (left > MAXX ) return; + if (right < MINX ) return; + + if (top < MINY) top = MINY; + if (bot > MAXY ) bot = MAXY; + if (left < MINX) left = MINX; + if (right > MAXX ) right = MAXX; + + gr_ubox12(left, top, right, bot ); + +} + +void gr_ubox(int left,int top,int right,int bot) +{ + if (TYPE==BM_LINEAR) + gr_ubox0( left, top, right, bot ); + +#ifdef __MSDOS__ + else if ( TYPE == BM_MODEX ) + gr_ubox12( left, top, right, bot ); +#endif + + else + gr_ubox12( left, top, right, bot ); +} + +void gr_box(int left,int top,int right,int bot) +{ + if (TYPE==BM_LINEAR) + gr_box0( left, top, right, bot ); + +#ifdef __MSDOS__ + else if ( TYPE == BM_MODEX ) + gr_box12( left, top, right, bot ); +#endif + + else + gr_ubox12( left, top, right, bot ); +} + diff --git a/2d/canvas.c b/2d/canvas.c new file mode 100644 index 00000000..befb02c3 --- /dev/null +++ b/2d/canvas.c @@ -0,0 +1,147 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#include +#include +//#include +#include + +#include "u_mem.h" + + +#include "gr.h" +#include "grdef.h" +#ifdef __MSDOS__ +#include "modex.h" +#include "vesa.h" +#endif + +grs_canvas * grd_curcanv; //active canvas +grs_screen * grd_curscreen; //active screen + +grs_canvas *gr_create_canvas(int w, int h) +{ + grs_canvas *new; + + new = (grs_canvas *)d_malloc( sizeof(grs_canvas) ); + gr_init_bitmap_alloc (&new->cv_bitmap, BM_LINEAR, 0, 0, w, h, w); + + new->cv_color = 0; + new->cv_drawmode = 0; + new->cv_font = NULL; + new->cv_font_fg_color = 0; + new->cv_font_bg_color = 0; + return new; +} + +grs_canvas *gr_create_sub_canvas(grs_canvas *canv, int x, int y, int w, int h) +{ + grs_canvas *new; + + new = (grs_canvas *)d_malloc( sizeof(grs_canvas) ); + gr_init_sub_bitmap (&new->cv_bitmap, &canv->cv_bitmap, x, y, w, h); + + new->cv_color = canv->cv_color; + new->cv_drawmode = canv->cv_drawmode; + new->cv_font = canv->cv_font; + new->cv_font_fg_color = canv->cv_font_fg_color; + new->cv_font_bg_color = canv->cv_font_bg_color; + return new; +} + +void gr_init_canvas(grs_canvas *canv, unsigned char * pixdata, int pixtype, int w, int h) +{ + int wreal; + canv->cv_color = 0; + canv->cv_drawmode = 0; + canv->cv_font = NULL; + canv->cv_font_fg_color = 0; + canv->cv_font_bg_color = 0; + + +#ifndef __MSDOS__ + wreal = w; +#else + wreal = (pixtype == BM_MODEX) ? w / 4 : w; +#endif + gr_init_bitmap (&canv->cv_bitmap, pixtype, 0, 0, w, h, wreal, pixdata); +} + +void gr_init_sub_canvas(grs_canvas *new, grs_canvas *src, int x, int y, int w, int h) +{ + new->cv_color = src->cv_color; + new->cv_drawmode = src->cv_drawmode; + new->cv_font = src->cv_font; + new->cv_font_fg_color = src->cv_font_fg_color; + new->cv_font_bg_color = src->cv_font_bg_color; + + gr_init_sub_bitmap (&new->cv_bitmap, &src->cv_bitmap, x, y, w, h); +} + +void gr_free_canvas(grs_canvas *canv) +{ + gr_free_bitmap_data(&canv->cv_bitmap); + d_free(canv); +} + +void gr_free_sub_canvas(grs_canvas *canv) +{ + d_free(canv); +} + +int gr_wait_for_retrace = 1; + +void gr_show_canvas( grs_canvas *canv ) +{ +#ifdef __MSDOS__ + if (canv->cv_bitmap.bm_type == BM_MODEX ) + gr_modex_setstart( canv->cv_bitmap.bm_x, canv->cv_bitmap.bm_y, gr_wait_for_retrace ); + + else if (canv->cv_bitmap.bm_type == BM_SVGA ) + gr_vesa_setstart( canv->cv_bitmap.bm_x, canv->cv_bitmap.bm_y ); +#endif + // else if (canv->cv_bitmap.bm_type == BM_LINEAR ) + // Int3(); // Get JOHN! + //gr_linear_movsd( canv->cv_bitmap.bm_data, (void *)gr_video_memory, 320*200); +} + +void gr_set_current_canvas( grs_canvas *canv ) +{ + if (canv==NULL) + grd_curcanv = &(grd_curscreen->sc_canvas); + else + grd_curcanv = canv; +#ifndef NO_ASM + if ( (grd_curcanv->cv_color >= 0) && (grd_curcanv->cv_color <= 255) ) { + gr_var_color = grd_curcanv->cv_color; + } else + gr_var_color = 0; + gr_var_bitmap = grd_curcanv->cv_bitmap.bm_data; + gr_var_bwidth = grd_curcanv->cv_bitmap.bm_rowsize; +#endif +} + +void gr_clear_canvas(int color) +{ + gr_setcolor(color); + gr_rect(0,0,GWIDTH-1,GHEIGHT-1); +} + +void gr_setcolor(int color) +{ + grd_curcanv->cv_color=color; +#ifndef NO_ASM + gr_var_color = color; +#endif +} + diff --git a/2d/circle.c b/2d/circle.c new file mode 100644 index 00000000..4d25a70b --- /dev/null +++ b/2d/circle.c @@ -0,0 +1,114 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifdef RCS +static char rcsid[] = "$Id: circle.c,v 1.1.1.1 2001-01-19 03:29:57 bradleyb Exp $"; +#endif + +#include +#include "u_mem.h" + +#include "gr.h" +#include "grdef.h" + +#ifndef OGL + +int gr_circle(fix xc1,fix yc1,fix r1) +{ + int p,x, y, xc, yc, r; + + r = f2i(r1); + xc = f2i(xc1); + yc = f2i(yc1); + p=3-(r*2); + x=0; + y=r; + + // Big clip + if ( (xc+r) < 0 ) return 1; + if ( (xc-r) > GWIDTH ) return 1; + if ( (yc+r) < 0 ) return 1; + if ( (yc-r) > GHEIGHT ) return 1; + + while(x (b)) ? (a) : (b)) +*/ +#define IABS(x) (((x) < 0) ? -(x) : (x)) + +#define EXCHG(a,b) do { \ + int __temp__ = (a); \ + (a) = (b); \ + (b) = __temp__; \ +} while(0) + +// sort two values +#define SORT2(a,b) do { \ + if((a) > (b)) EXCHG(a,b); \ +} while(0) + +# define SCALE(var,arg,num,den) \ + ((var) = ((arg) * (num)) / (den)) + +# define USCALE(var,arg,num,den) \ + ((var) = ((unsigned)(arg) * (unsigned)(num)) / (unsigned)(den)) + +# define FSCALE(var,arg,num,den) ((var) = fixmuldiv((arg),(num),(den))) + +#define CLIPDOT(xx,yy,WHEN_OUTSIDE,WHEN_CLIPPED) { \ + if((xx > XMAX) || (xx < XMIN)) { WHEN_OUTSIDE; } \ + if((yy > YMAX) || (yy < YMIN)) { WHEN_OUTSIDE; } \ +} + +#define CLIPHLINE(x1,x2,yy,WHEN_OUTSIDE,WHEN_CLIPPED) { \ + if(x1 > x2) EXCHG(x1,x2); \ + if((x1 > XMAX) || (x2 < XMIN)) { WHEN_OUTSIDE; } \ + if((yy > YMAX) || (yy < YMIN)) { WHEN_OUTSIDE; } \ + if(x1 < XMIN) { x1 = XMIN; WHEN_CLIPPED; } \ + if(x2 > XMAX) { x2 = XMAX; WHEN_CLIPPED; } \ +} + +#define CLIPVLINE(xx,y1,y2,WHEN_OUTSIDE,WHEN_CLIPPED) { \ + if(y1 > y2) EXCHG(y1,y2); \ + if((xx > XMAX) || (xx < XMIN)) { WHEN_OUTSIDE; } \ + if((y1 > YMAX) || (y2 < YMIN)) { WHEN_OUTSIDE; } \ + if(y1 < YMIN) { y1 = YMIN; WHEN_CLIPPED; } \ + if(y2 > YMAX) { y2 = YMAX; WHEN_CLIPPED; } \ +} + +#define CLIPBOX(x1,y1,x2,y2,WHEN_OUTSIDE,WHEN_CLIPPED) { \ + if(x1 > x2) EXCHG(x1,x2); \ + if(y1 > y2) EXCHG(y1,y2); \ + if((x1 > XMAX) || (x2 < 0)) { WHEN_OUTSIDE; } \ + if((y1 > YMAX) || (y2 < 0)) { WHEN_OUTSIDE; } \ + if(x1 < 0) { x1 = 0; WHEN_CLIPPED; } \ + if(y1 < 0) { y1 = 0; WHEN_CLIPPED; } \ + if(x2 > XMAX) { x2 = XMAX; WHEN_CLIPPED; } \ + if(y2 > YMAX) { y2 = YMAX; WHEN_CLIPPED; } \ +} + +#define CLIPLINE(x1,y1,x2,y2,XMIN,YMIN,XMAX,YMAX,WHEN_OUTSIDE,WHEN_CLIPPED,MY_SCALE) do { \ + register int temp; \ + if(y1 > y2) \ + { EXCHG(y1,y2); EXCHG(x1,x2); } \ + if((y2 < YMIN) || (y1 > YMAX)) \ + { WHEN_OUTSIDE; } \ + if(x1 < x2) { \ + if((x2 < XMIN) || (x1 > XMAX)) { \ + WHEN_OUTSIDE; \ + } \ + if(x1 < XMIN) { \ + MY_SCALE(temp,(y2 - y1),(XMIN - x1),(x2 - x1)); \ + if((y1 += temp) > YMAX) { WHEN_OUTSIDE; } \ + x1 = XMIN; \ + WHEN_CLIPPED; \ + } \ + if(x2 > XMAX) { \ + MY_SCALE(temp,(y2 - y1),(x2 - XMAX),(x2 - x1)); \ + if((y2 -= temp) < YMIN) { WHEN_OUTSIDE; } \ + x2 = XMAX; \ + WHEN_CLIPPED; \ + } \ + if(y1 < YMIN) { \ + MY_SCALE(temp,(x2 - x1),(YMIN - y1),(y2 - y1)); \ + x1 += temp; \ + y1 = YMIN; \ + WHEN_CLIPPED; \ + } \ + if(y2 > YMAX) { \ + MY_SCALE(temp,(x2 - x1),(y2 - YMAX),(y2 - y1)); \ + x2 -= temp; \ + y2 = YMAX; \ + WHEN_CLIPPED; \ + } \ + } \ + else { \ + if((x1 < XMIN) || (x2 > XMAX)) { \ + WHEN_OUTSIDE; \ + } \ + if(x1 > XMAX) { \ + MY_SCALE(temp,(y2 - y1),(x1 - XMAX),(x1 - x2)); \ + if((y1 += temp) > YMAX) { WHEN_OUTSIDE; } \ + x1 = XMAX; \ + WHEN_CLIPPED; \ + } \ + if(x2 < XMIN) { \ + MY_SCALE(temp,(y2 - y1),(XMIN - x2),(x1 - x2)); \ + if((y2 -= temp) < YMIN) { WHEN_OUTSIDE; } \ + x2 = XMIN; \ + WHEN_CLIPPED; \ + } \ + if(y1 < YMIN) { \ + MY_SCALE(temp,(x1 - x2),(YMIN - y1),(y2 - y1)); \ + x1 -= temp; \ + y1 = YMIN; \ + WHEN_CLIPPED; \ + } \ + if(y2 > YMAX) { \ + MY_SCALE(temp,(x1 - x2),(y2 - YMAX),(y2 - y1)); \ + x2 += temp; \ + y2 = YMAX; \ + WHEN_CLIPPED; \ + } \ + } \ +} while(0) diff --git a/2d/diff b/2d/diff new file mode 100644 index 00000000..2dff4f73 --- /dev/null +++ b/2d/diff @@ -0,0 +1,354 @@ +13a14 +> #include +23c24 +< #include "mem.h" +--- +> #include "u_mem.h" +31a33 +> #include "bitmap.h" +133a136 +> +135a139,156 +> //hack to allow color codes to be embedded in strings -MPM +> //note we subtract one from color, since 255 is "transparent" so it'll never be used, and 0 would otherwise end the string. +> //function must already have orig_color var set (or they could be passed as args...) +> //perhaps some sort of recursive orig_color type thing would be better, but that would be way too much trouble for little gain +> int gr_message_color_level=1; +> #define CHECK_EMBEDDED_COLORS() if ((*text_ptr >= 0x01) && (*text_ptr <= 0x03)) { \ +> text_ptr++; \ +> if (*text_ptr){ \ +> if (gr_message_color_level >= *(text_ptr-1)) \ +> FG_COLOR = *text_ptr - 1; \ +> text_ptr++; \ +> } \ +> } \ +> else if ((*text_ptr >= 0x04) && (*text_ptr <= 0x06)){ \ +> if (gr_message_color_level >= *text_ptr - 3) \ +> FG_COLOR=orig_color; \ +> text_ptr++; \ +> } +359c380 +< +--- +> #ifdef __ENV_MSDOS__ +749a771 +> #endif +975a998 +> #ifndef OGL +1049a1073,1336 +> #else // OGL +> +> #include "../main/inferno.h" +> #include "ogl_init.h" +> #include "args.h" +> //font handling routines for OpenGL - Added 9/25/99 Matthew Mueller - they are here instead of in arch/ogl because they use all these defines +> +> int pow2ize(int x);//from ogl.c +> +> int get_font_total_width(grs_font * font){ +> if (font->ft_flags & FT_PROPORTIONAL){ +> int i,w=0,c=font->ft_minchar; +> for (i=0;c<=font->ft_maxchar;i++,c++){ +> if (font->ft_widths[i]<0) +> Error("heh?\n"); +> w+=font->ft_widths[i]; +> } +> return w; +> }else{ +> return font->ft_w*(font->ft_maxchar-font->ft_minchar+1); +> } +> } +> void ogl_font_choose_size(grs_font * font,int gap,int *rw,int *rh){ +> int nchars = font->ft_maxchar-font->ft_minchar+1; +> int r,x,y,nc=0,smallest=999999,smallr=-1,tries; +> int smallprop=10000; +> int h,w; +> for (h=32;h<=256;h*=2){ +> // h=pow2ize(font->ft_h*rows+gap*(rows-1)); +> if (font->ft_h>h)continue; +> r=(h/(font->ft_h+gap)); +> w=pow2ize((get_font_total_width(font)+(nchars-r)*gap)/r); +> tries=0; +> do { +> if (tries) +> w=pow2ize(w+1); +> if(tries>3){ +> mprintf((0,"failed to fit (%ix%i, %ic)\n",w,h,nc)); +> break; +> } +> nc=0; +> y=0; +> while(y+font->ft_h<=h){ +> x=0; +> while (x if (nc==nchars) +> break; +> if (font->ft_flags & FT_PROPORTIONAL){ +> if (x+font->ft_widths[nc]+gap>w)break; +> x+=font->ft_widths[nc++]+gap; +> }else{ +> if (x+font->ft_w+gap>w)break; +> x+=font->ft_w+gap; +> nc++; +> } +> } +> if (nc==nchars) +> break; +> y+=font->ft_h+gap; +> } +> +> tries++; +> }while(nc!=nchars); +> if (nc!=nchars) +> continue; +> mprintf((0,"fit: %ix%i %i tries\n",w,h,tries)); +> +> if (w*h==smallest){//this gives squarer sizes priority (ie, 128x128 would be better than 512*32) +> if (w>=h){ +> if (w/h smallprop=w/h; +> smallest++;//hack +> } +> }else{ +> if (h/w smallprop=h/w; +> smallest++;//hack +> } +> } +> } +> if (w*h smallr=1; +> smallest=w*h; +> *rw=w; +> *rh=h; +> } +> } +> if (smallr<=0) +> Error("couldn't fit font?\n"); +> mprintf((0,"using %ix%i\n",*rw,*rh)); +> printf("using %ix%i\n",*rw,*rh); +> +> } +> +> void ogl_init_font(grs_font * font){ +> int nchars = font->ft_maxchar-font->ft_minchar+1; +> int i,w,h,tw,th,x,y,curx=0,cury=0; +> char *fp; +> // char data[32*32*4]; +> char *data; +> int gap=0;//having a gap just wastes ram, since we don't filter text textures at all. +> // char s[2]; +> ogl_font_choose_size(font,gap,&tw,&th); +> data=malloc(tw*th); +> gr_init_bitmap(&font->ft_parent_bitmap,BM_LINEAR,0,0,tw,th,tw,data); +> +> font->ft_parent_bitmap.gltexture=ogl_get_free_texture(); +> +> font->ft_bitmaps=(grs_bitmap*)malloc( nchars * sizeof(grs_bitmap)); +> mprintf((0,"ogl_init_font %s, %s, nchars=%i, (%ix%i tex)\n",(font->ft_flags & FT_PROPORTIONAL)?"proportional":"fixedwidth",(font->ft_flags & FT_COLOR)?"color":"mono",nchars,tw,th)); +> // s[1]=0; +> h=font->ft_h; +> // sleep(5); +> +> for(i=0;i // s[0]=font->ft_minchar+i; +> // gr_get_string_size(s,&w,&h,&aw); +> if (font->ft_flags & FT_PROPORTIONAL) +> w=font->ft_widths[i]; +> else +> w=font->ft_w; +> // mprintf((0,"char %i(%ix%i): ",i,w,h)); +> if (w<1 || w>256){ +> mprintf((0,"grr\n"));continue; +> } +> if (curx+w+gap>tw){ +> cury+=h+gap; +> curx=0; +> } +> if (cury+h>th) +> Error("font doesn't really fit (%i/%i)?\n",i,nchars); +> if (font->ft_flags & FT_COLOR) { +> if (font->ft_flags & FT_PROPORTIONAL) +> fp = font->ft_chars[i]; +> else +> fp = font->ft_data + i * w*h; +> for (y=0;y for (x=0;x font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=fp[x+y*w]; +> } +> +> // gr_init_bitmap(&font->ft_bitmaps[i],BM_LINEAR,0,0,w,h,w,font->); +> }else{ +> int BitMask,bits=0,white=gr_find_closest_color(63,63,63); +> // if (w*h>sizeof(data)) +> // Error("ogl_init_font: toobig\n"); +> if (font->ft_flags & FT_PROPORTIONAL) +> fp = font->ft_chars[i]; +> else +> fp = font->ft_data + i * BITS_TO_BYTES(w)*h; +> for (y=0;y BitMask=0; +> for (x=0; x< w; x++ ) +> { +> if (BitMask==0) { +> bits = *fp++; +> BitMask = 0x80; +> } +> +> if (bits & BitMask) +> font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=white; +> else +> font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=255; +> BitMask >>= 1; +> } +> } +> } +> gr_init_sub_bitmap(&font->ft_bitmaps[i],&font->ft_parent_bitmap,curx,cury,w,h); +> +> curx+=w+gap; +> } +> if (!(font->ft_flags & FT_COLOR)) { +> //use GL_INTENSITY instead of GL_RGB +> if (ogl_intensity4_ok){ +> font->ft_parent_bitmap.gltexture->internalformat=GL_INTENSITY4; +> font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE; +> }else if (ogl_luminance4_alpha4_ok){ +> font->ft_parent_bitmap.gltexture->internalformat=GL_LUMINANCE4_ALPHA4; +> font->ft_parent_bitmap.gltexture->format=GL_LUMINANCE_ALPHA; +> }else if (ogl_rgba2_ok){ +> font->ft_parent_bitmap.gltexture->internalformat=GL_RGBA2; +> font->ft_parent_bitmap.gltexture->format=GL_RGBA; +> }else{ +> font->ft_parent_bitmap.gltexture->internalformat=ogl_rgba_format; +> font->ft_parent_bitmap.gltexture->format=GL_RGBA; +> } +> } +> ogl_loadbmtexture_m(&font->ft_parent_bitmap,0); +> } +> +> int ogl_internal_string(int x, int y, char *s ) +> { +> ubyte * text_ptr, * next_row, * text_ptr1; +> int width, spacing,letter; +> int xx,yy; +> int orig_color=FG_COLOR;//to allow easy reseting to default string color with colored strings -MPM +> +> next_row = s; +> +> yy = y; +> +> if (grd_curscreen->sc_canvas.cv_bitmap.bm_type != BM_OGL) +> Error("carp.\n"); +> while (next_row != NULL) +> { +> text_ptr1 = next_row; +> next_row = NULL; +> +> text_ptr = text_ptr1; +> +> xx = x; +> +> if (xx==0x8000) //centered +> xx = get_centered_x(text_ptr); +> +> while (*text_ptr) +> { +> if (*text_ptr == '\n' ) +> { +> next_row = &text_ptr[1]; +> yy += FHEIGHT; +> break; +> } +> +> letter = *text_ptr-FMINCHAR; +> +> get_char_width(text_ptr[0],text_ptr[1],&width,&spacing); +> +> if (!INFONT(letter) || *text_ptr<=0x06) { //not in font, draw as space +> CHECK_EMBEDDED_COLORS() else{ +> xx += spacing; +> text_ptr++; +> } +> continue; +> } +> +> // ogl_ubitblt(FONT->ft_bitmaps[letter].bm_w,FONT->ft_bitmaps[letter].bm_h,xx,yy,0,0,&FONT->ft_bitmaps[letter],NULL); +> // if (*text_ptr>='0' && *text_ptr<='9'){ +> printf("%p\n",&FONT->ft_bitmaps[letter]); +> if (FFLAGS&FT_COLOR) +> gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]); +> else{ +> if (grd_curcanv->cv_bitmap.bm_type==BM_OGL) +> ogl_ubitmapm_c(xx,yy,&FONT->ft_bitmaps[letter],FG_COLOR); +> else +> Error("ogl_internal_string: non-color string to non-ogl dest\n"); +> // gr_ubitmapm(xx,yy,&FONT->ft_bitmaps[letter]);//ignores color.. +> } +> //} +> +> xx += spacing; +> +> text_ptr++; +> } +> +> } +> return 0; +> } +> int gr_internal_color_string(int x, int y, char *s ){ +> return ogl_internal_string(x,y,s); +> } +> +> #endif // OGL +> +1118a1406 +> #ifdef __ENV_MSDOS__ +1123a1412 +> #endif +1248a1538,1539 +> #define swapshort(a) (a) +> #define swapint(a) (a) +1251a1543 +> old_grs_font *oldfont; +1284c1576,1578 +< font = (grs_font *) malloc(datasize); +--- +> oldfont = (old_grs_font *) malloc(datasize); +> font = (grs_font *) malloc(sizeof(grs_font)); +> font->oldfont = oldfont; +1288c1582,1590 +< cfread(font,1,datasize,fontfile); +--- +> cfread(oldfont,1,datasize,fontfile); +> font->ft_flags=swapshort(oldfont->ft_flags); +> font->ft_w=swapshort(oldfont->ft_w); +> font->ft_h=swapshort(oldfont->ft_h); +> font->ft_baseline=swapshort(oldfont->ft_baseline); +> font->ft_maxchar=oldfont->ft_maxchar; +> font->ft_minchar=oldfont->ft_minchar; +> font->ft_bytewidth=swapshort(oldfont->ft_bytewidth); +> +1307c1609 +< font->ft_widths = (short *) (((int) font->ft_widths) + ((ubyte *) font)); +--- +> font->ft_widths = (short *) (((int) oldfont->ft_widths) + ((ubyte *) oldfont)); +1311c1613 +< font->ft_widths[i] = SWAPSHORT(font->ft_widths[i]); +--- +> font->ft_widths[i] = swapshort(oldfont->ft_widths[i]); +1314c1616 +< font->ft_data = ((int) font->ft_data) + ((ubyte *) font); +--- +> font->ft_data = ((int) oldfont->ft_data) + ((ubyte *) oldfont); +1330c1632 +< font->ft_data = ((unsigned char *) font) + sizeof(*font); +--- +> font->ft_data = ((unsigned char *) oldfont) + sizeof(*oldfont); +1339c1641 +< font->ft_kerndata = ((int) font->ft_kerndata) + ((ubyte *) font); +--- +> font->ft_kerndata = swapint(((int) oldfont->ft_kerndata) + ((ubyte *) oldfont)); +1386a1689,1692 +> +> #ifdef OGL +> ogl_init_font(font); +> #endif diff --git a/2d/disc.c b/2d/disc.c new file mode 100644 index 00000000..9a280c01 --- /dev/null +++ b/2d/disc.c @@ -0,0 +1,95 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#include +#include "u_mem.h" + +#include "gr.h" +#include "grdef.h" + +int gr_disk(fix xc1,fix yc1,fix r1) +{ + int p,x, y, xc, yc, r; + + r = f2i(r1); + xc = f2i(xc1); + yc = f2i(yc1); + p=3-(r*2); + x=0; + y=r; + + // Big clip + if ( (xc+r) < 0 ) return 1; + if ( (xc-r) > GWIDTH ) return 1; + if ( (yc+r) < 0 ) return 1; + if ( (yc-r) > GHEIGHT ) return 1; + + while(x +#include +#include +#include +#include + +#include +#include + +#include "pa_enabl.h" //$$POLY_ACC +#include "u_mem.h" + +#include "gr.h" +#include "grdef.h" +#include "error.h" + +#include "cfile.h" +#include "mono.h" +#include "byteswap.h" +#include "bitmap.h" + +#if defined(POLY_ACC) +#include "poly_acc.h" +#endif + +#define MAX_OPEN_FONTS 50 +#define FILENAME_LEN 13 + +typedef struct openfont { + char filename[FILENAME_LEN]; + grs_font *ptr; +} openfont; + +//list of open fonts, for use (for now) for palette remapping +openfont open_font[MAX_OPEN_FONTS]; + +#define FONT grd_curcanv->cv_font +#define FG_COLOR grd_curcanv->cv_font_fg_color +#define BG_COLOR grd_curcanv->cv_font_bg_color +#define FWIDTH FONT->ft_w +#define FHEIGHT FONT->ft_h +#define FBASELINE FONT->ft_baseline +#define FFLAGS FONT->ft_flags +#define FMINCHAR FONT->ft_minchar +#define FMAXCHAR FONT->ft_maxchar +#define FDATA FONT->ft_data +#define FCHARS FONT->ft_chars +#define FWIDTHS FONT->ft_widths + +#define BITS_TO_BYTES(x) (((x)+7)>>3) + +int gr_internal_string_clipped(int x, int y, char *s ); +int gr_internal_string_clipped_m(int x, int y, char *s ); + +ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second) +{ + ubyte *p=font->ft_kerndata; + + while (*p!=255) + if (p[0]==first && p[1]==second) + return p; + else p+=3; + + return NULL; + +} + +//takes the character AFTER being offset into font +#define INFONT(_c) ((_c >= 0) && (_c <= FMAXCHAR-FMINCHAR)) + +//takes the character BEFORE being offset into current font +void get_char_width(ubyte c,ubyte c2,int *width,int *spacing) +{ + int letter; + + letter = c-FMINCHAR; + + if (!INFONT(letter)) { //not in font, draw as space + *width=0; + if (FFLAGS & FT_PROPORTIONAL) + *spacing = FWIDTH/2; + else + *spacing = FWIDTH; + return; + } + + if (FFLAGS & FT_PROPORTIONAL) + *width = FWIDTHS[letter]; + else + *width = FWIDTH; + + *spacing = *width; + + if (FFLAGS & FT_KERNED) { + ubyte *p; + + if (!(c2==0 || c2=='\n')) { + int letter2; + + letter2 = c2-FMINCHAR; + + if (INFONT(letter2)) { + + p = find_kern_entry(FONT,letter,letter2); + + if (p) + *spacing = p[2]; + } + } + } +} + +int get_centered_x(char *s) +{ + int w,w2,s2; + + for (w=0;*s!=0 && *s!='\n';s++) { + get_char_width(s[0],s[1],&w2,&s2); + w += s2; + } + + return ((grd_curcanv->cv_bitmap.bm_w - w) / 2); +} + + +int gr_internal_string0(int x, int y, char *s ) +{ + unsigned char * fp; + ubyte * text_ptr, * next_row, * text_ptr1; + int r, BitMask, i, bits, width, spacing, letter, underline; + int skip_lines = 0; + + unsigned int VideoOffset, VideoOffset1; + + VideoOffset1 = y * ROWSIZE + x; + + next_row = s; + + while (next_row != NULL ) + { + text_ptr1 = next_row; + next_row = NULL; + + if (x==0x8000) { //centered + int xx = get_centered_x(text_ptr1); + VideoOffset1 = y * ROWSIZE + xx; + } + + for (r=0; r>= 1; + } + } + + VideoOffset += spacing-width; //for kerning + + text_ptr++; + } + + VideoOffset1 += ROWSIZE; y++; + } + + y += skip_lines; + VideoOffset1 += ROWSIZE * skip_lines; + skip_lines = 0; + } + return 0; +} + +int gr_internal_string0m(int x, int y, char *s ) +{ + unsigned char * fp; + ubyte * text_ptr, * next_row, * text_ptr1; + int r, BitMask, i, bits, width, spacing, letter, underline; + int skip_lines = 0; + + unsigned int VideoOffset, VideoOffset1; + + VideoOffset1 = y * ROWSIZE + x; + + next_row = s; + + while (next_row != NULL ) + { + text_ptr1 = next_row; + next_row = NULL; + + if (x==0x8000) { //centered + int xx = get_centered_x(text_ptr1); + VideoOffset1 = y * ROWSIZE + xx; + } + + for (r=0; r>= 1; + } + } + text_ptr++; + + VideoOffset += spacing-width; + } + + VideoOffset1 += ROWSIZE; y++; + } + y += skip_lines; + VideoOffset1 += ROWSIZE * skip_lines; + skip_lines = 0; + } + return 0; +} + +#ifdef __ENV_MSDOS__ +int gr_internal_string2(int x, int y, char *s ) +{ + unsigned char * fp; + char * text_ptr, * next_row, * text_ptr1; + int r, BitMask, i, bits, width, spacing, letter, underline; + int page_switched, skip_lines = 0; + + unsigned int VideoOffset, VideoOffset1; + + VideoOffset1 = (unsigned int)DATA + y * ROWSIZE + x; + + gr_vesa_setpage(VideoOffset1 >> 16); + + VideoOffset1 &= 0xFFFF; + + next_row = s; + + while (next_row != NULL ) + { + text_ptr1 = next_row; + next_row = NULL; + + if (x==0x8000) { //centered + int xx = get_centered_x(text_ptr1); + VideoOffset1 = y * ROWSIZE + xx; + gr_vesa_setpage(VideoOffset1 >> 16); + VideoOffset1 &= 0xFFFF; + } + + for (r=0; r 0xFFFF ) + { + for (i=0; i< width; i++ ) + { + gr_video_memory[VideoOffset++] = FG_COLOR; + + if (VideoOffset > 0xFFFF ) + { + VideoOffset -= 0xFFFF + 1; + page_switched = 1; + gr_vesa_incpage(); + } + } + } + else + { + for (i=0; i< width; i++ ) + gr_video_memory[VideoOffset++] = FG_COLOR; + } + } + else + { + // fp -- dword + // VideoOffset + // width + + fp += BITS_TO_BYTES(width)*r; + + BitMask = 0; + + if ( VideoOffset+width > 0xFFFF ) + { + for (i=0; i< width; i++ ) + { + if (BitMask==0) { + bits = *fp++; + BitMask = 0x80; + } + + if (bits & BitMask) + gr_video_memory[VideoOffset++] = FG_COLOR; + else + gr_video_memory[VideoOffset++] = BG_COLOR; + + BitMask >>= 1; + + if (VideoOffset > 0xFFFF ) + { + VideoOffset -= 0xFFFF + 1; + page_switched = 1; + gr_vesa_incpage(); + } + + } + } else { + + if (width == 8 ) + { + bits = *fp++; + + if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR; + else gr_video_memory[VideoOffset+0] = BG_COLOR; + + if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR; + else gr_video_memory[VideoOffset+1] = BG_COLOR; + + if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR; + else gr_video_memory[VideoOffset+2] = BG_COLOR; + + if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR; + else gr_video_memory[VideoOffset+3] = BG_COLOR; + + if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR; + else gr_video_memory[VideoOffset+4] = BG_COLOR; + + if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR; + else gr_video_memory[VideoOffset+5] = BG_COLOR; + + if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR; + else gr_video_memory[VideoOffset+6] = BG_COLOR; + + if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR; + else gr_video_memory[VideoOffset+7] = BG_COLOR; + + VideoOffset += 8; + } else { + for (i=0; i< width/2 ; i++ ) + { + if (BitMask==0) { + bits = *fp++; + BitMask = 0x80; + } + + if (bits & BitMask) + gr_video_memory[VideoOffset++] = FG_COLOR; + else + gr_video_memory[VideoOffset++] = BG_COLOR; + BitMask >>= 1; + + + // Unroll twice + + if (BitMask==0) { + bits = *fp++; + BitMask = 0x80; + } + + if (bits & BitMask) + gr_video_memory[VideoOffset++] = FG_COLOR; + else + gr_video_memory[VideoOffset++] = BG_COLOR; + BitMask >>= 1; + } + } + } + } + text_ptr++; + } + + y ++; + VideoOffset1 += ROWSIZE; + + if (VideoOffset1 > 0xFFFF ) { + VideoOffset1 -= 0xFFFF + 1; + if (!page_switched) + gr_vesa_incpage(); + } + } + + y += skip_lines; + VideoOffset1 += ROWSIZE * skip_lines; + skip_lines = 0; + } + return 0; +} + +int gr_internal_string2m(int x, int y, char *s ) +{ + unsigned char * fp; + char * text_ptr, * next_row, * text_ptr1; + int r, BitMask, i, bits, width, spacing, letter, underline; + int page_switched, skip_lines = 0; + + unsigned int VideoOffset, VideoOffset1; + + VideoOffset1 = (unsigned int)DATA + y * ROWSIZE + x; + + gr_vesa_setpage(VideoOffset1 >> 16); + + VideoOffset1 &= 0xFFFF; + + next_row = s; + + while (next_row != NULL ) + { + text_ptr1 = next_row; + next_row = NULL; + + if (x==0x8000) { //centered + int xx = get_centered_x(text_ptr1); + VideoOffset1 = y * ROWSIZE + xx; + gr_vesa_setpage(VideoOffset1 >> 16); + VideoOffset1 &= 0xFFFF; + } + + for (r=0; r 0xFFFF ) + { + for (i=0; i< width; i++ ) + { + gr_video_memory[VideoOffset++] = FG_COLOR; + + if (VideoOffset > 0xFFFF ) + { + VideoOffset -= 0xFFFF + 1; + page_switched = 1; + gr_vesa_incpage(); + } + } + } + else + { + for (i=0; i< width; i++ ) + gr_video_memory[VideoOffset++] = FG_COLOR; + } + } + else + { + fp += BITS_TO_BYTES(width)*r; + + BitMask = 0; + + if ( VideoOffset+width > 0xFFFF ) + { + for (i=0; i< width; i++ ) + { + if (BitMask==0) { + bits = *fp++; + BitMask = 0x80; + } + + if (bits & BitMask) + gr_video_memory[VideoOffset++] = FG_COLOR; + else + VideoOffset++; + + BitMask >>= 1; + + if (VideoOffset > 0xFFFF ) + { + VideoOffset -= 0xFFFF + 1; + page_switched = 1; + gr_vesa_incpage(); + } + + } + } else { + for (i=0; i< width; i++ ) + { + if (BitMask==0) { + bits = *fp++; + BitMask = 0x80; + } + + if (bits & BitMask) + gr_video_memory[VideoOffset++] = FG_COLOR; + else + VideoOffset++;; + BitMask >>= 1; + } + } + } + text_ptr++; + + VideoOffset += spacing-width; + } + + y ++; + VideoOffset1 += ROWSIZE; + + if (VideoOffset1 > 0xFFFF ) { + VideoOffset1 -= 0xFFFF + 1; + if (!page_switched) + gr_vesa_incpage(); + } + } + + y += skip_lines; + VideoOffset1 += ROWSIZE * skip_lines; + skip_lines = 0; + } + return 0; +} + +#endif // __ENV_MSDOS__ + +#if defined(POLY_ACC) +int gr_internal_string5(int x, int y, char *s ) +{ + unsigned char * fp; + ubyte * text_ptr, * next_row, * text_ptr1; + int r, BitMask, i, bits, width, spacing, letter, underline; + int skip_lines = 0; + + unsigned int VideoOffset, VideoOffset1; + + pa_flush(); + VideoOffset1 = y * ROWSIZE + x * PA_BPP; + + next_row = s; + + while (next_row != NULL ) + { + text_ptr1 = next_row; + next_row = NULL; + + if (x==0x8000) { //centered + int xx = get_centered_x(text_ptr1); + VideoOffset1 = y * ROWSIZE + xx * PA_BPP; + } + + for (r=0; r>= 1; + } + } + + VideoOffset += PA_BPP * (spacing-width); //for kerning + + text_ptr++; + } + + VideoOffset1 += ROWSIZE; y++; + } + + y += skip_lines; + VideoOffset1 += ROWSIZE * skip_lines; + skip_lines = 0; + } + return 0; +} + +int gr_internal_string5m(int x, int y, char *s ) +{ + unsigned char * fp; + ubyte * text_ptr, * next_row, * text_ptr1; + int r, BitMask, i, bits, width, spacing, letter, underline; + int skip_lines = 0; + + unsigned int VideoOffset, VideoOffset1; + + pa_flush(); + VideoOffset1 = y * ROWSIZE + x * PA_BPP; + + next_row = s; + + while (next_row != NULL ) + { + text_ptr1 = next_row; + next_row = NULL; + + if (x==0x8000) { //centered + int xx = get_centered_x(text_ptr1); + VideoOffset1 = y * ROWSIZE + xx * PA_BPP; + } + + for (r=0; r>= 1; + } + } + text_ptr++; + + VideoOffset += PA_BPP * (spacing-width); + } + + VideoOffset1 += ROWSIZE; y++; + } + y += skip_lines; + VideoOffset1 += ROWSIZE * skip_lines; + skip_lines = 0; + } + return 0; +} +#endif + +//a bitmap for the character +grs_bitmap char_bm = { + 0,0,0,0, //x,y,w,h + BM_LINEAR, //type + BM_FLAG_TRANSPARENT, //flags + 0, //rowsize + NULL, //data + 0 //selector +}; + +int gr_internal_color_string(int x, int y, char *s ) +{ + unsigned char * fp; + ubyte * text_ptr, * next_row, * text_ptr1; + int width, spacing,letter; + int xx,yy; + + char_bm.bm_h = FHEIGHT; //set height for chars of this font + + next_row = s; + + yy = y; + + + while (next_row != NULL) + { + text_ptr1 = next_row; + next_row = NULL; + + text_ptr = text_ptr1; + + xx = x; + + if (xx==0x8000) //centered + xx = get_centered_x(text_ptr); + + while (*text_ptr) + { + if (*text_ptr == '\n' ) + { + next_row = &text_ptr[1]; + yy += FHEIGHT; + break; + } + + letter = *text_ptr-FMINCHAR; + + get_char_width(text_ptr[0],text_ptr[1],&width,&spacing); + + if (!INFONT(letter)) { //not in font, draw as space + xx += spacing; + text_ptr++; + continue; + } + + if (FFLAGS & FT_PROPORTIONAL) + fp = FCHARS[letter]; + else + fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT; + + char_bm.bm_w = char_bm.bm_rowsize = width; + + char_bm.bm_data = fp; + gr_bitmapm(xx,yy,&char_bm); + + xx += spacing; + + text_ptr++; + } + + } + return 0; +} + +int gr_string(int x, int y, char *s ) +{ + int w, h, aw; + int clipped=0; + + Assert(FONT != NULL); + + if ( x == 0x8000 ) { + if ( y<0 ) clipped |= 1; + gr_get_string_size(s, &w, &h, &aw ); + // for x, since this will be centered, only look at + // width. + if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1; + if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1; + + if ( (y+h) < 0 ) clipped |= 2; + if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2; + + } else { + if ( (x<0) || (y<0) ) clipped |= 1; + gr_get_string_size(s, &w, &h, &aw ); + if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1; + if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1; + if ( (x+w) < 0 ) clipped |= 2; + if ( (y+h) < 0 ) clipped |= 2; + if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2; + if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2; + } + + if ( !clipped ) + return gr_ustring(x, y, s ); + + if ( clipped & 2 ) { + // Completely clipped... + mprintf( (1, "Text '%s' at (%d,%d) is off screen!\n", s, x, y )); + return 0; + } + + if ( clipped & 1 ) { + // Partially clipped... + //mprintf( (0, "Text '%s' at (%d,%d) is getting clipped!\n", s, x, y )); + } + + // Partially clipped... + + if (FFLAGS & FT_COLOR) + return gr_internal_color_string( x, y, s); + + if ( BG_COLOR == -1) + return gr_internal_string_clipped_m( x, y, s ); + + return gr_internal_string_clipped( x, y, s ); +} + +int gr_ustring(int x, int y, char *s ) +{ + if (FFLAGS & FT_COLOR) { + + return gr_internal_color_string(x,y,s); + + } + else + switch( TYPE ) + { + case BM_LINEAR: + if ( BG_COLOR == -1) + return gr_internal_string0m(x,y,s); + else + return gr_internal_string0(x,y,s); +#ifdef __ENV_MSDOS__ + case BM_SVGA: + if ( BG_COLOR == -1) + return gr_internal_string2m(x,y,s); + else + return gr_internal_string2(x,y,s); +#endif // __ENV_MSDOS__ +#if defined(POLY_ACC) + case BM_LINEAR15: + if ( BG_COLOR == -1) + return gr_internal_string5m(x,y,s); + else + return gr_internal_string5(x,y,s); +#endif + } + + return 0; +} + + +void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width ) +{ + int i = 0, longest_width = 0; + int width,spacing; + + *string_height = FHEIGHT; + *string_width = 0; + *average_width = FWIDTH; + + if (s != NULL ) + { + *string_width = 0; + while (*s) + { +// if (*s == CC_UNDERLINE) +// s++; + while (*s == '\n') + { + s++; + *string_height += FHEIGHT; + *string_width = 0; + } + + if (*s == 0) break; + + // 1 = next byte specifies color, so skip the 1 and the color value + if (*s == CC_COLOR) + s += 2; + else if (*s == CC_LSPACING) { + *string_height += *(s+1)-'0'; + s += 2; + } else { + get_char_width(s[0],s[1],&width,&spacing); + *string_width += spacing; + if (*string_width > longest_width) + longest_width = *string_width; + i++; + s++; + } + } + } + *string_width = longest_width; +} + + +int gr_uprintf( int x, int y, char * format, ... ) +{ + char buffer[1000]; + va_list args; + + va_start(args, format ); + vsprintf(buffer,format,args); + return gr_ustring( x, y, buffer ); +} + +int gr_printf( int x, int y, char * format, ... ) +{ + char buffer[1000]; + va_list args; + + va_start(args, format ); + vsprintf(buffer,format,args); + return gr_string( x, y, buffer ); +} + +void gr_close_font( grs_font * font ) +{ + if (font) + { + int fontnum; + + //find font in list + for (fontnum=0;fontnumft_chars ) + d_free( font->ft_chars ); + d_free( font ); + + } +} + +//remap (by re-reading) all the color fonts +void gr_remap_color_fonts() +{ + int fontnum; + + for (fontnum=0;fontnumft_flags & FT_COLOR)) + gr_remap_font(font,open_font[fontnum].filename); + } +} + +void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq ); +void decode_data_asm(ubyte *data, int num_pixels, ubyte * colormap, int * count ); +#ifdef __WATCOMC__ +#pragma aux decode_data_asm parm [esi] [ecx] [edi] [ebx] modify exact [esi edi eax ebx ecx] = \ +"again_ddn:" \ + "xor eax,eax" \ + "mov al,[esi]" \ + "inc dword ptr [ebx+eax*4]" \ + "mov al,[edi+eax]" \ + "mov [esi],al" \ + "inc esi" \ + "dec ecx" \ + "jne again_ddn" + +#endif + +grs_font * gr_init_font( char * fontname ) +{ + static int first_time=1; + grs_font *font; + int i,fontnum; + unsigned char * ptr; + int nchars; + CFILE *fontfile; + char file_id[4]; + int datasize; //size up to (but not including) palette + + if (first_time) { + int i; + for (i=0;ift_w = SWAPSHORT(font->ft_w); + font->ft_h = SWAPSHORT(font->ft_h); + font->ft_flags = SWAPSHORT(font->ft_flags); + font->ft_bytewidth = SWAPSHORT(font->ft_bytewidth); + font->ft_data = (ubyte *)SWAPINT((int)(font->ft_data)); + font->ft_chars = (ubyte **)SWAPINT((int)(font->ft_chars)); + font->ft_widths = (short *)SWAPINT((int)(font->ft_widths)); + font->ft_kerndata = (ubyte *)SWAPINT((int)(font->ft_kerndata)); +#endif + + nchars = font->ft_maxchar-font->ft_minchar+1; + + if (font->ft_flags & FT_PROPORTIONAL) { + + font->ft_widths = (short *) (((int) font->ft_widths) + ((ubyte *) font)); + +#ifdef MACINTOSH + for (i = 0; i < nchars; i++) + font->ft_widths[i] = SWAPSHORT(font->ft_widths[i]); +#endif + + font->ft_data = ((int) font->ft_data) + ((ubyte *) font); + + font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *)); + + ptr = font->ft_data; + + for (i=0; i< nchars; i++ ) { + font->ft_chars[i] = ptr; + if (font->ft_flags & FT_COLOR) + ptr += font->ft_widths[i] * font->ft_h; + else + ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h; + } + + } else { + + font->ft_data = ((unsigned char *) font) + sizeof(*font); + + font->ft_chars = NULL; + font->ft_widths = NULL; + + ptr = font->ft_data + (nchars * font->ft_w * font->ft_h); + } + + if (font->ft_flags & FT_KERNED) + font->ft_kerndata = ((int) font->ft_kerndata) + ((ubyte *) font); + + + if (font->ft_flags & FT_COLOR) { //remap palette + ubyte palette[256*3]; + ubyte colormap[256]; + int freq[256]; + + cfread(palette,3,256,fontfile); //read the palette + +#ifdef MACINTOSH // swap the first and last palette entries (black and white) + { + int i; + ubyte c; + + for (i = 0; i < 3; i++) { + c = palette[i]; + palette[i] = palette[765+i]; + palette[765+i] = c; + } + +// we also need to swap the data entries as well. black is white and white is black + + for (i = 0; i < ptr-font->ft_data; i++) { + if (font->ft_data[i] == 0) + font->ft_data[i] = 255; + else if (font->ft_data[i] == 255) + font->ft_data[i] = 0; + } + + } +#endif + + build_colormap_good( (ubyte *)&palette, colormap, freq ); + + colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // chaged from colormap[255] = 255 to this for macintosh + + decode_data_asm(font->ft_data, ptr-font->ft_data, colormap, freq ); + + } + + cfclose(fontfile); + + //set curcanv vars + + FONT = font; + FG_COLOR = 0; + BG_COLOR = 0; + + return font; + +} + +//remap a font by re-reading its data & palette +void gr_remap_font( grs_font *font, char * fontname ) +{ + int i; + int nchars; + CFILE *fontfile; + char file_id[4]; + int datasize; //size up to (but not including) palette + int data_ofs,data_len; + + if (! (font->ft_flags & FT_COLOR)) + return; + + fontfile = cfopen(fontname, "rb"); + + if (!fontfile) + Error( "Can't open font file %s", fontname ); + + cfread( file_id, 1, 4, fontfile ); + datasize = cfile_read_int(fontfile); + + + if ((file_id[0] != 'P') || + (file_id[1] != 'S') || + (file_id[2] != 'F') || + (file_id[3] != 'N')) + Error( "File %s is not a font file", fontname ); + + nchars = font->ft_maxchar-font->ft_minchar+1; + + //compute data length + data_len = 0; + if (font->ft_flags & FT_PROPORTIONAL) { + + for (i=0; i< nchars; i++ ) { + if (font->ft_flags & FT_COLOR) + data_len += font->ft_widths[i] * font->ft_h; + else + data_len += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h; + } + + } else + data_len = nchars * font->ft_w * font->ft_h; + + data_ofs = font->ft_data - ((ubyte *) font); + + cfseek(fontfile,data_ofs,SEEK_CUR); + cfread(font->ft_data,1,data_len,fontfile); //read raw data + + if (font->ft_flags & FT_COLOR) { //remap palette + ubyte palette[256*3]; + ubyte colormap[256]; + int freq[256]; + + cfseek(fontfile,-sizeof(palette),SEEK_END); + + cfread(palette,3,256,fontfile); //read the palette + +#ifdef MACINTOSH // swap the first and last palette entries (black and white) + { + int i; + ubyte c; + + for (i = 0; i < 3; i++) { + c = palette[i]; + palette[i] = palette[765+i]; + palette[765+i] = c; + } + +// we also need to swap the data entries as well. black is white and white is black + + for (i = 0; i < data_len; i++) { + if (font->ft_data[i] == 0) + font->ft_data[i] = 255; + else if (font->ft_data[i] == 255) + font->ft_data[i] = 0; + } + + } +#endif + + build_colormap_good( (ubyte *)&palette, colormap, freq ); + + colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255; + + decode_data_asm(font->ft_data, data_len, colormap, freq ); + + + } + + cfclose(fontfile); +} + + +void gr_set_fontcolor( int fg, int bg ) +{ + FG_COLOR = fg; + BG_COLOR = bg; +} + +void gr_set_curfont( grs_font * new ) +{ + FONT = new; +} + + +int gr_internal_string_clipped(int x, int y, char *s ) +{ + unsigned char * fp; + char * text_ptr, * next_row, * text_ptr1; + int r, BitMask, i, bits, width, spacing, letter, underline; + int x1 = x, last_x; + + next_row = s; + + while (next_row != NULL ) + { + text_ptr1 = next_row; + next_row = NULL; + + x = x1; + if (x==0x8000) //centered + x = get_centered_x(text_ptr1); + + last_x = x; + + for (r=0; r>= 1; + } + } + + x += spacing-width; //for kerning + + text_ptr++; + } + y++; + } + } + return 0; +} + +int gr_internal_string_clipped_m(int x, int y, char *s ) +{ + unsigned char * fp; + char * text_ptr, * next_row, * text_ptr1; + int r, BitMask, i, bits, width, spacing, letter, underline; + int x1 = x, last_x; + + next_row = s; + + while (next_row != NULL ) + { + text_ptr1 = next_row; + next_row = NULL; + + x = x1; + if (x==0x8000) //centered + x = get_centered_x(text_ptr1); + + last_x = x; + + for (r=0; r>= 1; + } + } + + x += spacing-width; //for kerning + + text_ptr++; + } + y++; + } + } + return 0; +} diff --git a/2d/gpixel.c b/2d/gpixel.c new file mode 100644 index 00000000..736c97a5 --- /dev/null +++ b/2d/gpixel.c @@ -0,0 +1,76 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#include +#include "u_mem.h" + +#include "gr.h" +#include "grdef.h" +#ifdef __MSDOS__ +#include "modex.h" +#include "vesa.h" +#endif + +unsigned char gr_ugpixel( grs_bitmap * bitmap, int x, int y ) +{ +#ifdef __MSDOS__ + switch(bitmap->bm_type) + { + case BM_LINEAR: +#endif + return bitmap->bm_data[ bitmap->bm_rowsize*y + x ]; +#ifdef __MSDOS__ + case BM_MODEX: + x += bitmap->bm_x; + y += bitmap->bm_y; + gr_modex_setplane( x & 3 ); + return gr_video_memory[(bitmap->bm_rowsize * y) + (x/4)]; + case BM_SVGA: + { + unsigned int offset; + offset = (unsigned int)bitmap->bm_data + (unsigned int)bitmap->bm_rowsize * y + x; + gr_vesa_setpage( offset >> 16 ); + return gr_video_memory[offset & 0xFFFF]; + } + } + return 0; +#endif +} + +unsigned char gr_gpixel( grs_bitmap * bitmap, int x, int y ) +{ + if ((x<0) || (y<0) || (x>=bitmap->bm_w) || (y>=bitmap->bm_h)) return 0; +#ifdef __MSDOS__ + switch(bitmap->bm_type) + { + case BM_LINEAR: +#endif + return bitmap->bm_data[ bitmap->bm_rowsize*y + x ]; +#ifdef __MSDOS__ + case BM_MODEX: + x += bitmap->bm_x; + y += bitmap->bm_y; + gr_modex_setplane( x & 3 ); + return gr_video_memory[(bitmap->bm_rowsize * y) + (x/4)]; + case BM_SVGA: + { + unsigned int offset; + offset = (unsigned int)bitmap->bm_data + (unsigned int)bitmap->bm_rowsize * y + x; + gr_vesa_setpage( offset >> 16 ); + return gr_video_memory[offset & 0xFFFF]; + } + } + return 0; +#endif +} + diff --git a/2d/ibitblt.c b/2d/ibitblt.c new file mode 100644 index 00000000..e858570d --- /dev/null +++ b/2d/ibitblt.c @@ -0,0 +1,192 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * Routines to to inverse bitblitting -- well not really. + * We don't inverse bitblt like in the PC, but this code + * does set up a structure that blits around the cockpit + * +*/ + +#include + +#include +#include "pstypes.h" +#include "gr.h" +#include "grdef.h" +#include "ibitblt.h" +#include "error.h" +//added 05/17/99 Matt Mueller +#include "u_mem.h" +//end addition -MM + +#define FIND_START 1 +#define FIND_STOP 2 + +#define MAX_WIDTH 1280 +#define MAX_SCANLINES 1024 +#define MAX_HOLES 10 + +static short start_points[MAX_SCANLINES][MAX_HOLES]; +static short hole_length[MAX_SCANLINES][MAX_HOLES]; +static double *scanline = NULL; + +// adb: gr_linear_movsd assumes c >= 4 +#define gr_linear_movsd(s,d,c) memcpy(d,s,c) + +void gr_ibitblt(grs_bitmap *src_bmp, grs_bitmap *dest_bmp, ubyte pixel_double) +{ + int x, y, sw, sh, srowsize, drowsize, dstart, sy, dy; + ubyte *src, *dest; + short *current_hole, *current_hole_length; + +// variable setup + + sw = src_bmp->bm_w; + sh = src_bmp->bm_h; + srowsize = src_bmp->bm_rowsize; + drowsize = dest_bmp->bm_rowsize; + src = src_bmp->bm_data; + dest = dest_bmp->bm_data; + + sy = 0; + while (start_points[sy][0] == -1) { + sy++; + dest += drowsize; + } + + if (pixel_double) { + ubyte *scan = (ubyte *)scanline; // set up for byte processing of scanline + + dy = sy; + for (y = sy; y < sy + sh; y++) { + gr_linear_rep_movsd_2x(src, scan, sw); + current_hole = start_points[dy]; + current_hole_length = hole_length[dy]; + for (x = 0; x < MAX_HOLES; x++) { + if (*current_hole == -1) + break; + dstart = *current_hole; + gr_linear_movsd(&(scan[dstart]), &(dest[dstart]), *current_hole_length); + current_hole++; + current_hole_length++; + } + dy++; + dest += drowsize; + current_hole = start_points[dy]; + current_hole_length = hole_length[dy]; + for (x = 0;x < MAX_HOLES; x++) { + if (*current_hole == -1) + break; + dstart = *current_hole; + gr_linear_movsd(&(scan[dstart]), &(dest[dstart]), *current_hole_length); + current_hole++; + current_hole_length++; + } + dy++; + dest += drowsize; + src += srowsize; + } + } else { + Assert(sw <= MAX_WIDTH); + Assert(sh <= MAX_SCANLINES); + for (y = sy; y < sy + sh; y++) { + for (x = 0; x < MAX_HOLES; x++) { + if (start_points[y][x] == -1) + break; + dstart = start_points[y][x]; + gr_linear_movsd(&(src[dstart]), &(dest[dstart]), hole_length[y][x]); + } + dest += drowsize; + src += srowsize; + } + } +} + +void gr_ibitblt_create_mask(grs_bitmap *mask_bmp, int sx, int sy, int sw, int sh, int srowsize) +{ + int x, y; + ubyte mode; + int count = 0; + + Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) ); + + for (y = 0; y < MAX_SCANLINES; y++) { + for (x = 0; x < MAX_HOLES; x++) { + start_points[y][x] = -1; + hole_length[y][x] = -1; + } + } + + for (y = sy; y < sy+sh; y++) { + count = 0; + mode = FIND_START; + for (x = sx; x < sx + sw; x++) { + if ((mode == FIND_START) && (mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x] == TRANSPARENCY_COLOR)) { + start_points[y][count] = x; + mode = FIND_STOP; + } else if ((mode == FIND_STOP) && (mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x] != TRANSPARENCY_COLOR)) { + hole_length[y][count] = x - start_points[y][count]; + count++; + mode = FIND_START; + } + } + if (mode == FIND_STOP) { + hole_length[y][count] = x - start_points[y][count]; + count++; + } + Assert(count <= MAX_HOLES); + } +} + +//added 7/11/99 by adb to prevent memleaks +static void free_scanline(void) +{ + if (scanline) d_free(scanline); +} +//end additions - adb + + +void gr_ibitblt_find_hole_size(grs_bitmap *mask_bmp, int *minx, int *miny, int *maxx, int *maxy) +{ + ubyte c; + int x, y, count = 0; + + Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) ); + Assert( mask_bmp->bm_flags&BM_FLAG_TRANSPARENT ); + + *minx = mask_bmp->bm_w - 1; + *maxx = 0; + *miny = mask_bmp->bm_h - 1; + *maxy = 0; + + //changed 7/11/99 by adb to prevent memleaks + if (scanline == NULL) { + scanline = (double *)d_malloc(sizeof(double) * (MAX_WIDTH / sizeof(double))); + atexit(free_scanline); + } + //end changes - adb + + for (y = 0; y < mask_bmp->bm_h; y++) { + for (x = 0; x < mask_bmp->bm_w; x++) { + c = mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x]; + if (c == TRANSPARENCY_COLOR) { // don't look for transparancy color here. + count++; + if (x < *minx) *minx = x; + if (y < *miny) *miny = y; + if (x > *maxx) *maxx = x; + if (y > *maxy) *maxy = y; + } + } + } + Assert (count); +} diff --git a/2d/line.c b/2d/line.c new file mode 100644 index 00000000..3b28ed3f --- /dev/null +++ b/2d/line.c @@ -0,0 +1,320 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * Graphical routines for drawing lines. + * + */ + +#include +#include + +#include "u_mem.h" + +#include "gr.h" +#include "grdef.h" +#include "fix.h" + +#include "clip.h" + +#ifdef __MSDOS__ +#include "modex.h" +#endif +#ifdef OGL +#include "ogl_init.h" +#endif + + +/* +Symmetric Double Step Line Algorithm +by Brian Wyvill +from "Graphics Gems", Academic Press, 1990 +*/ + +/* non-zero flag indicates the pixels needing EXCHG back. */ +void plot(int x,int y,int flag) +{ if (flag) + gr_upixel(y, x); + else + gr_upixel(x, y); +} + +int gr_hline(int x1, int x2, int y) +{ int i; + + if (x1 > x2) EXCHG(x1,x2); + for (i=x1; i<=x2; i++ ) + gr_upixel( i, y ); + return 0; +} + +int gr_vline(int y1, int y2, int x) +{ int i; + if (y1 > y2) EXCHG(y1,y2); + for (i=y1; i<=y2; i++ ) + gr_upixel( x, i ); + return 0; +} + +void gr_universal_uline(int a1, int b1, int a2, int b2) +{ + int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left; + int x1, y1; + int sign_x = 1, sign_y = 1, step, reverse, i; + + if (a1==a2) { + gr_vline(b1,b2,a1); + return; + } + + if (b1==b2) { + gr_hline(a1,a2,b1); + return; + } + + dx = a2 - a1; + dy = b2 - b1; + + if (dx < 0) { + sign_x = -1; + dx *= -1; + } + if (dy < 0) { + sign_y = -1; + dy *= -1; + } + + /* decide increment sign by the slope sign */ + if (sign_x == sign_y) + step = 1; + else + step = -1; + + if (dy > dx) { /* chooses axis of greatest movement (make * dx) */ + EXCHG(a1, b1); + EXCHG(a2, b2); + EXCHG(dx, dy); + reverse = 1; + } else + reverse = 0; + /* note error check for dx==0 should be included here */ + if (a1 > a2) { /* start from the smaller coordinate */ + x = a2; + y = b2; + x1 = a1; + y1 = b1; + } else { + x = a1; + y = b1; + x1 = a2; + y1 = b2; + } + + + /* Note dx=n implies 0 - n or (dx+1) pixels to be set */ + /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */ + /* In fact (dx-1)/4 as 2 pixels are already plottted */ + xend = (dx - 1) / 4; + pixels_left = (dx - 1) % 4; /* number of pixels left over at the + * end */ + plot(x, y, reverse); + plot(x1, y1, reverse); /* plot first two points */ + incr2 = 4 * dy - 2 * dx; + if (incr2 < 0) { /* slope less than 1/2 */ + c = 2 * dy; + incr1 = 2 * c; + D = incr1 - dx; + + for (i = 0; i < xend; i++) { /* plotting loop */ + ++x; + --x1; + if (D < 0) { + /* pattern 1 forwards */ + plot(x, y, reverse); + plot(++x, y, reverse); + /* pattern 1 backwards */ + plot(x1, y1, reverse); + plot(--x1, y1, reverse); + D += incr1; + } else { + if (D < c) { + /* pattern 2 forwards */ + plot(x, y, reverse); + plot(++x, y += step, reverse); + /* pattern 2 backwards */ + plot(x1, y1, reverse); + plot(--x1, y1 -= step, reverse); + } else { + /* pattern 3 forwards */ + plot(x, y += step, reverse); + plot(++x, y, reverse); + /* pattern 3 backwards */ + plot(x1, y1 -= step, reverse); + plot(--x1, y1, reverse); + } + D += incr2; + } + } /* end for */ + + /* plot last pattern */ + if (pixels_left) { + if (D < 0) { + plot(++x, y, reverse); /* pattern 1 */ + if (pixels_left > 1) + plot(++x, y, reverse); + if (pixels_left > 2) + plot(--x1, y1, reverse); + } else { + if (D < c) { + plot(++x, y, reverse); /* pattern 2 */ + if (pixels_left > 1) + plot(++x, y += step, reverse); + if (pixels_left > 2) + plot(--x1, y1, reverse); + } else { + /* pattern 3 */ + plot(++x, y += step, reverse); + if (pixels_left > 1) + plot(++x, y, reverse); + if (pixels_left > 2) + plot(--x1, y1 -= step, reverse); + } + } + } /* end if pixels_left */ + } + /* end slope < 1/2 */ + else { /* slope greater than 1/2 */ + c = 2 * (dy - dx); + incr1 = 2 * c; + D = incr1 + dx; + for (i = 0; i < xend; i++) { + ++x; + --x1; + if (D > 0) { + /* pattern 4 forwards */ + plot(x, y += step, reverse); + plot(++x, y += step, reverse); + /* pattern 4 backwards */ + plot(x1, y1 -= step, reverse); + plot(--x1, y1 -= step, reverse); + D += incr1; + } else { + if (D < c) { + /* pattern 2 forwards */ + plot(x, y, reverse); + plot(++x, y += step, reverse); + + /* pattern 2 backwards */ + plot(x1, y1, reverse); + plot(--x1, y1 -= step, reverse); + } else { + /* pattern 3 forwards */ + plot(x, y += step, reverse); + plot(++x, y, reverse); + /* pattern 3 backwards */ + plot(x1, y1 -= step, reverse); + plot(--x1, y1, reverse); + } + D += incr2; + } + } /* end for */ + /* plot last pattern */ + if (pixels_left) { + if (D > 0) { + plot(++x, y += step, reverse); /* pattern 4 */ + if (pixels_left > 1) + plot(++x, y += step, reverse); + if (pixels_left > 2) + plot(--x1, y1 -= step, reverse); + } else { + if (D < c) { + plot(++x, y, reverse); /* pattern 2 */ + if (pixels_left > 1) + plot(++x, y += step, reverse); + if (pixels_left > 2) + plot(--x1, y1, reverse); + } else { + /* pattern 3 */ + plot(++x, y += step, reverse); + if (pixels_left > 1) + plot(++x, y, reverse); + if (pixels_left > 2) { + if (D > c) /* step 3 */ + plot(--x1, y1 -= step, reverse); + else /* step 2 */ + plot(--x1, y1, reverse); + } + } + } + } + } +} + + +//unclipped version just calls clipping version for now +int gr_uline(fix _a1, fix _b1, fix _a2, fix _b2) +{ + int a1,b1,a2,b2; + a1 = f2i(_a1); b1 = f2i(_b1); a2 = f2i(_a2); b2 = f2i(_b2); + switch(TYPE) + { +#ifdef OGL + case BM_OGL: + ogl_ulinec(a1,b1,a2,b2,COLOR); + return 0; +#endif + case BM_LINEAR: + #ifdef NO_ASM + gr_universal_uline( a1,b1,a2,b2); + #else + gr_linear_line( a1, b1, a2, b2 ); + #endif + return 0; +#ifdef __MSDOS__ + case BM_MODEX: + modex_line_x1 = a1+XOFFSET; + modex_line_y1 = b1+YOFFSET; + modex_line_x2 = a2+XOFFSET; + modex_line_y2 = b2+YOFFSET; + modex_line_Color = grd_curcanv->cv_color; + gr_modex_line(); + return 0; + default: + gr_universal_uline( a1, b1, a2, b2 ); + return 0; +#endif + } + return 2; +} + +// Returns 0 if drawn with no clipping, 1 if drawn but clipped, and +// 2 if not drawn at all. + +int gr_line(fix a1, fix b1, fix a2, fix b2) +{ + int x1, y1, x2, y2; + int clipped=0; + + x1 = i2f(MINX); + y1 = i2f(MINY); + x2 = i2f(MAXX); + y2 = i2f(MAXY); + + CLIPLINE(a1,b1,a2,b2,x1,y1,x2,y2,return 2,clipped=1, FSCALE ); + + gr_uline( a1, b1, a2, b2 ); + + return clipped; + +} + + diff --git a/2d/linear.asm b/2d/linear.asm new file mode 100644 index 00000000..7c1a43ea --- /dev/null +++ b/2d/linear.asm @@ -0,0 +1,485 @@ +;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +;SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +;IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +;FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +; +; $Source: /cvs/cvsroot/d2x/2d/linear.asm,v $ +; $Revision: 1.1.1.1 $ +; $Author: bradleyb $ +; $Date: 2001-01-19 03:29:57 $ +; +; Routines to access linear VGA memory +; +; $Log: not supported by cvs2svn $ +; Revision 1.1.1.1 1999/06/14 21:57:07 donut +; Import of d1x 1.37 source. +; +; Revision 1.20 1994/11/28 17:08:30 john +; Took out some unused functions in linear.asm, moved +; gr_linear_movsd from linear.asm to bitblt.c, made sure that +; the code in ibiblt.c sets the direction flags before rep movsing. +; +; Revision 1.19 1994/11/27 22:57:56 john +; Took out some code that was never called. +; +; Revision 1.18 1994/09/12 14:40:16 john +; Neatend. +; +; Revision 1.17 1994/07/27 18:30:30 john +; Took away the blending table. +; +; Revision 1.16 1994/04/08 16:59:28 john +; Add fading poly's; Made palette fade 32 instead of 16. +; +; Revision 1.15 1993/12/21 20:10:03 john +; *** empty log message *** +; +; Revision 1.14 1993/12/21 19:58:31 john +; added selector stuff +; +; Revision 1.13 1993/12/21 11:40:51 john +; *** empty log message *** +; +; Revision 1.12 1993/12/09 15:01:52 john +; Changed palette stuff majorly +; +; Revision 1.11 1993/12/08 16:41:02 john +; *** empty log message *** +; +; Revision 1.10 1993/12/08 11:50:17 john +; Fixed bug with gr_init +; +; Revision 1.9 1993/12/07 12:32:12 john +; moved bmd_palette to gr_palette +; +; Revision 1.8 1993/12/03 12:11:25 john +; *** empty log message *** +; +; Revision 1.7 1993/11/16 11:29:08 john +; *** empty log message *** +; +; Revision 1.6 1993/10/15 16:22:13 john +; *** empty log message *** +; +; Revision 1.5 1993/09/29 16:15:28 john +; added assembler linear_line +; +; Revision 1.4 1993/09/26 18:59:27 john +; fade stuff +; +; Revision 1.3 1993/09/21 14:00:59 john +; added code to save 43/50 line text modes. +; +; Revision 1.2 1993/09/16 17:28:06 john +; added code to save/restore video mode +; +; Revision 1.1 1993/09/08 11:41:30 john +; Initial revision +; +; +; + + +[BITS 32] + +section .data + ; Put data here +%ifdef __ENV_LINUX__ +%define _gr_var_color gr_var_color +%define _gr_var_bitmap gr_var_bitmap +%define _gr_var_bwidth gr_var_bwidth +%endif + + global _gr_var_color + global _gr_var_bitmap + global _gr_var_bwidth + _gr_var_color dd 0 + _gr_var_bitmap dd 0 + _gr_var_bwidth dd 0 + + ; Local variables for gr_linear_line_ + AdjUp dd 0 ;error term adjust up on each advance + AdjDown dd 0 ;error term adjust down when error term turns over + WholeStep dd 0 ;minimum run length + XAdvance dd 0 ;1 or -1, for direction in which X advances + XStart dd 0 + YStart dd 0 + XEnd dd 0 + YEnd dd 0 + +section .text +; Fast run length slice line drawing implementation for mode 0x13, the VGA's +; 320x200 256-color mode. +; Draws a line between the specified endpoints in color Color. + + +global _gr_linear_line +global gr_linear_line +_gr_linear_line: +gr_linear_line: + + cld + + push ebx ;preserve C register variables + push esi + push edi + push ebp + + mov eax,[esp+20] + mov edx,[esp+24] + mov ebx,[esp+28] + mov ecx,[esp+32] + mov [XStart], eax + mov [YStart], edx + mov [XEnd], ebx + mov [YEnd], ecx + + mov ebp, [_gr_var_bwidth] + +; We'll draw top to bottom, to reduce the number of cases we have to handle, +; and to make lines between the same endpoints always draw the same pixels. + + mov eax,[YStart] + cmp eax,[YEnd] + jle LineIsTopToBottom + xchg [YEnd], eax ;swap endpoints + mov [YStart], eax + mov ebx, [XStart] + xchg [XEnd], ebx + mov [XStart], ebx + +LineIsTopToBottom: + +; Point EDI to the first pixel to draw. + mov edx,ebp + mul edx ;[YStart] * ebp + mov esi, [XStart] + mov edi, esi + add edi, [_gr_var_bitmap] + add edi, eax ;EDI = [YStart] * ebp + [XStart] + ; = offset of initial pixel + +; Figure out how far we're going vertically (guaranteed to be positive). + mov ecx, [YEnd] + sub ecx, [YStart] ;ECX = YDelta + +; Figure out whether we're going left or right, and how far we're going +; horizontally. In the process, special-case vertical lines, for speed and +; to avoid nasty boundary conditions and division by 0. + + mov edx, [XEnd] + sub edx, esi ;XDelta + jnz NotVerticalLine ;XDelta == 0 means vertical line + ;it is a vertical line + ;yes, special case vertical line + + mov eax, [_gr_var_color] +VLoop: + mov [edi],al + add edi,ebp + dec ecx + jns VLoop + jmp Done + +; Special-case code for horizontal lines. + +IsHorizontalLine: + mov eax, [_gr_var_color] + mov ah,al ;duplicate in high byte for word access + and ebx,ebx ;left to right? + jns DirSet ;yes + sub edi, edx ;currently right to left, point to left end so we + ; can go left to right (avoids unpleasantness with + ; right to left REP STOSW) +DirSet: + mov ecx, edx + inc ecx ;# of pixels to draw + + shr ecx, 1 ;# of words to draw + rep stosw ;do as many words as possible + adc ecx, ecx + rep stosb ;do the odd byte, if there is one + + jmp Done + +; Special-case code for diagonal lines. + +IsDiagonalLine: + mov eax, [_gr_var_color] + add ebx, ebp ;advance distance from one pixel to next + +DLoop: + mov [edi],al + add edi, ebx + dec ecx + jns DLoop + jmp Done + +NotVerticalLine: + mov ebx,1 ;assume left to right, so [XAdvance] = 1 + ;***leaves flags unchanged*** + jns LeftToRight ;left to right, all set + neg ebx ;right to left, so [XAdvance] = -1 + neg edx ;|XDelta| + +LeftToRight: +; Special-case horizontal lines. + + and ecx, ecx ;YDelta == 0? + jz IsHorizontalLine ;yes + +; Special-case diagonal lines. + cmp ecx, edx ;YDelta == XDelta? + jz IsDiagonalLine ;yes + +; Determine whether the line is X or Y major, and handle accordingly. + cmp edx, ecx + jae XMajor + jmp YMajor + +; X-major (more horizontal than vertical) line. + +XMajor: + and ebx,ebx ;left to right? + jns DFSet ;yes, CLD is already set + std ;right to left, so draw backwards +DFSet: + mov eax,edx ;XDelta + sub edx,edx ;prepare for division + div ecx ;EAX = XDelta/YDelta + ; (minimum # of pixels in a run in this line) + ;EDX = XDelta % YDelta + mov ebx,edx ;error term adjust each time Y steps by 1; + add ebx,ebx ; used to tell when one extra pixel should be + mov [AdjUp], ebx ; drawn as part of a run, to account for + ; fractional steps along the X axis per + ; 1-pixel steps along Y + mov esi, ecx ;error term adjust when the error term turns + add esi, esi ; over, used to factor out the X step made at + mov [AdjDown], esi ; that time + +; Initial error term; reflects an initial step of 0.5 along the Y axis. + sub edx, esi ;(XDelta % YDelta) - (YDelta * 2) + ;DX = initial error term +; The initial and last runs are partial, because Y advances only 0.5 for +; these runs, rather than 1. Divide one full run, plus the initial pixel, +; between the initial and last runs. + mov esi, ecx ;SI = YDelta + mov ecx, eax ;whole step (minimum run length) + shr ecx,1 + inc ecx ;initial pixel count = (whole step / 2) + 1; + ; (may be adjusted later). This is also the + ; final run pixel count + push ecx ;remember final run pixel count for later +; If the basic run length is even and there's no fractional advance, we have +; one pixel that could go to either the initial or last partial run, which +; we'll arbitrarily allocate to the last run. +; If there is an odd number of pixels per run, we have one pixel that can't +; be allocated to either the initial or last partial run, so we'll add 0.5 to +; the error term so this pixel will be handled by the normal full-run loop. + add edx,esi ;assume odd length, add YDelta to error term + ; (add 0.5 of a pixel to the error term) + test al,1 ;is run length even? + jnz XMajorAdjustDone ;no, already did work for odd case, all set + sub edx,esi ;length is even, undo odd stuff we just did + and ebx,ebx ;is the adjust up equal to 0? + jnz XMajorAdjustDone ;no (don't need to check for odd length, + ; because of the above test) + dec ecx ;both conditions met; make initial run 1 + ; shorter + +XMajorAdjustDone: + mov [WholeStep],eax ;whole step (minimum run length) + mov eax, [_gr_var_color] ;AL = drawing color +; Draw the first, partial run of pixels. + rep stosb ;draw the final run + add edi,ebp ;advance along the minor axis (Y) +; Draw all full runs. + cmp esi,1 ;are there more than 2 scans, so there are + ; some full runs? (SI = # scans - 1) + jna XMajorDrawLast ;no, no full runs + dec edx ;adjust error term by -1 so we can use + ; carry test + shr esi,1 ;convert from scan to scan-pair count + jnc XMajorFullRunsOddEntry ;if there is an odd number of scans, + ; do the odd scan now +XMajorFullRunsLoop: + mov ecx, [WholeStep] ;run is at least this long + add edx,ebx ;advance the error term and add an extra + jnc XMajorNoExtra ; pixel if the error term so indicates + inc ecx ;one extra pixel in run + sub edx,[AdjDown] ;reset the error term +XMajorNoExtra: + rep stosb ;draw this scan line's run + add edi,ebp ;advance along the minor axis (Y) +XMajorFullRunsOddEntry: ;enter loop here if there is an odd number + ; of full runs + mov ecx,[WholeStep] ;run is at least this long + add edx,ebx ;advance the error term and add an extra + jnc XMajorNoExtra2 ; pixel if the error term so indicates + inc ecx ;one extra pixel in run + sub edx,[AdjDown] ;reset the error term +XMajorNoExtra2: + rep stosb ;draw this scan line's run + add edi,ebp ;advance along the minor axis (Y) + + dec esi + jnz XMajorFullRunsLoop +; Draw the final run of pixels. +XMajorDrawLast: + pop ecx ;get back the final run pixel length + rep stosb ;draw the final run + + cld ;restore normal direction flag + jmp Done +; Y-major (more vertical than horizontal) line. +YMajor: + mov [XAdvance],ebx ;remember which way X advances + mov eax,ecx ;YDelta + mov ecx,edx ;XDelta + sub edx,edx ;prepare for division + div ecx ;EAX = YDelta/XDelta + ; (minimum # of pixels in a run in this line) + ;EDX = YDelta % XDelta + mov ebx,edx ;error term adjust each time X steps by 1; + add ebx,ebx ; used to tell when one extra pixel should be + mov [AdjUp],ebx ; drawn as part of a run, to account for + ; fractional steps along the Y axis per + ; 1-pixel steps along X + mov esi,ecx ;error term adjust when the error term turns + add esi,esi ; over, used to factor out the Y step made at + mov [AdjDown], esi ; that time + +; Initial error term; reflects an initial step of 0.5 along the X axis. + sub edx,esi ;(YDelta % XDelta) - (XDelta * 2) + ;DX = initial error term +; The initial and last runs are partial, because X advances only 0.5 for +; these runs, rather than 1. Divide one full run, plus the initial pixel, +; between the initial and last runs. + mov esi,ecx ;SI = XDelta + mov ecx,eax ;whole step (minimum run length) + shr ecx,1 + inc ecx ;initial pixel count = (whole step / 2) + 1; + ; (may be adjusted later) + push ecx ;remember final run pixel count for later + +; If the basic run length is even and there's no fractional advance, we have +; one pixel that could go to either the initial or last partial run, which +; we'll arbitrarily allocate to the last run. +; If there is an odd number of pixels per run, we have one pixel that can't +; be allocated to either the initial or last partial run, so we'll add 0.5 to +; the error term so this pixel will be handled by the normal full-run loop. + add edx,esi ;assume odd length, add XDelta to error term + test al,1 ;is run length even? + jnz YMajorAdjustDone ;no, already did work for odd case, all set + sub edx,esi ;length is even, undo odd stuff we just did + and ebx,ebx ;is the adjust up equal to 0? + jnz YMajorAdjustDone ;no (don't need to check for odd length, + ; because of the above test) + dec ecx ;both conditions met; make initial run 1 + ; shorter +YMajorAdjustDone: + mov [WholeStep],eax ;whole step (minimum run length) + mov eax,[_gr_var_color] ;AL = drawing color + mov ebx, [XAdvance] ;which way X advances + +; Draw the first, partial run of pixels. +YMajorFirstLoop: + mov [edi],al ;draw the pixel + add edi,ebp ;advance along the major axis (Y) + dec ecx + jnz YMajorFirstLoop + add edi,ebx ;advance along the minor axis (X) +; Draw all full runs. + cmp esi,1 ;# of full runs. Are there more than 2 + ; columns, so there are some full runs? + ; (SI = # columns - 1) + jna YMajorDrawLast ;no, no full runs + dec edx ;adjust error term by -1 so we can use + ; carry test + shr esi,1 ;convert from column to column-pair count + jnc YMajorFullRunsOddEntry ;if there is an odd number of + ; columns, do the odd column now +YMajorFullRunsLoop: + mov ecx,[WholeStep] ;run is at least this long + add edx,[AdjUp] ;advance the error term and add an extra + jnc YMajorNoExtra ; pixel if the error term so indicates + inc ecx ;one extra pixel in run + sub edx,[AdjDown] ;reset the error term +YMajorNoExtra: + ;draw the run +YMajorRunLoop: + mov [edi],al ;draw the pixel + add edi,ebp ;advance along the major axis (Y) + dec ecx + jnz YMajorRunLoop + add edi,ebx ;advance along the minor axis (X) +YMajorFullRunsOddEntry: ;enter loop here if there is an odd number + ; of full runs + mov ecx,[WholeStep] ;run is at least this long + add edx,[AdjUp] ;advance the error term and add an extra + jnc YMajorNoExtra2 ; pixel if the error term so indicates + inc ecx ;one extra pixel in run + sub edx, [AdjDown] ;reset the error term +YMajorNoExtra2: + ;draw the run +YMajorRunLoop2: + mov [edi],al ;draw the pixel + add edi,ebp ;advance along the major axis (Y) + dec ecx + jnz YMajorRunLoop2 + add edi,ebx ;advance along the minor axis (X) + + dec esi + jnz YMajorFullRunsLoop +; Draw the final run of pixels. +YMajorDrawLast: + pop ecx ;get back the final run pixel length +YMajorLastLoop: + mov [edi],al ;draw the pixel + add edi,ebp ;advance along the major axis (Y) + dec ecx + jnz YMajorLastLoop +Done: + pop ebp + pop edi + pop esi + pop ebx;restore C register variables + ret + +global _gr_linear_stosd +global gr_linear_stosd + +_gr_linear_stosd: +gr_linear_stosd: + + ; EAX -> Destination buffer + ; EDX -> Byte to store + ; EBX -> Number of bytes to move + + push ebx + push edi + mov eax,[esp+12] + mov edx,[esp+16] + mov ebx,[esp+20] + mov edi, eax + mov dh, dl + mov ax, dx + shl eax, 16 + mov ax, dx + cld + mov ecx, ebx + shr ecx, 2 + rep stosd + mov ecx, ebx + and ecx, 011b + rep stosb + pop edi + pop ebx + ret diff --git a/2d/linear.h b/2d/linear.h new file mode 100644 index 00000000..811f11c6 --- /dev/null +++ b/2d/linear.h @@ -0,0 +1,476 @@ +#ifndef _LINEAR_H +#define _LINEAR_H + +#ifndef NO_ASM +#ifdef __WATCOMC__ +extern unsigned int gr_var_color; +extern unsigned int gr_var_bwidth; +extern unsigned char * gr_var_bitmap; + +void gr_linear_stosd( void * source, unsigned char color, unsigned int nbytes); +void gr_linear_line( int x0, int y0, int x1, int y1); +void gr_update_buffer( void * sbuf1, void * sbuf2, void * dbuf, int size ); + +// This code aligns edi so that the destination is aligned to a dword boundry before rep movsd +void gr_linear_movsd(ubyte * src, ubyte * dest, unsigned int num_pixels ); +#pragma aux gr_linear_movsd parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx] = \ +" cld " \ +" mov ebx, ecx " \ +" mov eax, edi" \ +" and eax, 011b" \ +" jz d_aligned" \ +" mov ecx, 4" \ +" sub ecx, eax" \ +" sub ebx, ecx" \ +" rep movsb" \ +" d_aligned: " \ +" mov ecx, ebx" \ +" shr ecx, 2" \ +" rep movsd" \ +" mov ecx, ebx" \ +" and ecx, 11b" \ +" rep movsb"; + +void gr_linear_rep_movsdm(void * src, void * dest, unsigned int num_pixels ); +#pragma aux gr_linear_rep_movsdm parm [esi] [edi] [ecx] modify exact [ecx esi edi eax] = \ +"nextpixel:" \ + "mov al,[esi]" \ + "inc esi" \ + "cmp al, 255" \ + "je skip_it" \ + "mov [edi], al" \ +"skip_it:" \ + "inc edi" \ + "dec ecx" \ + "jne nextpixel"; + +void gr_linear_rep_movsdm_faded(void * src, void * dest, unsigned int num_pixels, ubyte fade_value ); +#pragma aux gr_linear_rep_movsdm_faded parm [esi] [edi] [ecx] [ebx] modify exact [ecx esi edi eax ebx] = \ +" xor eax, eax" \ +" mov ah, bl" \ +"nextpixel:" \ + "mov al,[esi]" \ + "inc esi" \ + "cmp al, 255" \ + "je skip_it" \ + "movb al, gr_fade_table[eax]" \ + "movb [edi], al" \ +"skip_it:" \ + "inc edi" \ + "dec ecx" \ + "jne nextpixel"; + + +void gr_linear_rep_movsd_2x(ubyte * src, ubyte * dest, int num_dest_pixels ); +#pragma aux gr_linear_rep_movsd_2x parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx] = \ + "shr ecx, 1" \ + "jnc nextpixel" \ + "mov al, [esi]" \ + "mov [edi], al" \ + "inc esi" \ + "inc edi" \ + "cmp ecx, 0" \ + "je done" \ +"nextpixel:" \ + "mov al,[esi]" \ + "mov ah, al" \ + "mov [edi], ax" \ + "inc esi" \ + "inc edi" \ + "inc edi" \ + "dec ecx" \ + "jne nextpixel" \ +"done:" + + + +void modex_copy_column(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize ); +#pragma aux modex_copy_column parm [esi] [edi] [ecx] [ebx] [edx] modify exact [ecx esi edi] = \ +"nextpixel:" \ + "mov al,[esi]" \ + "add esi, ebx" \ + "mov [edi], al" \ + "add edi, edx" \ + "dec ecx" \ + "jne nextpixel" + +void modex_copy_column_m(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize ); +#pragma aux modex_copy_column_m parm [esi] [edi] [ecx] [ebx] [edx] modify exact [ecx esi edi] = \ +"nextpixel:" \ + "mov al,[esi]" \ + "add esi, ebx" \ + "cmp al, 255" \ + "je skip_itx" \ + "mov [edi], al" \ +"skip_itx:" \ + "add edi, edx" \ + "dec ecx" \ + "jne nextpixel" + +void modex_copy_scanline( ubyte * src, ubyte * dest, int npixels ); +#pragma aux modex_copy_scanline parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx edx] = \ +" mov ebx, ecx " \ +" and ebx, 11b " \ +" shr ecx, 2 " \ +" cmp ecx, 0 " \ +" je no2group " \ +"next4pixels: " \ +" mov al, [esi+8] " \ +" mov ah, [esi+12] " \ +" shl eax, 16 " \ +" mov al, [esi] " \ +" mov ah, [esi+4] " \ +" mov [edi], eax " \ +" add esi, 16 " \ +" add edi, 4 " \ +" dec ecx " \ +" jne next4pixels " \ +"no2group: " \ +" cmp ebx, 0 " \ +" je done2 " \ +"finishend: " \ +" mov al, [esi] " \ +" add esi, 4 " \ +" mov [edi], al " \ +" inc edi " \ +" dec ebx " \ +" jne finishend " \ +"done2: "; + +void modex_copy_scanline_2x( ubyte * src, ubyte * dest, int npixels ); +#pragma aux modex_copy_scanline_2x parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx edx] = \ +" mov ebx, ecx " \ +" and ebx, 11b " \ +" shr ecx, 2 " \ +" cmp ecx, 0 " \ +" je no2group " \ +"next4pixels: " \ +" mov al, [esi+4] " \ +" mov ah, [esi+6] " \ +" shl eax, 16 " \ +" mov al, [esi] " \ +" mov ah, [esi+2] " \ +" mov [edi], eax " \ +" add esi, 8 " \ +" add edi, 4 " \ +" dec ecx " \ +" jne next4pixels " \ +"no2group: " \ +" cmp ebx, 0 " \ +" je done2 " \ +"finishend: " \ +" mov al, [esi] " \ +" add esi, 2 " \ +" mov [edi], al " \ +" inc edi " \ +" dec ebx " \ +" jne finishend " \ +"done2: "; + +#elif defined __GNUC__ +// This code aligns edi so that the destination is aligned to a dword boundry before rep movsd +inline void gr_linear_movsd(ubyte * src, ubyte * dest, unsigned int num_pixels ) { + int dummy[3]; + __asm__ __volatile__ ( +" cld;" +" movl %%ecx, %%ebx;" +" movl %%edi, %%eax;" +" andl $3, %%eax;" +" jz 0f;" +" movl $4, %%ecx;" +" subl %%eax,%%ecx;" +" subl %%ecx,%%ebx;" +" rep; movsb;" +"0: ;" +" movl %%ebx, %%ecx;" +" shrl $2, %%ecx;" +" rep; movsl;" +" movl %%ebx, %%ecx;" +" andl $3, %%ecx;" +" rep; movsb" + : "=S" (dummy[0]), "=D" (dummy[1]), "=c" (dummy[2]) + : "0" (src), "1" (dest), "2" (num_pixels) + : "%eax", "%ebx"); +} + +static inline void gr_linear_rep_movsdm(void * src, void * dest, unsigned int num_pixels ) { + int dummy[3]; + __asm__ __volatile__ ( +"0: ;" +" movb (%%esi), %%al;" +" incl %%esi;" +" cmpb $255, %%al;" +" je 1f;" +" movb %%al,(%%edi);" +"1: ;" +" incl %%edi;" +" decl %%ecx;" +" jne 0b" + : "=S" (dummy[0]), "=D" (dummy[1]), "=c" (dummy[2]) + : "0" (src), "1" (dest), "2" (num_pixels) + : "%eax"); +} + +/* #pragma aux gr_linear_rep_movsdm_faded parm [esi] [edi] [ecx] [ebx] modify exact [ecx esi edi eax ebx] */ +static inline void gr_linear_rep_movsdm_faded(void * src, void * dest, unsigned int num_pixels, ubyte fade_value ) { + int dummy[4]; + __asm__ __volatile__ ( +" xorl %%eax, %%eax;" +" movb %%bl, %%ah;" +"0:;" +" movb (%%esi), %%al;" +" incl %%esi;" +" cmpb $255, %%al;" +" je 1f;" +#ifdef __ENV_LINUX__ +" movb gr_fade_table(%%eax), %%al;" +#else +" movb _gr_fade_table(%%eax), %%al;" +#endif +" movb %%al, (%%edi);" +"1:" +" incl %%edi;" +" decl %%ecx;" +" jne 0b" + : "=S" (dummy[0]), "=D" (dummy[1]), "=c" (dummy[2]), "=b" (dummy[3]) + : "0" (src), "1" (dest), "2" (num_pixels), "3" (fade_value) + : "%eax"); +} + +inline void gr_linear_rep_movsd_2x(ubyte * src, ubyte * dest, unsigned int num_dest_pixels ) { +/* #pragma aux gr_linear_rep_movsd_2x parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx] */ + int dummy[3]; + __asm__ __volatile__ ( + "shrl $1, %%ecx;" + "jnc 0f;" + "movb (%%esi), %%al;" + "movb %%al, (%%edi);" + "incl %%esi;" + "incl %%edi;" + "cmpl $0, %%ecx;" + "je 1f;" +"0: ;" + "movb (%%esi), %%al;" + "movb %%al, %%ah;" + "movw %%ax, (%%edi);" + "incl %%esi;" + "incl %%edi;" + "incl %%edi;" + "decl %%ecx;" + "jne 0b;" +"1:" + : "=S" (dummy[0]), "=D" (dummy[1]), "=c" (dummy[2]) + : "0" (src), "1" (dest), "2" (num_dest_pixels) + : "%eax"); +} + +static inline void modex_copy_column(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize ) { +/*#pragma aux modex_copy_column parm [esi] [edi] [ecx] [ebx] [edx] modify exact [ecx esi edi] = */ + __asm__ __volatile__ ( +"0: ;" + "movb (%%esi), %%al;" + "addl %%ebx, %%esi;" + "movb %%al, (%%edi);" + "addl %%edx, %%edi;" + "decl %%ecx;" + "jne 0b" + : : "S" (src), "D" (dest), "c" (num_pixels), "b" (src_rowsize), "d" (dest_rowsize) + : "%eax", "%ecx", "%esi", "%edi"); +} + +static inline void modex_copy_column_m(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize ) { +/* #pragma aux modex_copy_column_m parm [esi] [edi] [ecx] [ebx] [edx] modify exact [ecx esi edi] = */ + __asm__ __volatile__ ( +"0: ;" + "movb (%%esi), %%al;" + "addl %%ebx, %%esi;" + "cmpb $255, %%al;" + "je 1f;" + "movb %%al, (%%edi);" +"1: ;" + "addl %%edx, %%edi;" + "decl %%ecx;" + "jne 0b" + : : "S" (src), "D" (dest), "c" (num_pixels), "b" (src_rowsize), "d" (dest_rowsize) + : "%eax", "%ecx", "%esi", "%edi"); +} + +static inline void modex_copy_scanline( ubyte * src, ubyte * dest, int npixels ) { +/* #pragma aux modex_copy_scanline parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx edx] */ + __asm__ __volatile__ ( +" movl %%ecx, %%ebx;" +" andl $3, %%ebx;" +" shrl $2, %%ecx;" +" cmpl $0, %%ecx;" +" je 1f;" +"0: ;" +" movb 8(%%esi), %%al;" +" movb 12(%%esi), %%ah;" +" shll $16, %%eax;" +" movb (%%esi), %%al;" +" movb 4(%%esi), %%ah;" +" movl %%eax, (%%edi);" +" addl $16, %%esi;" +" addl $4, %%edi;" +" decl %%ecx;" +" jne 0b;" +"1: ;" +" cmpl $0, %%ebx;" +" je 3f;" +"2: ;" +" movb (%%esi), %%al;" +" addl $4, %%esi;" +" movb %%al, (%%edi);" +" incl %%edi;" +" decl %%ebx;" +" jne 2b;" +"3:" + : : "S" (src), "D" (dest), "c" (npixels) + : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi"); +} + +static inline void modex_copy_scanline_2x( ubyte * src, ubyte * dest, int npixels ) { +/* #pragma aux modex_copy_scanline_2x parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx edx] = */ + __asm__ __volatile__ ( +" movl %%ecx, %%ebx;" +" andl $3, %%ebx;" +" shrl $2, %%ecx;" +" cmpl $0, %%ecx;" +" je 1f;" +"0: ;" +" movb 4(%%esi), %%al;" +" movb 6(%%esi), %%ah;" +" shll $16, %%eax;" +" movb (%%esi), %%al;" +" movb 2(%%esi), %%ah;" +" movl %%eax, (%%edi);" +" addl $8, %%esi;" +" addl $4, %%edi;" +" decl %%ecx;" +" jne 0b;" +"1: ;" +" cmp $0, %%ebx;" +" je 3f;" +"2:" +" movb (%%esi),%%al;" +" addl $2, %%esi;" +" movb %%al, (%%edi);" +" incl %%edi;" +" decl %%ebx;" +" jne 2b;" +"3:" + : : "S" (src), "D" (dest), "c" (npixels) + : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi"); +} +#elif defined _MSC_VER + +extern unsigned int gr_var_color; +extern unsigned int gr_var_bwidth; +extern unsigned char * gr_var_bitmap; + +void gr_linear_stosd( ubyte * source, unsigned char color, unsigned int nbytes); +void gr_linear_line( int x0, int y0, int x1, int y1); +void gr_update_buffer( void * sbuf1, void * sbuf2, void * dbuf, int size ); + +// This code aligns edi so that the destination is aligned to a dword boundry before rep movsd +__inline void gr_linear_movsd(ubyte * src, ubyte * dest, unsigned int num_pixels ) +{ + __asm { + mov esi, [src] + mov edi, [dest] + mov ecx, [num_pixels] + cld + mov ebx, ecx + mov eax, edi + and eax, 011b + jz d_aligned + mov ecx, 4 + sub ecx, eax + sub ebx, ecx + rep movsb +d_aligned: + mov ecx, ebx + shr ecx, 2 + rep movsd + mov ecx, ebx + and ecx, 11b + rep movsb + } +} + +__inline void gr_linear_rep_movsdm(void * src, void * dest, unsigned int num_pixels ) +{ + __asm { + nextpixel: + mov esi, [src] + mov edi, [dest] + mov ecx, [num_pixels] + mov al, [esi] + inc esi + cmp al, 255 + je skip_it + mov [edi], al + skip_it: + inc edi + dec ecx + jne nextpixel + } +} + +__inline void gr_linear_rep_movsdm_faded(void * src, void * dest, unsigned int num_pixels, ubyte fade_value ) +{ + __asm { + mov esi, [src] + mov edi, [dest] + mov ecx, [num_pixels] + movzx ebx, byte ptr [fade_value] + xor eax, eax + mov ah, bl + nextpixel: + mov al, [esi] + inc esi + cmp al, 255 + je skip_it + mov al, gr_fade_table[eax] + mov [edi], al + skip_it: + inc edi + dec ecx + jne nextpixel + } +} + +__inline void gr_linear_rep_movsd_2x(ubyte * src, ubyte * dest, uint num_dest_pixels ) +{ + __asm { + mov esi, [src] + mov edi, [dest] + mov ecx, [num_dest_pixels] + shr ecx, 1 + jnc nextpixel + mov al, [esi] + mov [edi], al + inc esi + inc edi + cmp ecx, 0 + je done +nextpixel: + mov al, [esi] + mov ah, al + mov [edi], ax + inc esi + inc edi + inc edi + dec ecx + jne nextpixel +done: + } +} + +#else +#define NO_ASM 1 // We really do want no assembler... + +#endif +#endif // NO_ASM + +#endif diff --git a/2d/palette.c b/2d/palette.c new file mode 100644 index 00000000..be6f427a --- /dev/null +++ b/2d/palette.c @@ -0,0 +1,229 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * Graphical routines for setting the palette + * + */ + +#include +#include +#include + +#include "pstypes.h" +#include "u_mem.h" +#include "gr.h" +#include "grdef.h" +#include "cfile.h" +#include "error.h" +#include "mono.h" +#include "fix.h" +//added/remove by dph on 1/9/99 +//#include "key.h" +//end remove + +extern int gr_installed; + +ubyte gr_palette[256*3]; +ubyte gr_current_pal[256*3]; +ubyte gr_fade_table[256*34]; + +ubyte gr_palette_gamma = 0; +int gr_palette_gamma_param = 0; +ubyte gr_palette_faded_out = 1; + +extern void gr_palette_load( ubyte * pal ); + +void gr_palette_set_gamma( int gamma ) +{ + if ( gamma < 0 ) gamma = 0; +//added/changed on 10/27/98 by Victor Rachels to increase brightness slider + if ( gamma > 16 ) gamma = 16; //was 8 +//end this section change - Victor Rachels + + if (gr_palette_gamma_param != gamma ) { + gr_palette_gamma_param = gamma; + gr_palette_gamma = gamma; + if (!gr_palette_faded_out) + gr_palette_load( gr_palette ); + } +} + +int gr_palette_get_gamma() +{ + return gr_palette_gamma_param; +} + + +void gr_use_palette_table( char * filename ) +{ + CFILE *fp; + int i,fsize; + + fp = cfopen( filename, "rb" ); + if ( fp==NULL) + Error("Can't open palette file <%s>",filename); + + fsize = cfilelength( fp ); + Assert( fsize == 9472 ); + cfread( gr_palette, 256*3, 1, fp ); + cfread( gr_fade_table, 256*34, 1, fp ); + cfclose(fp); + + // This is the TRANSPARENCY COLOR + for (i=0; i> 15; + + Computed_colors[add_index].r = r; + Computed_colors[add_index].g = g; + Computed_colors[add_index].b = b; + Computed_colors[add_index].color_num = color_num; +} + +void init_computed_colors(void) +{ + int i; + + for (i=0; i 4) { + color_record trec; + trec = Computed_colors[i-1]; + Computed_colors[i-1] = Computed_colors[i]; + Computed_colors[i] = trec; + return Computed_colors[i-1].color_num; + } + return Computed_colors[i].color_num; + } + +// r &= 63; +// g &= 63; +// b &= 63; + + best_value = SQUARE(r-gr_palette[0])+SQUARE(g-gr_palette[1])+SQUARE(b-gr_palette[2]); + best_index = 0; + if (best_value==0) { + add_computed_color(r, g, b, best_index); + return best_index; + } + j=0; + // only go to 255, 'cause we dont want to check the transparent color. + for (i=1; i<254; i++ ) { + j += 3; + value = SQUARE(r-gr_palette[j])+SQUARE(g-gr_palette[j+1])+SQUARE(b-gr_palette[j+2]); + if ( value < best_value ) { + if (value==0) { + add_computed_color(r, g, b, i); + return i; + } + best_value = value; + best_index = i; + } + } + add_computed_color(r, g, b, best_index); + return best_index; +} + +int gr_find_closest_color_15bpp( int rgb ) +{ + return gr_find_closest_color( ((rgb>>10)&31)*2, ((rgb>>5)&31)*2, (rgb&31)*2 ); +} + + +int gr_find_closest_color_current( int r, int g, int b ) +{ + int i, j; + int best_value, best_index, value; + +// r &= 63; +// g &= 63; +// b &= 63; + + best_value = SQUARE(r-gr_current_pal[0])+SQUARE(g-gr_current_pal[1])+SQUARE(b-gr_current_pal[2]); + best_index = 0; + if (best_value==0) + return best_index; + + j=0; + // only go to 255, 'cause we dont want to check the transparent color. + for (i=1; i<254; i++ ) { + j += 3; + value = SQUARE(r-gr_current_pal[j])+SQUARE(g-gr_current_pal[j+1])+SQUARE(b-gr_current_pal[j+2]); + if ( value < best_value ) { + if (value==0) + return i; + best_value = value; + best_index = i; + } + } + return best_index; +} + +void gr_make_cthru_table(ubyte * table, ubyte r, ubyte g, ubyte b ) +{ + int i; + ubyte r1, g1, b1; + + for (i=0; i<256; i++ ) { + r1 = gr_palette[i*3+0] + r; + if ( r1 > 63 ) r1 = 63; + g1 = gr_palette[i*3+1] + g; + if ( g1 > 63 ) g1 = 63; + b1 = gr_palette[i*3+2] + b; + if ( b1 > 63 ) b1 = 63; + table[i] = gr_find_closest_color( r1, g1, b1 ); + } +} + diff --git a/2d/pcx.c b/2d/pcx.c new file mode 100644 index 00000000..d6dbc630 --- /dev/null +++ b/2d/pcx.c @@ -0,0 +1,315 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * + * Routines to read/write pcx images. + * + */ + +#include +#include +#include +#include + +#include "gr.h" +#include "grdef.h" +#include "u_mem.h" +#include "pcx.h" +#include "cfile.h" + +int pcx_encode_byte(ubyte byt, ubyte cnt, FILE * fid); +int pcx_encode_line(ubyte *inBuff, int inLen, FILE * fp); + +/* PCX Header data type */ +typedef struct { + ubyte Manufacturer; + ubyte Version; + ubyte Encoding; + ubyte BitsPerPixel; + short Xmin; + short Ymin; + short Xmax; + short Ymax; + short Hdpi; + short Vdpi; + ubyte ColorMap[16][3]; + ubyte Reserved; + ubyte Nplanes; + short BytesPerLine; + ubyte filler[60]; +} PCXHeader; + + +int pcx_read_bitmap( char * filename, grs_bitmap * bmp,int bitmap_type ,ubyte * palette ) +{ + PCXHeader header; + CFILE * PCXfile; + int i, row, col, count, xsize, ysize; + ubyte data, *pixdata; + + PCXfile = cfopen( filename , "rb" ); + if ( !PCXfile ) + return PCX_ERROR_OPENING; + + // read 128 char PCX header + if (cfread( &header, sizeof(PCXHeader), 1, PCXfile )!=1) { + cfclose( PCXfile ); + return PCX_ERROR_NO_HEADER; + } + + // Is it a 256 color PCX file? + if ((header.Manufacturer != 10)||(header.Encoding != 1)||(header.Nplanes != 1)||(header.BitsPerPixel != 8)||(header.Version != 5)) { + cfclose( PCXfile ); + return PCX_ERROR_WRONG_VERSION; + } + + // Find the size of the image + xsize = header.Xmax - header.Xmin + 1; + ysize = header.Ymax - header.Ymin + 1; + + if ( bitmap_type == BM_LINEAR ) { + if ( bmp->bm_data == NULL ) { + gr_init_bitmap_alloc (bmp, bitmap_type, 0, 0, xsize, ysize, xsize); + } + } + + if ( bmp->bm_type == BM_LINEAR ) { + for (row=0; row< ysize ; row++) { + pixdata = &bmp->bm_data[bmp->bm_rowsize*row]; + for (col=0; col< xsize ; ) { + if (cfread( &data, 1, 1, PCXfile )!=1 ) { + cfclose( PCXfile ); + return PCX_ERROR_READING; + } + if ((data & 0xC0) == 0xC0) { + count = data & 0x3F; + if (cfread( &data, 1, 1, PCXfile )!=1 ) { + cfclose( PCXfile ); + return PCX_ERROR_READING; + } + memset( pixdata, data, count ); + pixdata += count; + col += count; + } else { + *pixdata++ = data; + col++; + } + } + } + } else { + for (row=0; row< ysize ; row++) { + for (col=0; col< xsize ; ) { + if (cfread( &data, 1, 1, PCXfile )!=1 ) { + cfclose( PCXfile ); + return PCX_ERROR_READING; + } + if ((data & 0xC0) == 0xC0) { + count = data & 0x3F; + if (cfread( &data, 1, 1, PCXfile )!=1 ) { + cfclose( PCXfile ); + return PCX_ERROR_READING; + } + for (i=0;i>= 2; + } + } else { + cfclose( PCXfile ); + return PCX_ERROR_NO_PALETTE; + } + } + cfclose(PCXfile); + return PCX_ERROR_NONE; +} + +int pcx_write_bitmap( char * filename, grs_bitmap * bmp, ubyte * palette ) +{ + int retval; + int i; + ubyte data; + PCXHeader header; + FILE * PCXfile; + + memset( &header, 0, sizeof( PCXHeader ) ); + + header.Manufacturer = 10; + header.Encoding = 1; + header.Nplanes = 1; + header.BitsPerPixel = 8; + header.Version = 5; + header.Xmax = bmp->bm_w-1; + header.Ymax = bmp->bm_h-1; + header.BytesPerLine = bmp->bm_w; + + PCXfile = fopen( filename , "wb" ); + if ( !PCXfile ) + return PCX_ERROR_OPENING; + + if ( fwrite( &header, sizeof( PCXHeader ), 1, PCXfile ) != 1 ) { + fclose( PCXfile ); + return PCX_ERROR_WRITING; + } + + for (i=0; ibm_h; i++ ) { + if (!pcx_encode_line( &bmp->bm_data[bmp->bm_rowsize*i], bmp->bm_w, PCXfile )) { + fclose( PCXfile ); + return PCX_ERROR_WRITING; + } + } + + // Mark an extended palette + data = 12; + if (fwrite( &data, 1, 1, PCXfile )!=1) { + fclose( PCXfile ); + return PCX_ERROR_WRITING; + } + + // Write the extended palette + for (i=0; i<768; i++ ) + palette[i] <<= 2; + + retval = fwrite( palette, 768, 1, PCXfile ); + + for (i=0; i<768; i++ ) + palette[i] >>= 2; + + if (retval !=1) { + fclose( PCXfile ); + return PCX_ERROR_WRITING; + } + + fclose( PCXfile ); + return PCX_ERROR_NONE; + +} + +// returns number of bytes written into outBuff, 0 if failed +int pcx_encode_line(ubyte *inBuff, int inLen, FILE * fp) +{ + ubyte this, last; + int srcIndex, i; + register int total; + register ubyte runCount; // max single runlength is 63 + total = 0; + last = *(inBuff); + runCount = 1; + + for (srcIndex = 1; srcIndex < inLen; srcIndex++) { + this = *(++inBuff); + if (this == last) { + runCount++; // it encodes + if (runCount == 63) { + if (!(i=pcx_encode_byte(last, runCount, fp))) + return(0); + total += i; + runCount = 0; + } + } else { // this != last + if (runCount) { + if (!(i=pcx_encode_byte(last, runCount, fp))) + return(0); + total += i; + } + last = this; + runCount = 1; + } + } + + if (runCount) { // finish up + if (!(i=pcx_encode_byte(last, runCount, fp))) + return 0; + return total + i; + } + return total; +} + +// subroutine for writing an encoded byte pair +// returns count of bytes written, 0 if error +int pcx_encode_byte(ubyte byt, ubyte cnt, FILE * fid) +{ + if (cnt) { + if ( (cnt==1) && (0xc0 != (0xc0 & byt)) ) { + if(EOF == putc((int)byt, fid)) + return 0; // disk write error (probably full) + return 1; + } else { + if(EOF == putc((int)0xC0 | cnt, fid)) + return 0; // disk write error + if(EOF == putc((int)byt, fid)) + return 0; // disk write error + return 2; + } + } + return 0; +} + +//text for error messges +char pcx_error_messages[] = { + "No error.\0" + "Error opening file.\0" + "Couldn't read PCX header.\0" + "Unsupported PCX version.\0" + "Error reading data.\0" + "Couldn't find palette information.\0" + "Error writing data.\0" +}; + + +//function to return pointer to error message +char *pcx_errormsg(int error_number) +{ + char *p = pcx_error_messages; + + while (error_number--) { + + if (!p) return NULL; + + p += strlen(p)+1; + + } + + return p; +} + +// fullscreen loading, 10/14/99 Jan Bobrowski + +int pcx_read_fullscr(char * filename, ubyte * palette) +{ + int pcx_error; + grs_bitmap bm; + gr_init_bitmap_data(&bm); + pcx_error = pcx_read_bitmap(filename, &bm, BM_LINEAR, palette); + if (pcx_error == PCX_ERROR_NONE) + show_fullscr(&bm); + gr_free_bitmap_data(&bm); + return pcx_error; +} diff --git a/2d/pixel.c b/2d/pixel.c new file mode 100644 index 00000000..ab5cbf6c --- /dev/null +++ b/2d/pixel.c @@ -0,0 +1,97 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * + * Graphical routines for setting a pixel. + * + */ + +#include +#include "u_mem.h" + +#include "gr.h" +#include "grdef.h" +#include "vesa.h" +#include "modex.h" +#ifdef OGL +#include "ogl_init.h" +#endif + + +#ifndef D1XD3D +void gr_upixel( int x, int y ) +{ + switch (TYPE) + { +#ifdef OGL + case BM_OGL: + ogl_upixelc(x,y,COLOR); + return; +#endif + case BM_LINEAR: + DATA[ ROWSIZE*y+x ] = COLOR; + return; +#ifdef __MSDOS__ + case BM_MODEX: + gr_modex_setplane( (x+XOFFSET) & 3 ); + gr_video_memory[(ROWSIZE * (y+YOFFSET)) + ((x+XOFFSET)>>2)] = COLOR; + return; + case BM_SVGA: + gr_vesa_pixel( COLOR, (unsigned int)DATA + (unsigned int)ROWSIZE * y + x); + return; +#endif + } +} +#endif + +void gr_pixel( int x, int y ) +{ + if ((x<0) || (y<0) || (x>=GWIDTH) || (y>=GHEIGHT)) return; + gr_upixel (x, y); +} + +#ifndef D1XD3D +inline void gr_bm_upixel( grs_bitmap * bm, int x, int y, unsigned char color ) +{ + switch (bm->bm_type) + { +#ifdef OGL + case BM_OGL: + ogl_upixelc(bm->bm_x+x,bm->bm_y+y,color); + return; +#endif + case BM_LINEAR: + bm->bm_data[ bm->bm_rowsize*y+x ] = color; + return; +#ifdef __MSDOS__ + case BM_MODEX: + x += bm->bm_x; + y += bm->bm_y; + gr_modex_setplane( x & 3 ); + gr_video_memory[(bm->bm_rowsize * y) + (x/4)] = color; + return; + case BM_SVGA: + gr_vesa_pixel(color,(unsigned int)bm->bm_data + (unsigned int)bm->bm_rowsize * y + x); + return; +#endif + } +} +#endif + +void gr_bm_pixel( grs_bitmap * bm, int x, int y, unsigned char color ) +{ + if ((x<0) || (y<0) || (x>=bm->bm_w) || (y>=bm->bm_h)) return; + gr_bm_upixel (bm, x, y, color); +} + + diff --git a/2d/poly.c b/2d/poly.c new file mode 100644 index 00000000..62bd27b1 --- /dev/null +++ b/2d/poly.c @@ -0,0 +1,280 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * + * Graphical routines for drawing polygons. + * + */ + +#include +#include "u_mem.h" +#include "gr.h" +#include "grdef.h" + +//#define USE_POLY_CODE 1 + +#define MAX_SCAN_LINES 1200 + +#ifdef USE_POLY_CODE + +int y_edge_list[MAX_SCAN_LINES]; + +void gr_upoly(int nverts, int *vert ) +{ + int temp; + int startx, stopx; // X coordinates of both ends of current edge. + int firstx, firsty; // Saved copy of the first vertex to connect later. + int dx_dy; // Slope of current edge. + int miny, maxy; + + int starty, stopy; // Y coordinates of both ends of current edge. + + int x1, x2, i; + + // Find the min and max rows to clear out the minimun y_edge_list. + // (Is it worth it?) + maxy = vert[1]; + miny = vert[1]; + + for (i=3; i<(nverts*2); i+=2 ) + { + if (vert[i]>maxy) maxy=vert[i]; + if (vert[i]>= 16; + miny--; // -1 to be safe + maxy >>= 16; + maxy++; // +1 to be safe + + // Clear only the part of the y_edge_list that w will be using + if (miny < 0) miny = 0; + if (maxy > MAX_SCAN_LINES) maxy = MAX_SCAN_LINES; + + for (i=miny; i> 16; + + do + { + nverts--; + + // Get the beginning coordinates of the current edge. + startx = vert[0]; + starty = vert[1] >> 16; + + // Get the ending coordinates of the current edge. + if (nverts > 0 ) { + stopx = vert[2]; + stopy = vert[3] >> 16; + vert += 2; + } else { + stopx = firstx; // Last edge, uses first vertex as endpoint + stopy = firsty; + } + + if (stopy < starty ) { + temp = stopy; + stopy = starty; + starty = temp; + temp = stopx; + stopx = startx; + startx = temp; + } + + if (stopy == starty ) + { + // Draw a edge going horizontally across screen + x1 = startx>>16; + x2 = stopx>>16; + + if (x2 > x1 ) + //gr_uscanline( x1, x2-1, stopy ); + gr_uscanline( x1, x2, stopy ); + else + //gr_uscanline( x2, x1-1, stopy ); + gr_uscanline( x2, x1, stopy ); + + } else { + + dx_dy = (stopx - startx) / (stopy - starty); + + for (; starty < stopy; starty++ ) + { + if (y_edge_list[starty]==-1) + y_edge_list[starty] = startx; + else { + x1 = y_edge_list[starty]>>16; + x2 = startx>>16; + + if (x2 > x1 ) + //gr_uscanline( x1, x2-1, starty ); + gr_uscanline( x1, x2, starty ); + else + //gr_uscanline( x2, x1-1, starty ); + gr_uscanline( x2, x1, starty ); + } + startx += dx_dy; + } + } + + + } while (nverts > 0); +} + + +void gr_poly(int nverts, int *vert ) +{ + int temp; + int startx, stopx; // X coordinates of both ends of current edge. + int firstx, firsty; // Saved copy of the first vertex to connect later. + int dx_dy; // Slope of current edge. + int miny, maxy; + + int starty, stopy; // Y coordinates of both ends of current edge. + + int x1, x2, i, j; + + // Find the min and max rows to clear out the minimun y_edge_list. + // (Is it worth it?) + maxy = vert[1]; + miny = vert[1]; + + j = 0; + + for (i=3; i<(nverts*2); i+=2 ) + { + if (vert[i]>maxy) { + if ((maxy=vert[i]) > MAXY) j++; + //if (j>1) break; + } + + if (vert[i]1) break; + } + } + + miny >>= 16; + miny--; // -1 to be safe + maxy >>= 16; + maxy++; // +1 to be safe + + if (miny < MINY) miny = MINY; + if (maxy > MAXY) maxy = MAXY+1; + + // Clear only the part of the y_edge_list that w will be using + for (i=miny; i> 16; + + do + { + nverts--; + + // Get the beginning coordinates of the current edge. + startx = vert[0]; + starty = vert[1] >> 16; + + // Get the ending coordinates of the current edge. + if (nverts > 0 ) { + stopx = vert[2]; + stopy = vert[3] >> 16; + vert += 2; + } else { + stopx = firstx; // Last edge, uses first vertex as endpoint + stopy = firsty; + } + + + if (stopy < starty ) { + temp = stopy; + stopy = starty; + starty = temp; + temp = stopx; + stopx = startx; + startx = temp; + } + + if (stopy == starty ) + { + // Draw a edge going horizontally across screen + if ((stopy >= MINY) && (stopy <=MAXY )) { + x1 = startx>>16; + x2 = stopx>>16; + + if (x1 > x2 ) { + temp = x2; + x2 = x1; + x1 = temp; + } + + if ((x1 <= MAXX ) && (x2 >= MINX)) + { + if (x1 < MINX ) x1 = MINX; + if (x2 > MAXX ) x2 = MAXX+1; + //gr_uscanline( x1, x2-1, stopy ); + gr_scanline( x1, x2, stopy ); + } + } + } else { + + dx_dy = (stopx - startx) / (stopy - starty); + + if (starty < MINY ) { + startx = dx_dy*(MINY-starty)+startx; + starty = MINY; + } + + if (stopy > MAXY ) { + stopx = dx_dy*(MAXY-starty)+startx; + stopy = MAXY+1; + } + + for (; starty < stopy; starty++ ) + { if (y_edge_list[starty]==-1) + y_edge_list[starty] = startx; + else { + x1 = y_edge_list[starty]>>16; + x2 = startx>>16; + + if (x1 > x2 ) { + temp = x2; + x2 = x1; + x1 = temp; + } + + if ((x1 <= MAXX ) && (x2 >= MINX)) + { + if (x1 < MINX ) x1 = MINX; + if (x2 > MAXX ) x2 = MAXX+1; + //gr_uscanline( x1, x2-1, starty ); + gr_scanline( x1, x2, starty ); + } + } + startx += dx_dy; + } + } + + + } while (nverts > 0); +} + +#endif + diff --git a/2d/rect.c b/2d/rect.c new file mode 100644 index 00000000..60576b7d --- /dev/null +++ b/2d/rect.c @@ -0,0 +1,70 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * + * Graphical routines for drawing rectangles. + * + */ + +#include +#include "u_mem.h" + +#include "gr.h" +#include "grdef.h" + +#ifdef OGL +#include "ogl_init.h" +#endif + + +void gr_urect(int left,int top,int right,int bot) +{ + int i; + +#ifdef OGL + if (TYPE == BM_OGL) { + ogl_urect(left,top,right,bot); + return; + } +#endif +#ifdef D1XD3D + if (TYPE == BM_DIRECTX) { + if (left <= right && top <= bot) + Win32_Rect (left, top, right, bot, grd_curcanv->cv_bitmap.bm_data, COLOR); + return; + } +#endif + for ( i=top; i<=bot; i++ ) + gr_uscanline( left, right, i ); +} + +void gr_rect(int left,int top,int right,int bot) +{ + int i; + +#ifdef OGL + if (TYPE == BM_OGL) { + ogl_urect(left,top,right,bot); + return; + } +#endif +#ifdef D1XD3D + if (TYPE == BM_DIRECTX) { + if (left <= right && top <= bot) + Win32_Rect (left, top, right, bot, grd_curcanv->cv_bitmap.bm_data, COLOR); + return; + } +#endif + for ( i=top; i<=bot; i++ ) + gr_scanline( left, right, i ); +} diff --git a/2d/rle.c b/2d/rle.c new file mode 100644 index 00000000..02a82dbf --- /dev/null +++ b/2d/rle.c @@ -0,0 +1,663 @@ +/*THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * Changed shorts to ints in parameters. + * + */ + +#ifdef RCS +static char rcsid[] = "$Id: rle.c,v 1.1.1.1 2001-01-19 03:29:57 bradleyb Exp $"; +#endif + +#include +#include +#include +#include + +#include "pstypes.h" +#include "u_mem.h" +#include "mono.h" + + +#include "gr.h" +#include "grdef.h" +#include "error.h" +//#include "key.h" +#include "rle.h" +//#define RLE_CODE 0xC0 +//#define NOT_RLE_CODE 63 + +#define RLE_CODE 0xE0 +#define NOT_RLE_CODE 31 + +void rle_expand_texture_sub( grs_bitmap * bmp, grs_bitmap * rle_temp_bitmap_1 ); + +#ifndef NO_ASM +#ifdef __WATCOMC__ +int gr_rle_decode_asm( ubyte * src, ubyte * dest ); +#pragma aux gr_rle_decode_asm parm [esi] [edi] value [edi] modify exact [eax ebx ecx edx esi edi] = \ +" cld " \ +" xor ecx, ecx " \ +" cld " \ +" jmp NextByte " \ +" " \ +"Unique: " \ +" mov [edi],al " \ +" inc edi " \ +" " \ +"NextByte: " \ +" mov al,[esi] " \ +" inc esi " \ +" " \ +" mov ah, al " \ +" and ah, 0xE0 " \ +" cmp ah, 0xE0 " \ +" jne Unique " \ +" " \ +" mov cl, al " \ +" and cl, 31 " \ +" je done " \ +" " \ +" mov al,[esi] " \ +" inc esi " \ +" mov ah, al " \ +" shr ecx,1 " \ +" rep stosw " \ +" jnc NextByte " \ +" mov [edi],al " \ +" inc edi " \ +" " \ +" jmp NextByte " \ +" " \ +"done: "; + +void rle_stosb(char *dest, int len, int color); +#pragma aux rle_stosb = "cld rep stosb" parm [edi] [ecx] [eax] modify exact [edi ecx]; +#elif defined __GNUC__ +static inline int gr_rle_decode_asm( ubyte * src, ubyte * dest ) { + register int __ret; + int dummy; + __asm__ __volatile__ ( +" cld;" +" xorl %%ecx, %%ecx;" +" jmp 1f;" +"0:;" +" movb %%al,(%%edi);" +" incl %%edi;" +"1:;" +" movb (%%esi), %%al;" +" incl %%esi;" +" movb %%al, %%ah;" +" andb $0xE0, %%ah;" +" cmpb $0xE0, %%ah;" +" jne 0b;" +" movb %%al, %%cl;" +" andb $31, %%cl;" +" je 2f;" +" movb (%%esi), %%al;" +" incl %%esi;" +" movb %%al, %%ah;" +" shrl $1, %%ecx;" +" rep; stosw;" +" jnc 1b;" +" movb %%al, (%%edi);" +" incl %%edi;" +" jmp 1b;" +"2:" +: "=D" (__ret), "=S" (dummy) : "1" (src), "D" (dest) : "%eax", "%ecx"); + return __ret; +} + +static inline void rle_stosb(char *dest, int len, int color) { + int dummy[1]; + __asm__ __volatile__ ( + "cld; rep; stosb" + : "=D" (dummy[0]), "=c" (dummy[1]) + : "0" (dest), "1" (len), "a" (color) ); +} +#elif defined _MSC_VER +__inline int gr_rle_decode_asm( ubyte * src, ubyte * dest ) +{ + int retval; + __asm { + mov esi,[src] + mov edi,[dest] + xor ecx, ecx + cld + jmp NextByte +Unique: + mov [edi], al + inc edi +NextByte: + mov al,[esi] + inc esi + mov ah, al + and ah,0xE0 + cmp ah,0xE0 + jne Unique + + mov cl, al + and cl, 31 + je done + + mov al, [esi] + inc esi + mov ah, al + shr ecx, 1 + rep stosw + jnc NextByte + mov [edi], al + inc edi + jmp NextByte +done: + mov [retval],edi + } + return retval; +} + +__inline void rle_stosb(char *dest, int len, int color) +{ + __asm { + mov edi,[dest] + mov ecx,[len] + mov eax,[color] + cld + rep stosb + } +} + +#else +# undef NO_ASM +# define NO_ASM 1 +/* Well, if inline assembler is not supported for this compiler, we don't + **really** want ASM... */ +#endif +#endif + +#ifdef NO_ASM +void rle_stosb(ubyte *dest, int len, int color) +{ + int i; + for (i=0; i x2 ) { + count = x2-x1+1; + if ( color != 255 ) rle_stosb( dest, count, color ); + return; + } + + if ( color != 255 ) rle_stosb( dest, count, color ); + dest += count; + i += count; + + while( i <= x2 ) { + color = *src++; + if ( color == RLE_CODE ) return; + if ( (color & RLE_CODE) == (RLE_CODE) ) { + count = color & (~RLE_CODE); + color = *src++; + } else { + // unique + count = 1; + } + // we know have '*count' pixels of 'color'. + if ( i+count <= x2 ) { + if ( color != 255 )rle_stosb( dest, count, color ); + i += count; + dest += count; + } else { + count = x2-i+1; + if ( color != 255 )rle_stosb( dest, count, color ); + i += count; + dest += count; + } + + } +} + +void gr_rle_expand_scanline( ubyte *dest, ubyte *src, int x1, int x2 ) +{ + int i = 0; + ubyte count=0; + ubyte color=0; + + if ( x2 < x1 ) return; + + while ( i < x1 ) { + color = *src++; + if ( color == RLE_CODE ) return; + if ( (color & RLE_CODE)==RLE_CODE ) { + count = color & (~RLE_CODE); + color = *src++; + } else { + // unique + count = 1; + } + i += count; + } + count = i - x1; + i = x1; + // we know have '*count' pixels of 'color'. + + if ( x1+count > x2 ) { + count = x2-x1+1; + rle_stosb( dest, count, color ); + return; + } + + rle_stosb( dest, count, color ); + dest += count; + i += count; + + while( i <= x2 ) { + color = *src++; + if ( color == RLE_CODE ) return; + if ( (color & RLE_CODE)==RLE_CODE ) { + count = color & (~RLE_CODE); + color = *src++; + } else { + // unique + count = 1; + } + // we know have '*count' pixels of 'color'. + if ( i+count <= x2 ) { + rle_stosb( dest, count, color ); + i += count; + dest += count; + } else { + count = x2-i+1; + rle_stosb( dest, count, color ); + i += count; + dest += count; + } + } +} + + +int gr_rle_encode( int org_size, ubyte *src, ubyte *dest ) +{ + int i; + ubyte c, oc; + ubyte count; + ubyte *dest_start; + + dest_start = dest; + oc = *src++; + count = 1; + + for (i=1; ibm_w+1)* bmp->bm_h ); + if (rle_data==NULL) return 0; + doffset = 4 + bmp->bm_h; + for (y=0; ybm_h; y++ ) { + d1= gr_rle_getsize( bmp->bm_w, &bmp->bm_data[bmp->bm_w*y] ); + if ( ((doffset+d1) > bmp->bm_w*bmp->bm_h) || (d1 > 255 ) ) { + d_free(rle_data); + return 0; + } + d = gr_rle_encode( bmp->bm_w, &bmp->bm_data[bmp->bm_w*y], &rle_data[doffset] ); + Assert( d==d1 ); + doffset += d; + rle_data[y+4] = d; + } + //mprintf( 0, "Bitmap of size %dx%d, (%d bytes) went down to %d bytes\n", bmp->bm_w, bmp->bm_h, bmp->bm_h*bmp->bm_w, doffset ); + memcpy( rle_data, &doffset, 4 ); + memcpy( bmp->bm_data, rle_data, doffset ); + d_free(rle_data); + bmp->bm_flags |= BM_FLAG_RLE; + return 1; +} + +#define MAX_CACHE_BITMAPS 32 + +typedef struct rle_cache_element { + grs_bitmap * rle_bitmap; + ubyte * rle_data; + grs_bitmap * expanded_bitmap; + int last_used; +} rle_cache_element; + +int rle_cache_initialized = 0; +int rle_counter = 0; +int rle_next = 0; +rle_cache_element rle_cache[MAX_CACHE_BITMAPS]; + +int rle_hits = 0; +int rle_misses = 0; + +void rle_cache_close(void) +{ + if (rle_cache_initialized) { + int i; + rle_cache_initialized = 0; + for (i=0; ibm_flags & BM_FLAG_PAGED_OUT) ); + + lc = rle_counter; + rle_counter++; + if ( rle_counter < lc ) { + for (i=0; i 0)) +// mprintf(( 0, "RLE-CACHE %d%%, H:%d, M:%d\n", (rle_misses*100)/(rle_hits+rle_misses), rle_hits, rle_misses )); + + lowest_count = rle_cache[rle_next].last_used; + least_recently_used = rle_next; + rle_next++; + if ( rle_next >= MAX_CACHE_BITMAPS ) + rle_next = 0; + + for (i=0; iiMagic == BM_MAGIC_NUMBER); +#endif + + sbits = &bmp->bm_data[4 + 64]; + dbits = rle_temp_bitmap_1->bm_data; + + rle_temp_bitmap_1->bm_flags = bmp->bm_flags & (~BM_FLAG_RLE); + + for (i=0; i < 64; i++ ) { +#ifdef NO_ASM + gr_rle_decode(sbits,dbits); +#else + dbits1=(unsigned char *)gr_rle_decode_asm( sbits, dbits ); +#endif + sbits += (int)bmp->bm_data[4+i]; + dbits += 64; +#ifndef NO_ASM + Assert( dbits == dbits1 ); // Get John, bogus rle data! +#endif + } +#ifdef D1XD3D + gr_set_bitmap_data (rle_temp_bitmap_1, rle_temp_bitmap_1->bm_data); +#endif +} + + +void gr_rle_expand_scanline_generic( grs_bitmap * dest, int dx, int dy, ubyte *src, + int x1, int x2, int masked ) +{ + int i = 0, j; + int count=0; + ubyte color=0; + + if ( x2 < x1 ) return; + + while ( i < x1 ) { + color = *src++; + if ( color == RLE_CODE ) return; + if ( (color & RLE_CODE) == RLE_CODE ) { + count = color & NOT_RLE_CODE; + color = *src++; + } else { + // unique + count = 1; + } + i += count; + } + count = i - x1; + i = x1; + // we know have '*count' pixels of 'color'. + + if ( x1+count > x2 ) { + count = x2-x1+1; + if (!masked || color != 255) + for ( j=0; j +#include +#include +#include +#include + +#include "mono.h" +#include "fix.h" +#include "gr.h" +#include "error.h" +#include "rle.h" + +#if 0 +#define TRANSPARENCY_COLOR 255; +#endif + +static int Transparency_color = TRANSPARENCY_COLOR; + +#include "scalea.h" + +void rls_stretch_scanline( char * source, char * dest, int XDelta, int YDelta ); +void rls_stretch_scanline_setup( int XDelta, int YDelta ); +void scale_bitmap_asm(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 ); +void scale_bitmap_asm_rle(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 ); +void scale_bitmap_cc_asm(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 ); +void scale_bitmap_cc_asm_rle(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 ); + +void scale_row_c( ubyte * sbits, ubyte * dbits, int width, fix u, fix du ) +{ + int i; + ubyte c; + + for ( i=0; icv_bitmap; + fix x0, y0, x1, y1; + fix u0, v0, u1, v1; + fix clipped_x0, clipped_y0, clipped_x1, clipped_y1; + fix clipped_u0, clipped_v0, clipped_u1, clipped_v1; + fix xmin, xmax, ymin, ymax; + int dx0, dy0, dx1, dy1; + int dtemp; + // Set initial variables.... + + x0 = vertbuf[0].x; y0 = vertbuf[0].y; + x1 = vertbuf[2].x; y1 = vertbuf[2].y; + + xmin = 0; ymin = 0; + xmax = i2f(dbp->bm_w)-fl2f(.5); ymax = i2f(dbp->bm_h)-fl2f(.5); + + u0 = i2f(0); v0 = i2f(0); + u1 = i2f(bp->bm_w-1); v1 = i2f(bp->bm_h-1); + + // Check for obviously offscreen bitmaps... + if ( (y1<=y0) || (x1<=x0) ) return; + if ( (x1<0 ) || (x0>=xmax) ) return; + if ( (y1<0 ) || (y0>=ymax) ) return; + + clipped_u0 = u0; clipped_v0 = v0; + clipped_u1 = u1; clipped_v1 = v1; + + clipped_x0 = x0; clipped_y0 = y0; + clipped_x1 = x1; clipped_y1 = y1; + + // Clip the left, moving u0 right as necessary + if ( x0 < xmin ) { + clipped_u0 = FIND_SCALED_NUM(xmin,x0,x1,u0,u1); + clipped_x0 = xmin; + } + + // Clip the right, moving u1 left as necessary + if ( x1 > xmax ) { + clipped_u1 = FIND_SCALED_NUM(xmax,x0,x1,u0,u1); + clipped_x1 = xmax; + } + + // Clip the top, moving v0 down as necessary + if ( y0 < ymin ) { + clipped_v0 = FIND_SCALED_NUM(ymin,y0,y1,v0,v1); + clipped_y0 = ymin; + } + + // Clip the bottom, moving v1 up as necessary + if ( y1 > ymax ) { + clipped_v1 = FIND_SCALED_NUM(ymax,y0,y1,v0,v1); + clipped_y1 = ymax; + } + + dx0 = f2i(clipped_x0); dx1 = f2i(clipped_x1); + dy0 = f2i(clipped_y0); dy1 = f2i(clipped_y1); + + if (dx1<=dx0) return; + if (dy1<=dy0) return; + + Assert( dx0>=0 ); + Assert( dy0>=0 ); + Assert( dx1bm_w ); + Assert( dy1bm_h ); + Assert( f2i(u0)<=f2i(u1) ); + Assert( f2i(v0)<=f2i(v1) ); + Assert( f2i(u0)>=0 ); + Assert( f2i(v0)>=0 ); + Assert( u1bm_w) ); + Assert( v1bm_h) ); + + //mprintf( 0, "(%.2f,%.2f) to (%.2f,%.2f) using (%.2f,%.2f) to (%.2f,%.2f)\n", f2fl(clipped_x0), f2fl(clipped_y0), f2fl(clipped_x1), f2fl(clipped_y1), f2fl(clipped_u0), f2fl(clipped_v0), f2fl(clipped_u1), f2fl(clipped_v1) ); + + dtemp = f2i(clipped_u1)-f2i(clipped_u0); + + if ( bp->bm_flags & BM_FLAG_RLE ) { + if ( (dtemp < (f2i(clipped_x1)-f2i(clipped_x0))) && (dtemp>0) ) + scale_bitmap_cc_asm_rle(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1 ); + else + scale_bitmap_asm_rle(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1 ); + } else { + if ( (dtemp < (f2i(clipped_x1)-f2i(clipped_x0))) && (dtemp>0) ) + scale_bitmap_cc_asm(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1 ); + else + scale_bitmap_asm(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1 ); + } +} + + +void scale_bitmap_c(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 ) +{ + fix u, v, du, dv; + int x, y; + ubyte * sbits, * dbits; + + du = (u1-u0) / (x1-x0); + dv = (v1-v0) / (y1-y0); + + v = v0; + + for (y=y0; y<=y1; y++ ) { + sbits = &source_bmp->bm_data[source_bmp->bm_rowsize*f2i(v)]; + dbits = &dest_bmp->bm_data[dest_bmp->bm_rowsize*y+x0]; + u = u0; + v += dv; + for (x=x0; x<=x1; x++ ) { + *dbits++ = sbits[ u >> 16 ]; + u += du; + } + } +} + +void scale_bitmap_asm(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 ) +{ + fix du, dv, v; + int y; + + du = (u1-u0) / (x1-x0); + dv = (v1-v0) / (y1-y0); + + v = v0; + + for (y=y0; y<=y1; y++ ) { + scale_row_asm_transparent( &source_bmp->bm_data[source_bmp->bm_rowsize*f2i(v)], &dest_bmp->bm_data[dest_bmp->bm_rowsize*y+x0], x1-x0+1, u0, du ); + v += dv; + } +} + +ubyte scale_rle_data[640]; + +void decode_row( grs_bitmap * bmp, int y ) +{ + int i, offset=4+bmp->bm_h; + + for (i=0; ibm_data[4+i]; + gr_rle_decode( &bmp->bm_data[offset], scale_rle_data ); +} + +void scale_bitmap_asm_rle(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 ) +{ + fix du, dv, v; + int y, last_row=-1; + + du = (u1-u0) / (x1-x0); + dv = (v1-v0) / (y1-y0); + + v = v0; + + for (y=y0; y<=y1; y++ ) { + if ( f2i(v) != last_row ) { + last_row = f2i(v); + decode_row( source_bmp, last_row ); + } + scale_row_asm_transparent( scale_rle_data, &dest_bmp->bm_data[dest_bmp->bm_rowsize*y+x0], x1-x0+1, u0, du ); + v += dv; + } +} + + +void scale_bitmap_cc_asm(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 ) +{ + fix dv, v; + int y; + + dv = (v1-v0) / (y1-y0); + + rls_stretch_scanline_setup( (int)(x1-x0), f2i(u1)-f2i(u0) ); + if ( scale_ydelta_minus_1 < 1 ) return; + rls_do_cc_setup_asm(); + + v = v0; + + for (y=y0; y<=y1; y++ ) { + scale_source_ptr = &source_bmp->bm_data[source_bmp->bm_rowsize*f2i(v)+f2i(u0)]; + scale_dest_ptr = &dest_bmp->bm_data[dest_bmp->bm_rowsize*y+x0]; + scale_do_cc_scanline(); + v += dv; + } +} + +void scale_bitmap_cc_asm_rle(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 ) +{ + fix dv, v; + int y, last_row = -1; + + dv = (v1-v0) / (y1-y0); + + rls_stretch_scanline_setup( (int)(x1-x0), f2i(u1)-f2i(u0) ); + if ( scale_ydelta_minus_1 < 1 ) return; + rls_do_cc_setup_asm(); + + v = v0; + + for (y=y0; y<=y1; y++ ) { + if ( f2i(v) != last_row ) { + last_row = f2i(v); + decode_row( source_bmp, last_row ); + } + //scale_source_ptr = &source_bmp->bm_data[source_bmp->bm_rowsize*f2i(v)+f2i(u0)]; + scale_source_ptr = &scale_rle_data[f2i(u0)]; + scale_dest_ptr = &dest_bmp->bm_data[dest_bmp->bm_rowsize*y+x0]; + scale_do_cc_scanline(); + v += dv; + } +} + + + +// Run-length slice bitmap scan line stretcher + +void DrawHorizontalRun(char *ScreenPtr, int RunLength, int Color) +{ + int i; + + for (i=0; i 0) + { + RunLength++; + ErrorTerm -= AdjDown; /* reset the error term */ + } + /* Draw this scan line's run */ + + //if ( *source != Transparency_color ) + rep_stosb(dest, RunLength, *source ); + dest += RunLength; + source++; + + } + + /* Draw the final run of pixels */ + //if ( *source != Transparency_color ) + rep_stosb(dest, FinalPixelCount, *source ); + + return; +} + + + + +void rls_stretch_scanline_setup( int XDelta, int YDelta ) +{ + scale_trans_color = Transparency_color & 0xFF; + scale_ydelta_minus_1 = YDelta - 1; + + /* X major line */ + /* Minimum # of pixels in a run in this line */ + scale_whole_step = XDelta / YDelta; + + /* Error term adjust each time Y steps by 1; used to tell when one + extra pixel should be drawn as part of a run, to account for + fractional steps along the X axis per 1-pixel steps along Y */ + scale_adj_up = (XDelta % YDelta) * 2; + + /* Error term adjust when the error term turns over, used to factor + out the X step made at that time */ + scale_adj_down = YDelta * 2; + + /* Initial error term; reflects an initial step of 0.5 along the Y + axis */ + scale_error_term = (XDelta % YDelta) - (YDelta * 2); + + /* The initial and last runs are partial, because Y advances only 0.5 + for these runs, rather than 1. Divide one full run, plus the + initial pixel, between the initial and last runs */ + scale_initial_pixel_count = (scale_whole_step / 2) + 1; + scale_final_pixel_count = scale_initial_pixel_count; + + /* If the basic run length is even and there's no fractional + advance, we have one pixel that could go to either the initial + or last partial run, which we'll arbitrarily allocate to the + last run */ + if ((scale_adj_up == 0) && ((scale_whole_step & 0x01) == 0)) + { + scale_initial_pixel_count--; + } + /* If there're an odd number of pixels per run, we have 1 pixel that can't + be allocated to either the initial or last partial run, so we'll add 0.5 + to error term so this pixel will be handled by the normal full-run loop */ + if ((scale_whole_step & 0x01) != 0) + { + scale_error_term += YDelta; + } + +} + diff --git a/2d/scalea.asm b/2d/scalea.asm new file mode 100644 index 00000000..fa569b52 --- /dev/null +++ b/2d/scalea.asm @@ -0,0 +1,236 @@ +;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +;SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +;IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +;FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +; +; $Source: /cvs/cvsroot/d2x/2d/scalea.asm,v $ +; $Revision: 1.1.1.1 $ +; $Author: bradleyb $ +; $Date: 2001-01-19 03:29:57 $ +; +; Asm inner loop for scaler. +; +; $Log: not supported by cvs2svn $ +; Revision 1.1.1.1 1999/06/14 21:57:07 donut +; Import of d1x 1.37 source. +; +; Revision 1.2 1994/01/12 18:02:52 john +; Asm code for the scaler... first iteration here +; has compiled code that works!! +; +; Revision 1.1 1994/01/12 12:20:11 john +; Initial revision +; +; + + + +[BITS 32] + +[SECTION .data] + + align 4 + + + global _scale_trans_color + global _scale_error_term + global _scale_initial_pixel_count + global _scale_adj_up + global _scale_adj_down + global _scale_final_pixel_count + global _scale_ydelta_minus_1 + global _scale_whole_step + global _scale_source_ptr + global _scale_dest_ptr + + + _scale_trans_color db 0 + _scale_error_term dd 0 + _scale_initial_pixel_count dd 0 + _scale_adj_up dd 0 + _scale_adj_down dd 0 + _scale_final_pixel_count dd 0 + _scale_ydelta_minus_1 dd 0 + _scale_whole_step dd 0 + _scale_source_ptr dd 0 + _scale_dest_ptr dd 0 + _scale_cc_jump_spot dd 0 + _scale_slice_length_1 dd 0 + _scale_slice_length_2 dd 0 + +[SECTION .text] + +global _rls_stretch_scanline_asm + +_rls_stretch_scanline_asm: + cld + pusha + mov esi, [_scale_source_ptr] + mov edi, [_scale_dest_ptr] + mov edx, [_scale_ydelta_minus_1] + mov ebx, [_scale_whole_step] + mov ah, [_scale_trans_color] + mov ebp, [_scale_error_term] + + mov ecx, [_scale_initial_pixel_count] + lodsb + cmp al, ah + je first_pixel_transparent + rep stosb + jmp next_pixel + +first_pixel_transparent: + add edi, ecx + jmp next_pixel + +skip_this_pixel: add edi, ecx + dec edx + jz done + +next_pixel: lodsb ; get next source pixel + mov ecx, ebx + add ebp, [_scale_adj_up] + jle no_inc_error_term + inc ecx + sub ebp, [_scale_adj_down] +no_inc_error_term: + cmp al, ah + je skip_this_pixel + rep stosb ; write source pixel to n locations + dec edx + jnz next_pixel + +done: lodsb + cmp al, ah + je exit_sub + mov ecx, [_scale_final_pixel_count] + rep stosb + +exit_sub: + popa + ret + +global _scale_do_cc_scanline +global _rls_do_cc_setup_asm + +_scale_do_cc_scanline: + cld + pusha + mov esi, [_scale_source_ptr] + mov edi, [_scale_dest_ptr] + mov ah, [_scale_trans_color] + mov ebx, [_scale_slice_length_1] + mov edx, [_scale_slice_length_2] + + mov ecx, [_scale_initial_pixel_count] + + ; Do the first texture pixel + mov ecx, [_scale_initial_pixel_count] + lodsb + cmp al, ah + je @1 + rep stosb +@1: add edi, ecx + + mov ecx, [_scale_cc_jump_spot] + jmp ecx + + ; This is the compiled code to do the middle pixels... +scale_cc_start: mov al, [esi] +scale_cc_changer: db 08bh, 0cbh ;mov ecx, ebx ;<==== CODE CHANGES TO EBX OR EDX !!!!!! + inc esi + cmp al, ah + je @2 + rep stosb + @2: add edi, ecx +scale_cc_end: + +%macro repproc 0 + mov al, [esi] + db 08bh, 0cbh ;mov ecx, ebx ;<==== CODE CHANGES TO EBX OR EDX !!!!!! + inc esi + cmp al, ah + je %%skip + rep stosb +%%skip: add edi, ecx +%endmacro + +%rep 319 +repproc +%endrep +last_cc_instruction: + + mov ecx, [_scale_final_pixel_count] + lodsb + cmp al, ah + je last_one_transparent + rep stosb +last_one_transparent: + + popa + ret + +_rls_do_cc_setup_asm: + + pusha + + mov ebx, [_scale_whole_step] + mov [_scale_slice_length_1], ebx + inc ebx + mov [_scale_slice_length_2], ebx + + mov ebp, [_scale_error_term] + mov edx, [_scale_ydelta_minus_1] + + mov ebx, scale_cc_end + sub ebx, scale_cc_start ; ebx = distance to next changer inst. + + mov eax, [_scale_ydelta_minus_1] + + + imul eax, ebx ; eax = sizeof 1 iteration * numiterations. + + mov edi, last_cc_instruction + sub edi, eax ; edi = address of first iteration that we need + ; to jump to + mov [_scale_cc_jump_spot], edi + + mov ecx, scale_cc_changer + sub ecx, scale_cc_start ; ecx = distance from start to to next changer inst. + + add edi, ecx + +next_pixel1: add ebp, [_scale_adj_up] + jle no_inc_error_term1 + ; Modify code in scale_do_cc_scanline_ to write 'edx' pixels + mov al, byte [edi] + cmp al, 08bh + jne BigError + mov word[edi], 0CA8Bh ; 0x8BCA = mov ecx, edx + add edi, ebx + sub ebp, [_scale_adj_down] + dec edx + jnz next_pixel1 + jmp done1 + +no_inc_error_term1: ; Modify code in scale_do_cc_scanline_ to write 'ebx' pixels + mov al, byte [edi] + cmp al, 08bh + jne BigError + mov word [edi], 0CB8Bh ; 0x8BCB = mov ecx, ebx + add edi, ebx + dec edx + jnz next_pixel1 + +done1: popa + ret + +BigError: int 3 ; Stop, buddy!! + popa + ret diff --git a/2d/scalea.h b/2d/scalea.h new file mode 100644 index 00000000..0b6168b4 --- /dev/null +++ b/2d/scalea.h @@ -0,0 +1,95 @@ +extern char scale_trans_color; +extern int scale_error_term; +extern int scale_initial_pixel_count; +extern int scale_adj_up; +extern int scale_adj_down; +extern int scale_final_pixel_count; +extern int scale_ydelta_minus_1; +extern int scale_whole_step; +extern ubyte * scale_source_ptr; +extern ubyte * scale_dest_ptr; +extern void rls_stretch_scanline_asm(); +extern void scale_do_cc_scanline(); +extern void rls_do_cc_setup_asm(); + +#ifdef __WATCOMC__ +void rep_stosb(char *ScreenPtr, int RunLength, int Color); +#pragma aux rep_stosb = \ +" rep stosb" \ +parm [EDI] [ECX] [EAX]\ +modify []; + +// esi, edi = source, dest +// ecx = width +// ebx = u +// edx = du + +void scale_row_asm_transparent( ubyte * sbits, ubyte * dbits, int width, fix u, fix du ); +#pragma aux scale_row_asm_transparent parm [esi] [edi] [ecx] [ebx] [edx] modify exact [edi eax ebx ecx] = \ +"newpixel: mov eax, ebx " \ +" shr eax, 16 " \ +" mov al, [esi+eax] " \ +" cmp al, 255 " \ +" je skip_it " \ +" mov [edi], al " \ +"skip_it: add ebx, edx " \ +" inc edi " \ +" dec ecx " \ +" jne newpixel " + +void scale_row_asm( ubyte * sbits, ubyte * dbits, int width, fix u, fix du ); +#pragma aux scale_row_asm parm [esi] [edi] [ecx] [ebx] [edx] modify exact [edi eax ebx ecx] = \ +"newpixel1: mov eax, ebx " \ +" shr eax, 16 " \ +" mov al, [esi+eax] " \ +" add ebx, edx " \ +" mov [edi], al " \ +" inc edi " \ +" dec ecx " \ +" jne newpixel1 " + + +void rep_movsb( ubyte * sbits, ubyte * dbits, int width ); +#pragma aux rep_movsb parm [esi] [edi] [ecx] modify exact [esi edi ecx] = \ +"rep movsb" + +#else +static inline void rep_stosb(char *ScreenPtr, int RunLength, int Color) { + __asm__ __volatile__ ("cld; rep; stosb" + : : "D" (ScreenPtr), "c" (RunLength), "a" (Color) : "%ecx", "%edi"); +} +static inline void scale_row_asm_transparent( ubyte * sbits, ubyte * dbits, int width, fix u, fix du ) { + __asm__ __volatile__ ( +"0: movl %%ebx, %%eax;" +" shrl $16, %%eax;" +" movb (%%esi, %%eax), %%al;" +" cmpb $255, %%al;" +" je 1f;" +" movb %%al, (%%edi);" +"1: addl %%edx, %%ebx;" +" incl %%edi;" +" decl %%ecx;" +" jne 0b" + : : "S" (sbits), "D" (dbits), "c" (width), "b" (u), "d" (du) + : "%eax", "%ebx", "%ecx", "%edi"); +} + +static inline void scale_row_asm( ubyte * sbits, ubyte * dbits, int width, fix u, fix du ) { + __asm__ __volatile__ ( +"0: movl %%ebx,%%eax;" +" shrl $16, %%eax;" +" movb (%%esi, %%eax), %%al;" +" addl %%edx, %%ebx;" +" movb %%al, (%%edi);" +" incl %%edi;" +" decl %%ecx;" +" jne 0b" + : : "S" (sbits), "D" (dbits), "c" (width), "b" (u), "d" (du) + : "%eax", "%ebx", "%ecx", "%edi"); +} + +static inline void rep_movsb( ubyte * sbits, ubyte * dbits, int width ) { + __asm__ __volatile__ ("cld; rep; movsb" + : : "S" (sbits), "D" (dbits), "c" (width) : "%ecx", "%esi", "%edi"); +} +#endif diff --git a/2d/scalec.c b/2d/scalec.c new file mode 100644 index 00000000..c68f6a05 --- /dev/null +++ b/2d/scalec.c @@ -0,0 +1,413 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +#include +#include +#include "gr.h" +#include "grdef.h" +#include "rle.h" + +// John's new stuff below here.... + +int scale_error_term; +int scale_initial_pixel_count; +int scale_adj_up; +int scale_adj_down; +int scale_final_pixel_count; +int scale_ydelta_minus_1; +int scale_whole_step; +ubyte * scale_source_ptr; +ubyte * scale_dest_ptr; + + +ubyte scale_rle_data[640]; + +void scale_up_bitmap(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 ); +void scale_up_bitmap_rle(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 ); +void rls_stretch_scanline_setup( int XDelta, int YDelta ); +void rls_stretch_scanline(void); + + +void decode_row( grs_bitmap * bmp, int y ) +{ + int i, offset=4+bmp->bm_h; + + for (i=0; ibm_data[4+i]; + gr_rle_decode( &bmp->bm_data[offset], scale_rle_data ); +} + +void scale_up_bitmap(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 ) +{ + fix dv, v; + int y; + + dv = (v1-v0) / (y1-y0); + + rls_stretch_scanline_setup( (int)(x1-x0), f2i(u1)-f2i(u0) ); + if ( scale_ydelta_minus_1 < 1 ) return; + + v = v0; + + for (y=y0; y<=y1; y++ ) { + scale_source_ptr = &source_bmp->bm_data[source_bmp->bm_rowsize*f2i(v)+f2i(u0)]; + scale_dest_ptr = &dest_bmp->bm_data[dest_bmp->bm_rowsize*y+x0]; + rls_stretch_scanline(); + v += dv; + } +} + + + + +void scale_up_bitmap_rle(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 ) +{ + fix dv, v; + int y, last_row = -1; + + dv = (v1-v0) / (y1-y0); + + rls_stretch_scanline_setup( (int)(x1-x0), f2i(u1)-f2i(u0) ); + if ( scale_ydelta_minus_1 < 1 ) return; + + v = v0; + + for (y=y0; y<=y1; y++ ) { + if ( f2i(v) != last_row ) { + last_row = f2i(v); + decode_row( source_bmp, last_row ); + } + scale_source_ptr = &scale_rle_data[f2i(u0)]; + scale_dest_ptr = &dest_bmp->bm_data[dest_bmp->bm_rowsize*y+x0]; + rls_stretch_scanline(); + v += dv; + } +} + +void rls_stretch_scanline_setup( int XDelta, int YDelta ) +{ + scale_ydelta_minus_1 = YDelta - 1; + + /* X major line */ + /* Minimum # of pixels in a run in this line */ + scale_whole_step = XDelta / YDelta; + + /* Error term adjust each time Y steps by 1; used to tell when one + extra pixel should be drawn as part of a run, to account for + fractional steps along the X axis per 1-pixel steps along Y */ + scale_adj_up = (XDelta % YDelta) * 2; + + /* Error term adjust when the error term turns over, used to factor + out the X step made at that time */ + scale_adj_down = YDelta * 2; + + /* Initial error term; reflects an initial step of 0.5 along the Y + axis */ + scale_error_term = (XDelta % YDelta) - (YDelta * 2); + + /* The initial and last runs are partial, because Y advances only 0.5 + for these runs, rather than 1. Divide one full run, plus the + initial pixel, between the initial and last runs */ + scale_initial_pixel_count = (scale_whole_step / 2) + 1; + scale_final_pixel_count = scale_initial_pixel_count; + + /* If the basic run length is even and there's no fractional + advance, we have one pixel that could go to either the initial + or last partial run, which we'll arbitrarily allocate to the + last run */ + if ((scale_adj_up == 0) && ((scale_whole_step & 0x01) == 0)) + { + scale_initial_pixel_count--; + } + /* If there're an odd number of pixels per run, we have 1 pixel that can't + be allocated to either the initial or last partial run, so we'll add 0.5 + to error term so this pixel will be handled by the normal full-run loop */ + if ((scale_whole_step & 0x01) != 0) + { + scale_error_term += YDelta; + } + +} + +void rls_stretch_scanline() +{ + ubyte c; + int i, j, len, ErrorTerm, x; + + // Setup initial variables + ErrorTerm = scale_error_term; + + // Draw the first, partial run of pixels + + c = *scale_source_ptr++; + if ( c != TRANSPARENCY_COLOR ) { + for (i=0; i 0) { + len++; + ErrorTerm -= scale_adj_down; // reset the error term + } + + // Draw this run o' pixels + c = *scale_source_ptr++; + if ( c != TRANSPARENCY_COLOR ) { + + if (len > 3) { + while ((size_t)(scale_dest_ptr) & 0x3) { *scale_dest_ptr++ = c; len--; }; + if (len >= 4) { + x = (c << 24) | (c << 16) | (c << 8) | c; + while (len > 4) { *((int *)scale_dest_ptr) = x; scale_dest_ptr += 4; len -= 4; }; + } + while (len > 0) { *scale_dest_ptr++ = c; len--; }; + } else { + for (i=0; ibm_data[source_bmp->bm_rowsize*f2i(v)]; + dbits = &dest_bmp->bm_data[dest_bmp->bm_rowsize*y+x0]; + u = u0; + v += dv; + for (x=x0; x<=x1; x++ ) { + *dbits++ = sbits[ u >> 16 ]; + u += du; + } + } +} + +void scale_row_asm_transparent( ubyte * sbits, ubyte * dbits, int width, fix u, fix du ) +{ +#if 0 + int i; + ubyte c; + + for (i=0; i> 16 ]; + if ( c!=TRANSPARENCY_COLOR) + *dbits = c; + dbits++; + u += du; + } +#endif + int i; + ubyte c; + ubyte *dbits_end = &dbits[width-1]; + + if ( du < F1_0 ) { + // Scaling up. + fix next_u; + int next_u_int; + + next_u_int = f2i(u)+1; + c = sbits[ next_u_int ]; + next_u = i2f(next_u_int); + if ( c != TRANSPARENCY_COLOR ) goto NonTransparent; + +Transparent: + while (1) { + dbits++; + if ( dbits > dbits_end ) return; + u += du; + if ( u > next_u ) { + next_u_int = f2i(u)+1; + c = sbits[ next_u_int ]; + next_u = i2f(next_u_int); + if ( c != TRANSPARENCY_COLOR ) goto NonTransparent; + } + } + return; + +NonTransparent: + while (1) { + *dbits++ = c; + if ( dbits > dbits_end ) return; + u += du; + if ( u > next_u ) { + next_u_int = f2i(u)+1; + c = sbits[ next_u_int ]; + next_u = i2f(next_u_int); + if ( c == TRANSPARENCY_COLOR ) goto Transparent; + } + } + return; + + + + } else { + for ( i=0; ibm_data[dest_bmp->bm_rowsize*y+x0], x1-x0+1, u0, du ); + v += dv; + } +} + +#define FIND_SCALED_NUM(x,x0,x1,y0,y1) (fixmuldiv((x)-(x0),(y1)-(y0),(x1)-(x0))+(y0)) + +// Scales bitmap, bp, into vertbuf[0] to vertbuf[1] +void scale_bitmap(grs_bitmap *bp, grs_point *vertbuf ,int orientation) +{ + grs_bitmap * dbp = &grd_curcanv->cv_bitmap; + fix x0, y0, x1, y1; + fix u0, v0, u1, v1; + fix clipped_x0, clipped_y0, clipped_x1, clipped_y1; + fix clipped_u0, clipped_v0, clipped_u1, clipped_v1; + fix xmin, xmax, ymin, ymax; + int dx0, dy0, dx1, dy1; + int dtemp; + // Set initial variables.... + + x0 = vertbuf[0].x; y0 = vertbuf[0].y; + x1 = vertbuf[2].x; y1 = vertbuf[2].y; + + xmin = 0; ymin = 0; + xmax = i2f(dbp->bm_w)-fl2f(.5); ymax = i2f(dbp->bm_h)-fl2f(.5); + + u0 = i2f(0); v0 = i2f(0); + u1 = i2f(bp->bm_w-1); v1 = i2f(bp->bm_h-1); + + // Check for obviously offscreen bitmaps... + if ( (y1<=y0) || (x1<=x0) ) return; + if ( (x1<0 ) || (x0>=xmax) ) return; + if ( (y1<0 ) || (y0>=ymax) ) return; + + clipped_u0 = u0; clipped_v0 = v0; + clipped_u1 = u1; clipped_v1 = v1; + + clipped_x0 = x0; clipped_y0 = y0; + clipped_x1 = x1; clipped_y1 = y1; + + // Clip the left, moving u0 right as necessary + if ( x0 < xmin ) { + clipped_u0 = FIND_SCALED_NUM(xmin,x0,x1,u0,u1); + clipped_x0 = xmin; + } + + // Clip the right, moving u1 left as necessary + if ( x1 > xmax ) { + clipped_u1 = FIND_SCALED_NUM(xmax,x0,x1,u0,u1); + clipped_x1 = xmax; + } + + // Clip the top, moving v0 down as necessary + if ( y0 < ymin ) { + clipped_v0 = FIND_SCALED_NUM(ymin,y0,y1,v0,v1); + clipped_y0 = ymin; + } + + // Clip the bottom, moving v1 up as necessary + if ( y1 > ymax ) { + clipped_v1 = FIND_SCALED_NUM(ymax,y0,y1,v0,v1); + clipped_y1 = ymax; + } + + dx0 = f2i(clipped_x0); dx1 = f2i(clipped_x1); + dy0 = f2i(clipped_y0); dy1 = f2i(clipped_y1); + + if (dx1<=dx0) return; + if (dy1<=dy0) return; + +// Assert( dx0>=0 ); +// Assert( dy0>=0 ); +// Assert( dx1bm_w ); +// Assert( dy1bm_h ); +// Assert( f2i(u0)<=f2i(u1) ); +// Assert( f2i(v0)<=f2i(v1) ); +// Assert( f2i(u0)>=0 ); +// Assert( f2i(v0)>=0 ); +// Assert( u1bm_w) ); +// Assert( v1bm_h) ); +//mprintf( 0, "(%.2f,%.2f) to (%.2f,%.2f) using (%.2f,%.2f) to (%.2f,%.2f)\n", f2fl(clipped_x0), f2fl(clipped_y0), f2fl(clipped_x1), f2fl(clipped_y1), f2fl(clipped_u0), f2fl(clipped_v0), f2fl(clipped_u1), f2fl(clipped_v1) ); + + dtemp = f2i(clipped_u1)-f2i(clipped_u0); + +#if 0 + if ( bp->bm_flags & BM_FLAG_RLE ) + scale_bitmap_c_rle(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1 ); + else + scale_bitmap_c(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1 ); +#endif + if ( bp->bm_flags & BM_FLAG_RLE ) { + if ( (dtemp < (f2i(clipped_x1)-f2i(clipped_x0))) && (dtemp>0) ) + scale_up_bitmap_rle(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1 ); + else + scale_bitmap_c_rle(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1 ); + } else { + if ( (dtemp < (f2i(clipped_x1)-f2i(clipped_x0))) && (dtemp>0) ) + scale_up_bitmap(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1 ); + else + scale_bitmap_c(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1 ); + } +} + diff --git a/2d/tmerge.c b/2d/tmerge.c new file mode 100644 index 00000000..2364379d --- /dev/null +++ b/2d/tmerge.c @@ -0,0 +1,61 @@ +// tmerge.c - C Texture merge routines for use with D1X +// Ripped from ldescent by + +#include +#ifdef NO_ASM // If for some reason we have elected not to use assembler... + +#include "gr.h" + +void gr_merge_textures( ubyte * lower, ubyte * upper, ubyte * dest ) +{ + int x,y; + ubyte c; + for (y=0;y<64;y++) for (x=0;x<64;x++) { + c=upper[64*y+x]; + if (c==TRANSPARENCY_COLOR) + c=lower[64*y+x]; + *dest++=c; + } +} + +void gr_merge_textures_1( ubyte * lower, ubyte * upper, ubyte * dest ) +{ + int x,y; + ubyte c; + for (y=0; y<64; y++ ) + for (x=0; x<64; x++ ) { + c = upper[ 64*x+(63-y) ]; + if (c==TRANSPARENCY_COLOR) + c = lower[ 64*y+x ]; + *dest++ = c; + } +} + +void gr_merge_textures_2( ubyte * lower, ubyte * upper, ubyte * dest ) +{ + int x,y; + ubyte c; + for (y=0; y<64; y++ ) + for (x=0; x<64; x++ ) { + c = upper[ 64*(63-y)+(63-x) ]; + if (c==TRANSPARENCY_COLOR) + c = lower[ 64*y+x ]; + *dest++ = c; + } +} + +void gr_merge_textures_3( ubyte * lower, ubyte * upper, ubyte * dest ) +{ + int x,y; + ubyte c; + for (y=0; y<64; y++ ) + for (x=0; x<64; x++ ) { + c = upper[ 64*(63-x)+y ]; + if (c==TRANSPARENCY_COLOR) + c = lower[ 64*y+x ]; + *dest++ = c; + } +} + + +#endif diff --git a/2d/tmerge_a.asm b/2d/tmerge_a.asm new file mode 100644 index 00000000..dca02bc0 --- /dev/null +++ b/2d/tmerge_a.asm @@ -0,0 +1,283 @@ +;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +;SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +;IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +;FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. + +[BITS 32] + +section .data + +row_count dd 0 + +section .text + +; C-calling: +; void gr_merge_textures( ubyte * lower, ubyte * upper, ubyte * dest ) + +global _gr_merge_textures, _gr_merge_textures_1, _gr_merge_textures_2, _gr_merge_textures_3 +global gr_merge_textures, gr_merge_textures_1, gr_merge_textures_2, gr_merge_textures_3 + +; case 1: +; // +; for (y=0; y<64; y++ ) +; for (x=0; x<64; x++ ) { +; c = top_data[ 64*x+(63-y) ]; +; if (c==255) +; c = bottom_data[ 64*y+x ]; +; *dest_data++ = c; +; } +; break; +; case 2: +; // Normal +; for (y=0; y<64; y++ ) +; for (x=0; x<64; x++ ) { +; c = top_data[ 64*(63-y)+(63-x) ]; +; if (c==255) +; c = bottom_data[ 64*y+x ]; +; *dest_data++ = c; +; } +; break; +; case 3: +; // Normal +; for (y=0; y<64; y++ ) +; for (x=0; x<64; x++ ) { +; c = top_data[ 64*(63-x)+y ]; +; if (c==255) +; c = bottom_data[ 64*y+x ]; +; *dest_data++ = c; +; } +; break; +_gr_merge_textures: +gr_merge_textures: + + ; EAX = lower data + ; EDX = upper data + ; EBX = dest data + + push ebx + push esi + push edi + push ebp + + mov eax, [esp+20] + mov edx, [esp+24] + mov ebx, [esp+28] + + mov ebp, edx + mov edi, ebx + mov bl, 255 + mov bh, bl + and ebx, 0ffffh + and edx, 0ffffh + mov esi, eax + mov ecx, (64*64)/2 + + jmp gmt1 + +second_must_be_not_trans: + mov ah, dh + mov [edi],ax + add edi,2 + dec ecx + je donegmt + +gmt1: mov dx, [ebp] + add ebp, 2 + cmp edx, ebx + jne not_transparent + +; both transparent + movsw + dec ecx + jne gmt1 + jmp donegmt + +; DH OR DL ARE INVISIBLE +not_transparent: + mov ax,[esi] + add esi,2 + + cmp dl, bl + je second_must_be_not_trans + mov al, dl + cmp dh, bh + je @@1 + mov ah, dh +@@1: mov [edi],ax + add edi,2 + dec ecx + jne gmt1 + +donegmt: + + pop ebp + pop edi + pop esi + pop ebx + ret + +; ----------------------------------------------------------------------------------------- +; case 1, normal in x, flip in y +_gr_merge_textures_1: +gr_merge_textures_1: + +; eax = background data +; edx = foreground data +; ebx = destination address + + push ebp + push edi + push esi + push ebx + + mov eax, [esp+20] + mov edx, [esp+24] + mov ebx, [esp+28] + + mov ch, 255 ; transparent color, stick in a register, is this faster? + + mov esi, 63 ; esi will be the offset to the current pixel + mov [row_count], esi + + mov ebp, 64 ; do for 64 pixels + + align 4 +gmt1_1: mov cl, [edx + esi] ; get foreground pixel + add esi, 64 ; point at next row + cmp cl, ch ; see if transparent + jne not_transparent_1 ; dl contains a solid color, just write it + + mov cl,[eax] ; get background pixel + +not_transparent_1: mov [ebx], cl ; write pixel + inc ebx ; point at next destination address + inc eax + + dec ebp ; see if done a whole row + jne gmt1_1 ; no, so do next pixel + + mov ebp, 64 ; do for 64 pixels + + dec dword [row_count] ; advance to next row + mov esi, [row_count] ; doing next row, get offset, DANGER: DOESN'T SET FLAGS, BEWARE ON 68000, POWERPC!! + jns gmt1_1 ; no (going down to 0) + + pop ebx + pop esi + pop edi + pop ebp + ret + +; ----------------------------------------------------------------------------------------- +; case 1, normal in x, flip in y +_gr_merge_textures_2: +gr_merge_textures_2: + +; eax = background data +; edx = foreground data +; ebx = destination address + + push ebp + push edi + push esi + push ebx + + mov eax, [esp+20] + mov edx, [esp+24] + mov ebx, [esp+28] + + mov ch, 255 ; transparent color, stick in a register, is this faster? + + mov esi, 63 + 64*63 ; esi will be the offset to the current pixel + + align 4 +gmt1_2: mov cl, [edx + esi] ; get foreground pixel + cmp cl, ch ; see if transparent + jne not_transparent_2 ; dl contains a solid color, just write it + + mov cl,[eax] ; get background pixel + +not_transparent_2: mov [ebx], cl ; write pixel + inc ebx ; point at next destination address + inc eax + + dec esi ; advance to next row + jns gmt1_2 ; no (going down to 0) + + pop ebx + pop esi + pop edi + pop ebp + ret + +; ----------------------------------------------------------------------------------------- +; case 1, normal in x, flip in y +_gr_merge_textures_3: +gr_merge_textures_3: + +; eax = background data +; edx = foreground data +; ebx = destination address + + push ebp + push edi + push esi + push ebx + + mov eax, [esp+20] + mov edx, [esp+24] + mov ebx, [esp+28] + + mov ch, 255 ; transparent color, stick in a register, is this faster? + + mov esi, 64*63 ; esi will be the offset to the current pixel + mov dword [row_count], 64 + + mov ebp, 32 ; do for 64 pixels (2x loop) + +; first copy of loop + align 4 +gmt1_3: mov cl, [edx + esi] ; get foreground pixel + sub esi, 64 ; point at next row + cmp cl, ch ; see if transparent + jne not_transparent_3 ; dl contains a solid color, just write it + + mov cl,[eax] ; get background pixel + +not_transparent_3: inc eax + mov [ebx], cl ; write pixel + inc ebx ; point at next destination address + +; second copy of loop + mov cl, [edx + esi] ; get foreground pixel + sub esi, 64 ; point at next row + cmp cl, ch ; see if transparent + jne nt_3a ; dl contains a solid color, just write it + + mov cl,[eax] ; get background pixel + +nt_3a: inc eax + mov [ebx], cl ; write pixel + inc ebx ; point at next destination address + + dec ebp ; see if done a whole row + jne gmt1_3 ; no, so do next pixel + + mov ebp, 32 ; do for 64 pixels + + add esi, 64*64+1 ; doing next row, get offset, DANGER: DOESN'T SET FLAGS, BEWARE ON 68000, POWERPC!! + + dec dword [row_count] ; advance to next row + jne gmt1_3 ; no (going down to 0) + + pop ebx + pop esi + pop edi + pop ebp + ret diff --git a/3d/Makefile.am b/3d/Makefile.am new file mode 100644 index 00000000..c4bbfd7f --- /dev/null +++ b/3d/Makefile.am @@ -0,0 +1,6 @@ +noinst_LIBRARIES = lib3d.a +INCLUDES = -I $(top_srcdir)/includes + +lib3d_a_SOURCES = \ +clipper.c globvars.c interp.c points.c setup.c \ +draw.c instance.c matrix.c rod.c diff --git a/3d/Makefile.in b/3d/Makefile.in new file mode 100644 index 00000000..59d8ac7d --- /dev/null +++ b/3d/Makefile.in @@ -0,0 +1,303 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +CFLAGS = @CFLAGS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +NASM = @NASM@ +NASMFLAGS = @NASMFLAGS@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_LIBS = @SDL_LIBS@ +VERSION = @VERSION@ + +noinst_LIBRARIES = lib3d.a +INCLUDES = -I $(top_srcdir)/includes + +lib3d_a_SOURCES = clipper.c globvars.c interp.c points.c setup.c draw.c instance.c matrix.c rod.c + +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../conf.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +lib3d_a_LIBADD = +lib3d_a_OBJECTS = clipper.o globvars.o interp.o points.o setup.o draw.o \ +instance.o matrix.o rod.o +AR = ar +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +DEP_FILES = .deps/clipper.P .deps/draw.P .deps/globvars.P \ +.deps/instance.P .deps/interp.P .deps/matrix.P .deps/points.P \ +.deps/rod.P .deps/setup.P +SOURCES = $(lib3d_a_SOURCES) +OBJECTS = $(lib3d_a_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu 3d/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +lib3d.a: $(lib3d_a_OBJECTS) $(lib3d_a_DEPENDENCIES) + -rm -f lib3d.a + $(AR) cru lib3d.a $(lib3d_a_OBJECTS) $(lib3d_a_LIBADD) + $(RANLIB) lib3d.a + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = 3d + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu 3d/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile $(LIBRARIES) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ + mostlyclean-tags mostlyclean-depend mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \ + clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-noinstLIBRARIES distclean-compile \ + distclean-tags distclean-depend distclean-generic \ + clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/3d/clipper.c b/3d/clipper.c new file mode 100644 index 00000000..9d1cdcdc --- /dev/null +++ b/3d/clipper.c @@ -0,0 +1,226 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +#include +#include "fix.h" +#include "vecmat.h" +#include "gr.h" +#include "3d.h" +#include "globvars.h" +#include "clipper.h" +#include "error.h" + +int free_point_num=0; + +g3s_point temp_points[MAX_POINTS_IN_POLY]; +g3s_point *free_points[MAX_POINTS_IN_POLY]; + +void init_free_points(void) +{ + int i; + + for (i=0;ip3_flags = PF_TEMP_POINT; + + return p; +} + +void free_temp_point(g3s_point *p) +{ + Assert(p->p3_flags & PF_TEMP_POINT); + + free_points[--free_point_num] = p; + + p->p3_flags &= ~PF_TEMP_POINT; +} + +//clips an edge against one plane. +g3s_point *clip_edge(int plane_flag,g3s_point *on_pnt,g3s_point *off_pnt) +{ + fix psx_ratio; + fix a,b,kn,kd; + g3s_point *tmp; + + //compute clipping value k = (xs-zs) / (xs-xe-zs+ze) + //use x or y as appropriate, and negate x/y value as appropriate + + if (plane_flag & (CC_OFF_RIGHT | CC_OFF_LEFT)) { + a = on_pnt->p3_x; + b = off_pnt->p3_x; + } + else { + a = on_pnt->p3_y; + b = off_pnt->p3_y; + } + + if (plane_flag & (CC_OFF_LEFT | CC_OFF_BOT)) { + a = -a; + b = -b; + } + + kn = a - on_pnt->p3_z; //xs-zs + kd = kn - b + off_pnt->p3_z; //xs-zs-xe+ze + + tmp = get_temp_point(); + + psx_ratio = fixdiv( kn, kd ); + + +// PSX_HACK!!!! +// tmp->p3_x = on_pnt->p3_x + fixmuldiv(off_pnt->p3_x-on_pnt->p3_x,kn,kd); +// tmp->p3_y = on_pnt->p3_y + fixmuldiv(off_pnt->p3_y-on_pnt->p3_y,kn,kd); + + tmp->p3_x = on_pnt->p3_x + fixmul( (off_pnt->p3_x-on_pnt->p3_x), psx_ratio); + tmp->p3_y = on_pnt->p3_y + fixmul( (off_pnt->p3_y-on_pnt->p3_y), psx_ratio); + + if (plane_flag & (CC_OFF_TOP|CC_OFF_BOT)) + tmp->p3_z = tmp->p3_y; + else + tmp->p3_z = tmp->p3_x; + + if (plane_flag & (CC_OFF_LEFT|CC_OFF_BOT)) + tmp->p3_z = -tmp->p3_z; + + if (on_pnt->p3_flags & PF_UVS) { +// PSX_HACK!!!! +// tmp->p3_u = on_pnt->p3_u + fixmuldiv(off_pnt->p3_u-on_pnt->p3_u,kn,kd); +// tmp->p3_v = on_pnt->p3_v + fixmuldiv(off_pnt->p3_v-on_pnt->p3_v,kn,kd); + tmp->p3_u = on_pnt->p3_u + fixmul((off_pnt->p3_u-on_pnt->p3_u), psx_ratio); + tmp->p3_v = on_pnt->p3_v + fixmul((off_pnt->p3_v-on_pnt->p3_v), psx_ratio); + + tmp->p3_flags |= PF_UVS; + } + + if (on_pnt->p3_flags & PF_LS) { +// PSX_HACK +// tmp->p3_r = on_pnt->p3_r + fixmuldiv(off_pnt->p3_r-on_pnt->p3_r,kn,kd); +// tmp->p3_g = on_pnt->p3_g + fixmuldiv(off_pnt->p3_g-on_pnt->p3_g,kn,kd); +// tmp->p3_b = on_pnt->p3_b + fixmuldiv(off_pnt->p3_b-on_pnt->p3_b,kn,kd); + + tmp->p3_l = on_pnt->p3_l + fixmul((off_pnt->p3_l-on_pnt->p3_l), psx_ratio); + + tmp->p3_flags |= PF_LS; + } + + g3_code_point(tmp); + + return tmp; +} + +//clips a line to the viewing pyramid. +void clip_line(g3s_point **p0,g3s_point **p1,ubyte codes_or) +{ + int plane_flag; + g3s_point *old_p1; + + //might have these left over + (*p0)->p3_flags &= ~(PF_UVS|PF_LS); + (*p1)->p3_flags &= ~(PF_UVS|PF_LS); + + for (plane_flag=1;plane_flag<16;plane_flag<<=1) + if (codes_or & plane_flag) { + + if ((*p0)->p3_codes & plane_flag) + {g3s_point *t=*p0; *p0=*p1; *p1=t;} //swap! + + old_p1 = *p1; + + *p1 = clip_edge(plane_flag,*p0,*p1); + + if (old_p1->p3_flags & PF_TEMP_POINT) + free_temp_point(old_p1); + } + +} + + +int clip_plane(int plane_flag,g3s_point **src,g3s_point **dest,int *nv,g3s_codes *cc) +{ + int i; + g3s_point **save_dest=dest; + + //copy first two verts to end + src[*nv] = src[0]; + src[*nv+1] = src[1]; + + cc->and = 0xff; cc->or = 0; + + for (i=1;i<=*nv;i++) { + + if (src[i]->p3_codes & plane_flag) { //cur point off? + + if (! (src[i-1]->p3_codes & plane_flag)) { //prev not off? + + *dest = clip_edge(plane_flag,src[i-1],src[i]); + cc->or |= (*dest)->p3_codes; + cc->and &= (*dest)->p3_codes; + dest++; + } + + if (! (src[i+1]->p3_codes & plane_flag)) { + + *dest = clip_edge(plane_flag,src[i+1],src[i]); + cc->or |= (*dest)->p3_codes; + cc->and &= (*dest)->p3_codes; + dest++; + } + + //see if must free discarded point + + if (src[i]->p3_flags & PF_TEMP_POINT) + free_temp_point(src[i]); + } + else { //cur not off, copy to dest buffer + + *dest++ = src[i]; + + cc->or |= src[i]->p3_codes; + cc->and &= src[i]->p3_codes; + } + } + + return (dest-save_dest); +} + + +g3s_point **clip_polygon(g3s_point **src,g3s_point **dest,int *nv,g3s_codes *cc) +{ + int plane_flag; + g3s_point **t; + + for (plane_flag=1;plane_flag<16;plane_flag<<=1) + + if (cc->or & plane_flag) { + + *nv = clip_plane(plane_flag,src,dest,nv,cc); + + if (cc->and) //clipped away + return dest; + + t = src; src = dest; dest = t; + + } + + return src; //we swapped after we copied +} + diff --git a/3d/clipper.h b/3d/clipper.h new file mode 100644 index 00000000..fa104ba0 --- /dev/null +++ b/3d/clipper.h @@ -0,0 +1,44 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/3d/clipper.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:29:58 $ + * + * Header for clipper.c + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 21:57:51 donut + * Import of d1x 1.37 source. + * + * Revision 1.1 1995/05/05 08:50:13 allender + * Initial revision + * + * Revision 1.1 1995/04/17 19:56:58 matt + * Initial revision + * + * + */ + + + +#ifndef _CLIPPER_H +#define _CLIPPER_H + +extern void free_temp_point(g3s_point *p); +extern g3s_point **clip_polygon(g3s_point **src,g3s_point **dest,int *nv,g3s_codes *cc); +extern void init_free_points(void); +extern void clip_line(g3s_point **p0,g3s_point **p1,ubyte codes_or); + +#endif diff --git a/3d/draw.c b/3d/draw.c new file mode 100644 index 00000000..9ce9c058 --- /dev/null +++ b/3d/draw.c @@ -0,0 +1,373 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * + * Drawing routines + * + */ + +#ifdef RCS +static char rcsid[] = "$Id: draw.c,v 1.1.1.1 2001-01-19 03:29:58 bradleyb Exp $"; +#endif + +#include +#include "error.h" + +#include "fix.h" +#include "vecmat.h" +#include "gr.h" +#include "3d.h" +#include "globvars.h" +#include "texmap.h" +#include "clipper.h" + +void (*tmap_drawer_ptr)(grs_bitmap *bm,int nv,g3s_point **vertlist) = draw_tmap; +void (*flat_drawer_ptr)(int nv,int *vertlist) = gr_upoly_tmap; +int (*line_drawer_ptr)(fix x0,fix y0,fix x1,fix y1) = gr_line; + +//specifies 2d drawing routines to use instead of defaults. Passing +//NULL for either or both restores defaults +void g3_set_special_render(void (*tmap_drawer)(),void (*flat_drawer)(),int (*line_drawer)(fix, fix, fix, fix)) +{ + tmap_drawer_ptr = (tmap_drawer)?tmap_drawer:draw_tmap; + flat_drawer_ptr = (flat_drawer)?flat_drawer:gr_upoly_tmap; + line_drawer_ptr = (line_drawer)?line_drawer:gr_line; +} +#ifndef OGL +//deal with a clipped line +bool must_clip_line(g3s_point *p0,g3s_point *p1,ubyte codes_or) +{ + bool ret; + + if ((p0->p3_flags&PF_TEMP_POINT) || (p1->p3_flags&PF_TEMP_POINT)) + + ret = 0; //line has already been clipped, so give up + + else { + + clip_line(&p0,&p1,codes_or); + + ret = g3_draw_line(p0,p1); + } + + //free temp points + + if (p0->p3_flags & PF_TEMP_POINT) + free_temp_point(p0); + + if (p1->p3_flags & PF_TEMP_POINT) + free_temp_point(p1); + + return ret; +} + +//draws a line. takes two points. returns true if drew +bool g3_draw_line(g3s_point *p0,g3s_point *p1) +{ + ubyte codes_or; + + if (p0->p3_codes & p1->p3_codes) + return 0; + + codes_or = p0->p3_codes | p1->p3_codes; + + if (codes_or & CC_BEHIND) + return must_clip_line(p0,p1,codes_or); + + if (!(p0->p3_flags&PF_PROJECTED)) + g3_project_point(p0); + + if (p0->p3_flags&PF_OVERFLOW) + return must_clip_line(p0,p1,codes_or); + + + if (!(p1->p3_flags&PF_PROJECTED)) + g3_project_point(p1); + + if (p1->p3_flags&PF_OVERFLOW) + return must_clip_line(p0,p1,codes_or); + + return (bool) (*line_drawer_ptr)(p0->p3_sx,p0->p3_sy,p1->p3_sx,p1->p3_sy); +} +#endif + +//returns true if a plane is facing the viewer. takes the unrotated surface +//normal of the plane, and a point on it. The normal need not be normalized +bool g3_check_normal_facing(vms_vector *v,vms_vector *norm) +{ + vms_vector tempv; + + vm_vec_sub(&tempv,&View_position,v); + + return (vm_vec_dot(&tempv,norm) > 0); +} + +bool do_facing_check(vms_vector *norm,g3s_point **vertlist,vms_vector *p) +{ + if (norm) { //have normal + + Assert(norm->x || norm->y || norm->z); + + return g3_check_normal_facing(p,norm); + } + else { //normal not specified, so must compute + + vms_vector tempv; + + //get three points (rotated) and compute normal + + vm_vec_perp(&tempv,&vertlist[0]->p3_vec,&vertlist[1]->p3_vec,&vertlist[2]->p3_vec); + + return (vm_vec_dot(&tempv,&vertlist[1]->p3_vec) < 0); + } +} + +//like g3_draw_poly(), but checks to see if facing. If surface normal is +//NULL, this routine must compute it, which will be slow. It is better to +//pre-compute the normal, and pass it to this function. When the normal +//is passed, this function works like g3_check_normal_facing() plus +//g3_draw_poly(). +//returns -1 if not facing, 1 if off screen, 0 if drew +bool g3_check_and_draw_poly(int nv,g3s_point **pointlist,vms_vector *norm,vms_vector *pnt) +{ + if (do_facing_check(norm,pointlist,pnt)) + return g3_draw_poly(nv,pointlist); + else + return 255; +} + +bool g3_check_and_draw_tmap(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bm,vms_vector *norm,vms_vector *pnt) +{ + if (do_facing_check(norm,pointlist,pnt)) + return g3_draw_tmap(nv,pointlist,uvl_list,bm); + else + return 255; +} + +//deal with face that must be clipped +bool must_clip_flat_face(int nv,g3s_codes cc) +{ + int i; + bool ret=0; + g3s_point **bufptr; + + bufptr = clip_polygon(Vbuf0,Vbuf1,&nv,&cc); + + if (nv>0 && !(cc.or&CC_BEHIND) && !cc.and) { + + for (i=0;ip3_flags&PF_PROJECTED)) + g3_project_point(p); + + if (p->p3_flags&PF_OVERFLOW) { + ret = 1; + goto free_points; + } + + Vertex_list[i*2] = p->p3_sx; + Vertex_list[i*2+1] = p->p3_sy; + } + + (*flat_drawer_ptr)(nv,(int *)Vertex_list); + } + else + ret=1; + + //free temp points +free_points: + ; + + for (i=0;ip3_flags & PF_TEMP_POINT) + free_temp_point(Vbuf1[i]); + +// Assert(free_point_num==0); + + return ret; +} + +#if (!(defined(D1XD3D) || defined(OGL))) +//draw a flat-shaded face. +//returns 1 if off screen, 0 if drew +bool g3_draw_poly(int nv,g3s_point **pointlist) +{ + int i; + g3s_point **bufptr; + g3s_codes cc; + + cc.or = 0; cc.and = 0xff; + + bufptr = Vbuf0; + + for (i=0;ip3_codes; + cc.or |= bufptr[i]->p3_codes; + } + + if (cc.and) + return 1; //all points off screen + + if (cc.or) + return must_clip_flat_face(nv,cc); + + //now make list of 2d coords (& check for overflow) + + for (i=0;ip3_flags&PF_PROJECTED)) + g3_project_point(p); + + if (p->p3_flags&PF_OVERFLOW) + return must_clip_flat_face(nv,cc); + + Vertex_list[i*2] = p->p3_sx; + Vertex_list[i*2+1] = p->p3_sy; + } + + (*flat_drawer_ptr)(nv,(int *)Vertex_list); + + return 0; //say it drew +} + +bool must_clip_tmap_face(int nv,g3s_codes cc,grs_bitmap *bm); + +//draw a texture-mapped face. +//returns 1 if off screen, 0 if drew +bool g3_draw_tmap(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bm) +{ + int i; + g3s_point **bufptr; + g3s_codes cc; + + cc.or = 0; cc.and = 0xff; + + bufptr = Vbuf0; + + for (i=0;ip3_codes; + cc.or |= p->p3_codes; + + p->p3_u = uvl_list[i].u; + p->p3_v = uvl_list[i].v; + p->p3_l = uvl_list[i].l; + + p->p3_flags |= PF_UVS + PF_LS; + + } + + if (cc.and) + return 1; //all points off screen + + if (cc.or) + return must_clip_tmap_face(nv,cc,bm); + + //now make list of 2d coords (& check for overflow) + + for (i=0;ip3_flags&PF_PROJECTED)) + g3_project_point(p); + + if (p->p3_flags&PF_OVERFLOW) { + Int3(); //should not overflow after clip + return 255; + } + } + + (*tmap_drawer_ptr)(bm,nv,bufptr); + + return 0; //say it drew +} +#endif + +bool must_clip_tmap_face(int nv,g3s_codes cc,grs_bitmap *bm) +{ + g3s_point **bufptr; + int i; + + bufptr = clip_polygon(Vbuf0,Vbuf1,&nv,&cc); + + if (nv && !(cc.or&CC_BEHIND) && !cc.and) { + + for (i=0;ip3_flags&PF_PROJECTED)) + g3_project_point(p); + + if (p->p3_flags&PF_OVERFLOW) { + Int3(); //should not overflow after clip + goto free_points; + } + } + + (*tmap_drawer_ptr)(bm,nv,bufptr); + } + +free_points: + ; + + for (i=0;ip3_flags & PF_TEMP_POINT) + free_temp_point(bufptr[i]); + +// Assert(free_point_num==0); + + return 0; + +} + +#ifndef __powerc +int checkmuldiv(fix *r,fix a,fix b,fix c); +#endif + +#ifndef OGL +//draw a sortof sphere - i.e., the 2d radius is proportional to the 3d +//radius, but not to the distance from the eye +int g3_draw_sphere(g3s_point *pnt,fix rad) +{ + if (! (pnt->p3_codes & CC_BEHIND)) { + + if (! (pnt->p3_flags & PF_PROJECTED)) + g3_project_point(pnt); + + if (! (pnt->p3_codes & PF_OVERFLOW)) { + fix r2,t; + + r2 = fixmul(rad,Matrix_scale.x); +#ifndef __powerc + if (checkmuldiv(&t,r2,Canv_w2,pnt->p3_z)) + return gr_disk(pnt->p3_sx,pnt->p3_sy,t); +#else + if (pnt->p3_z == 0) + return 0; + return gr_disk(pnt->p3_sx, pnt->p3_sy, fl2f(((f2fl(r2) * fCanv_w2) / f2fl(pnt->p3_z)))); +#endif + } + } + + return 0; +} +#endif + diff --git a/3d/globvars.c b/3d/globvars.c new file mode 100644 index 00000000..b31aae71 --- /dev/null +++ b/3d/globvars.c @@ -0,0 +1,76 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/3d/globvars.c,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:29:58 $ + * + * Global variables for 3d + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 21:57:45 donut + * Import of d1x 1.37 source. + * + * Revision 1.2 1995/09/13 11:30:47 allender + * added fCanv_w2 and vCanv_h2 for PPC implementation + * + * Revision 1.1 1995/05/05 08:50:48 allender + * Initial revision + * + * Revision 1.1 1995/04/17 04:24:57 matt + * Initial revision + * + * + */ + +#ifdef RCS +static char rcsid[] = "$Id: globvars.c,v 1.1.1.1 2001-01-19 03:29:58 bradleyb Exp $"; +#endif + +#include +#include "fix.h" +#include "vecmat.h" +#include "gr.h" +#include "3d.h" +#include "globvars.h" + +vms_vector View_position; +fix View_zoom; + +vms_matrix Unscaled_matrix; //before scaling +vms_matrix View_matrix; + +vms_vector Window_scale; //scaling for window aspect +vms_vector Matrix_scale; //how the matrix is scaled, window_scale * zoom + +int Canvas_width; //the actual width +int Canvas_height; //the actual height + +fix Canv_w2; //fixed-point width/2 +fix Canv_h2; //fixed-point height/2 + +#ifdef __powerc +double fCanv_w2; +double fCanv_h2; +#endif + +//vertex buffers for polygon drawing and clipping +g3s_point * Vbuf0[MAX_POINTS_IN_POLY]; +g3s_point *Vbuf1[MAX_POINTS_IN_POLY]; + +//list of 2d coords +fix Vertex_list[MAX_POINTS_IN_POLY*2]; + + + diff --git a/3d/globvars.h b/3d/globvars.h new file mode 100644 index 00000000..62e7850f --- /dev/null +++ b/3d/globvars.h @@ -0,0 +1,66 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/3d/globvars.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:29:58 $ + * + * Private (internal) header for 3d library + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 21:57:51 donut + * Import of d1x 1.37 source. + * + * Revision 1.2 1995/09/13 11:31:19 allender + * added fCanv_w2 and vCanv_h2 for PPC implementation + * + * Revision 1.1 1995/05/05 08:51:02 allender + * Initial revision + * + * Revision 1.1 1995/04/17 04:07:58 matt + * Initial revision + * + * + */ + + + +#ifndef _GLOBVARS_H +#define _GLOBVARS_H + +#define MAX_POINTS_IN_POLY 100 + +extern int Canvas_width,Canvas_height; //the actual width & height +extern fix Canv_w2,Canv_h2; //fixed-point width,height/2 + +#ifdef __powerc +extern double fCanv_w2, fCanv_h2; +#endif + +extern vms_vector Window_scale; +extern int free_point_num; + +extern fix View_zoom; +extern vms_vector View_position,Matrix_scale; +extern vms_matrix View_matrix,Unscaled_matrix; + + +//vertex buffers for polygon drawing and clipping +extern g3s_point *Vbuf0[]; +extern g3s_point *Vbuf1[]; + +//list of 2d coords +extern fix Vertex_list[]; + +#endif diff --git a/3d/instance.c b/3d/instance.c new file mode 100644 index 00000000..1e66feae --- /dev/null +++ b/3d/instance.c @@ -0,0 +1,131 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/3d/instance.c,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:29:58 $ + * + * Instancing routines + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 21:57:45 donut + * Import of d1x 1.37 source. + * + * Revision 1.2 1995/06/12 12:36:57 allender + * fixed bug where g3_start_instance_angles recursively called itself + * + * Revision 1.1 1995/05/05 08:51:27 allender + * Initial revision + * + * Revision 1.1 1995/04/17 06:43:29 matt + * Initial revision + * + * + */ + +#ifdef RCS +static char rcsid[] = "$Id: instance.c,v 1.1.1.1 2001-01-19 03:29:58 bradleyb Exp $"; +#endif + +#include +#include +#include "error.h" + +#include "fix.h" +#include "vecmat.h" +#include "gr.h" +#include "3d.h" +#include "globvars.h" + +#define MAX_INSTANCE_DEPTH 5 + +struct instance_context { + vms_matrix m; + vms_vector p; +} instance_stack[MAX_INSTANCE_DEPTH]; + +int instance_depth = 0; + +//instance at specified point with specified orientation +//if matrix==NULL, don't modify matrix. This will be like doing an offset +void g3_start_instance_matrix(vms_vector *pos,vms_matrix *orient) +{ + vms_vector tempv; + vms_matrix tempm,tempm2; + +#ifdef D1XD3D + Win32_start_instance_matrix (pos, orient); +#endif + + Assert(instance_depth= 0); + + View_position = instance_stack[instance_depth].p; + View_matrix = instance_stack[instance_depth].m; +} + + diff --git a/3d/interp.asm b/3d/interp.asm new file mode 100644 index 00000000..f459abbf --- /dev/null +++ b/3d/interp.asm @@ -0,0 +1,1012 @@ +; THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +; SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +; END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +; ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +; IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +; SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +; FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +; CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +; AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +; COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. + + +.386 + option oldstructs + + .nolist + include pstypes.inc + include psmacros.inc + include gr.inc + include 3d.inc + .list + + assume cs:_TEXT, ds:_DATA + +_DATA segment dword public USE32 'DATA' + +rcsid db "$Id: interp.asm,v 1.1.1.1 2001-01-19 03:29:58 bradleyb Exp $" + align 4 + +;table with address for each opcode +opcode_table dd op_eof ;0 = eof + dd op_defpoints ;1 = defpoints + dd op_flatpoly ;2 = flat-shaded polygon + dd op_tmappoly ;3 = texture-mapped polygon + dd op_sortnorm ;4 = sort by normal + dd op_rodbm ;5 = rod bitmap + dd op_subcall ;6 = call a subobject + dd op_defp_start ;7 = defpoints with start + dd op_glow ;8 = glow value for next poly +n_opcodes = ($-opcode_table)/4 + +bitmap_ptr dd ? +anim_angles dd ? ;pointer to angle data + +morph_points dd ? ;alternate points for morph + +;light value for the next tmap +glow_num dd -1 ;-1 means off +glow_values dd ? ;ptr to array of values + + public _highest_texture_num +_highest_texture_num dw 0 + +zero_angles fixang 0,0,0 ;vms_angvec <0,0,0> ;for if no angles specified + +rod_top_p g3s_point <> +rod_bot_p g3s_point <> + + public g3d_interp_outline,_g3d_interp_outline +_g3d_interp_outline label dword +g3d_interp_outline dd 0 + +morph_pointlist dd ?,?,? + +morph_uvls fix 3 dup (?,?,?) + +;the light for the current model +model_light fix ? + +;ptr to array of points +Interp_point_list dd ? + +MAX_POINTS_PER_POLY = 25 + +point_list dd MAX_POINTS_PER_POLY dup (?) + +MAX_INTERP_COLORS = 100 + +;this is a table of mappings from RGB15 to palette colors +interp_color_table dw MAX_INTERP_COLORS dup (?,?) + +n_interp_colors dd 0 +uninit_flag dd 0 + + +_DATA ends + + + +_TEXT segment dword public USE32 'CODE' + +;get and jump to next opcode +next macro + xor ebx,ebx + mov bx,[ebp] + ifndef NDEBUG + cmp ebx,n_opcodes + break_if ge,'Invalid opcode' + endif + mov ebx,opcode_table[ebx*4] + jmp ebx + endm + +;get and call the next opcode +call_next macro + xor ebx,ebx + mov bx,[ebp] + ifndef NDEBUG + cmp ebx,n_opcodes + break_if ge,'Invalid opcode' + endif + mov ebx,opcode_table[ebx*4] + call ebx + endm + +;give the interpreter an array of points to use +g3_set_interp_points: + mov Interp_point_list,eax + ret + +;interpreter to draw polygon model +;takes esi=ptr to object, edi=ptr to array of bitmap pointers, +;eax=ptr to anim angles, edx=light value, ebx=ptr to array of glow values +g3_draw_polygon_model: + pushm eax,ebx,ecx,edx,esi,edi,ebp + + mov ebp,esi ;ebp = interp ptr + + mov bitmap_ptr,edi ;save ptr to bitmap array + mov anim_angles,eax + mov model_light,edx + mov glow_values,ebx + + mov glow_num,-1 + +;;@@ mov depth,0 + + call_next + + popm eax,ebx,ecx,edx,esi,edi,ebp + ret + +;handlers for opcodes + +;end of a model or sub-rountine +op_eof: ret + +;define a list of points +op_defpoints: xor ecx,ecx + mov cx,2[ebp] ;num points + mov edi,Interp_point_list + lea esi,4[ebp] +rotate_loop: call g3_rotate_point + add edi,size g3s_point + add esi,size vms_vector + dec ecx + jnz rotate_loop + mov ebp,esi + next + +;define a list of points, with starting point num specified +op_defp_start: xor ecx,ecx + xor eax,eax + mov ax,w 4[ebp] ;starting point num + imulc eax,size g3s_point ;get ofs of point + add eax,Interp_point_list + mov edi,eax + mov cx,2[ebp] ;num points + lea esi,8[ebp] + jmp rotate_loop + next + +;draw a flat-shaded polygon +op_flatpoly: xor ecx,ecx + mov cx,2[ebp] ;num verts + lea esi,4[ebp] ;point + lea edi,16[ebp] ;vector + call g3_check_normal_facing + jng flat_not_facing + +;polygon is facing, so draw it + +;here the glow parameter is used for the player's headlight + test glow_num,-1 ;glow override? + js no_glow2 + mov eax,glow_num + mov esi,glow_values + mov eax,[esi+eax*4] + mov glow_num,-1 + cmp eax,-1 ;-1 means draw normal color + jne not_normal_color +;use the color specified, run through darkening table + xor ebx,ebx + mov eax,32 ;32 shades + imul model_light + sar eax,16 + or eax,eax + jns no_sat1 + xor eax,eax +no_sat1: cmp eax,32 + jl no_sat2 + mov eax,32 +no_sat2: mov bh,al ;get lighting table + xor eax,eax + mov ax,28[ebp] ;get color index + mov ax,interp_color_table[eax*4] + mov bl,al + mov al,gr_fade_table[ebx] + jmp got_color_index +not_normal_color: cmp eax,-2 ;-2 means use white + jne not_white + mov eax,255 ;hack! + jmp got_color_index +not_white: cmp eax,-3 ;-3 means don't draw polygon + je flat_not_facing +no_glow2: + + xor eax,eax + mov ax,28[ebp] ;get color index + mov ax,interp_color_table[eax*4] +got_color_index: call gr_setcolor_ ;set it + + lea esi,30[ebp] ;point number list + + ;make list of point pointers + + ifndef NDEBUG + cmp ecx,MAX_POINTS_PER_POLY + break_if ge,'Too many points in interp poly' + endif + + lea edi,point_list + xor ebx,ebx +copy_loop: xor eax,eax + mov ax,w [esi+ebx*2] ;get point number + imulc eax,size g3s_point + add eax,Interp_point_list + mov [edi+ebx*4],eax + inc ebx + cmp ebx,ecx + jne copy_loop + mov esi,edi + + call g3_draw_poly + xor ecx,ecx + mov cx,2[ebp] ;restore count + + ifndef NDEBUG + test g3d_interp_outline,-1 + jz no_outline + pushm ecx,esi + lea esi,30[ebp] + call draw_outline + popm ecx,esi +no_outline: + endif + +;polygon is not facing (or we've plotted it). jump to next opcode +flat_not_facing: and ecx,0fffffffeh + inc ecx ;adjust for pad + lea ebp,30[ebp+ecx*2] + next + +;set the glow value for the next tmap +op_glow: test glow_values,-1 + jz skip_glow + xor eax,eax + mov ax,2[ebp] + mov glow_num,eax +skip_glow: add ebp,4 + next + + +;draw a texture map +op_tmappoly: xor ecx,ecx + mov cx,2[ebp] ;num verts + lea esi,4[ebp] ;point + lea edi,16[ebp] ;normal + call g3_check_normal_facing + jng tmap_not_facing + +;polygon is facing, so draw it + + xor edx,edx + mov dx,28[ebp] ;get bitmap number + mov eax,bitmap_ptr + mov edx,[eax+edx*4] + + lea esi,30[ebp] ;point number list + mov eax,ecx + and eax,0fffffffeh + inc eax + lea ebx,30[ebp+eax*2] ;get uvl list + +;calculate light from surface normal + push esi + + test glow_num,-1 ;glow override? + js no_glow +;special glow lighting, which doesn't care about surface normal + mov eax,glow_num + mov esi,glow_values + mov eax,[esi+eax*4] + mov glow_num,-1 + jmp got_light_value +no_glow: + lea esi,View_matrix.fvec + lea edi,16[ebp] ;normal + call vm_vec_dotprod + neg eax +;scale light by model light + push edx + mov edx,eax + add eax,eax + add eax,edx ;eax *= 3 + sar eax,2 ;eax *= 3/4 + add eax,f1_0/4 ;eax = 1/4 + eax * 3/4 + fixmul model_light + pop edx +;now poke light into l values +got_light_value: pushm ecx,ebx +l_loop: mov 8[ebx],eax + add ebx,12 + dec ecx + jnz l_loop + popm ecx,ebx + pop esi + +;now draw it + ;make list of point pointers + + ifndef NDEBUG + cmp ecx,MAX_POINTS_PER_POLY + break_if ge,'Too many points in interp poly' + endif + + push ebx + lea edi,point_list + xor ebx,ebx +copy_loop2: xor eax,eax + mov ax,w [esi+ebx*2] ;get point number + imulc eax,size g3s_point + add eax,Interp_point_list + mov [edi+ebx*4],eax + inc ebx + cmp ebx,ecx + jne copy_loop2 + mov esi,edi + pop ebx + + call g3_draw_tmap + xor ecx,ecx + mov cx,2[ebp] ;restore count + + ifndef NDEBUG + test g3d_interp_outline,-1 + jz no_outline2 + pushm ecx,esi + lea esi,30[ebp] + call draw_outline + popm ecx,esi +no_outline2: + endif + +;polygon is not facing (or we've plotted it). jump to next opcode +tmap_not_facing: mov ebx,ecx + and ebx,0fffffffeh + inc ebx ;adjust for pad + lea ebp,30[ebp+ebx*2] + + mov eax,ecx + sal ecx,1 + add ecx,eax + sal ecx,2 ;ecx=ecx*12 + add ebp,ecx ;point past uvls + + next + +;sort based on surface normal +op_sortnorm: lea esi,16[ebp] ;point + lea edi,4[ebp] ;vector + call g3_check_normal_facing + jng sortnorm_not_facing + +;is facing. draw back then front + + push ebp + xor eax,eax + mov ax,30[ebp] ;get back offset + add ebp,eax + call_next + mov ebp,[esp] ;get ebp + xor eax,eax + mov ax,28[ebp] ;get front offset + add ebp,eax + call_next + pop ebp + + lea ebp,32[ebp] + next + +;is not facing. draw front then back + +sortnorm_not_facing: + push ebp + xor eax,eax + mov ax,28[ebp] ;get back offset + add ebp,eax + call_next + mov ebp,[esp] ;get ebp + xor eax,eax + mov ax,30[ebp] ;get front offset + add ebp,eax + call_next + pop ebp + + lea ebp,32[ebp] + next + +;draw a rod bitmap +op_rodbm: lea esi,20[ebp] ;bot point + lea edi,rod_bot_p + call g3_rotate_point + + lea esi,4[ebp] ;top point + lea edi,rod_top_p + call g3_rotate_point + + lea esi,rod_bot_p ;esi=bot, edi=top + mov eax,16[ebp] ;bot width + mov edx,32[ebp] ;top width + + xor ebx,ebx + mov bx,2[ebp] ;get bitmap number + mov ecx,bitmap_ptr + mov ebx,[ecx+ebx*4] + + call g3_draw_rod_tmap + + lea ebp,36[ebp] + next + + +;draw a subobject +op_subcall: xor eax,eax + mov ax,2[ebp] ;get object number + +;get ptr to angles + mov edi,anim_angles + or edi,edi + jnz angles_not_null +;angles not specified. Use zero angles + lea edi,zero_angles + jmp got_angles +angles_not_null: + imulc eax,size vms_angvec + add edi,eax +got_angles: + ;angles in edi + + lea esi,4[ebp] ;get position + call g3_start_instance_angles + + push ebp + xor eax,eax + mov ax,16[ebp] + add ebp,eax ;offset of subobject + call_next ;draw the subobject + pop ebp + + call g3_done_instance + + lea ebp,20[ebp] + next + +;takes ax, returns ax +find_color_index: push ebx + + ;first, see if color already in table + + xor ebx,ebx ;counter +look_loop: cmp ebx,n_interp_colors + je must_add_color + cmp ax,interp_color_table+2[ebx*4] + je found_color + inc ebx + jmp look_loop + +must_add_color: mov interp_color_table+2[ebx*4],ax ;save rgb15 + call gr_find_closest_color_15bpp_ + mov interp_color_table[ebx*4],ax ;save pal entry + inc n_interp_colors + +found_color: mov eax,ebx ;return index + pop ebx + ret + +;this remaps the 15bpp colors for the models into a new palette. It should +;be called whenever the palette changes +g3_remap_interp_colors: + pushm eax,ebx + + xor ebx,ebx ;index +remap_loop: cmp ebx,n_interp_colors + je done_remap + + xor eax,eax + mov ax,interp_color_table+2[ebx*4] ;get rgb15 + call gr_find_closest_color_15bpp_ + mov interp_color_table[ebx*4],ax ;store pal entry + + inc ebx + jmp remap_loop + +done_remap: popm eax,ebx + ret + + +;maps the colors back to RGB15 +g3_uninit_polygon_model: + mov uninit_flag,1 + +;initialize a polygon object +;translate colors, scale UV values +;takes esi=ptr to model +g3_init_polygon_model: + mov _highest_texture_num,-1 + + pushm eax,ebx,ecx,edx,esi,edi + call init_loop + popm eax,ebx,ecx,edx,esi,edi + + mov uninit_flag,0 + ret + + +init_loop: mov ax,[esi] ;get opcode + cmp ax,0 ;eof + jne not_eof + ret +not_eof: + +;defpoints + cmp ax,1 ;defpoints + jne not_defpoints + xor eax,eax + mov ax,2[esi] ;get count + sal eax,1 + add ax,2[esi] ;*3 + lea esi,4[esi+eax*4] + jmp init_loop +not_defpoints: + +;flat polygon + cmp ax,2 + jne not_flatpoly + ifndef NDEBUG + cmp w 2[esi],3 + break_if l,'face must have 3 or more points' + endif + ; The following 3 lines replace the above + xor eax, eax + mov ax,28[esi] ;get color + test uninit_flag,-1 + jz not_uninit +;unitialize! + mov ax,interp_color_table+2[eax*4] + jmp cont1 +not_uninit: + call find_color_index +cont1: mov 28[esi],ax ;store new color + + xor ecx,ecx + mov cx,2[esi] ;get nverts + and ecx,0fffffffeh + inc ecx ;adjust for pad + lea esi,30[esi+ecx*2] + jmp init_loop +not_flatpoly: + +;tmap polygon + cmp ax,3 + jne not_tmappoly + ifndef NDEBUG + cmp w 2[esi],3 + break_if l,'face must have 3 or more points' + endif + mov ax,28[esi] ;get bitmap number + cmp ax,_highest_texture_num + jle not_new + mov _highest_texture_num,ax +not_new: xor ecx,ecx + mov cx,2[esi] ;get nverts + mov ebx,ecx + and ebx,0fffffffeh + inc ebx ;adjust for pad + lea esi,30[esi+ebx*2] ;point at uvls + + imul ecx,12 ;size of uvls + add esi,ecx ;skip them + jmp init_loop + +;;@@init_uv_loop: mov eax,[esi] ;get u +;;@@ imul eax,64 ;times bitmap w +;;@@ mov [esi],eax +;;@@ mov eax,4[esi] ;get v +;;@@ imul eax,64 ;times bitmap h +;;@@ mov 4[esi],eax +;;@@ add esi,12 ;point at next +;;@@ dec ecx +;;@@ jnz init_uv_loop +;;@@ jmp init_loop +not_tmappoly: + +;sort + cmp ax,4 ;sortnorm + jne not_sortnorm + + push esi + xor eax,eax + mov ax,28[esi] ;get front offset + add esi,eax + call init_loop + mov esi,[esp] + xor eax,eax + mov ax,30[esi] ;get front offset + add esi,eax + call init_loop + pop esi + lea esi,32[esi] + + jmp init_loop +not_sortnorm: + cmp ax,5 + jne not_rodbm + + add esi,36 + jmp init_loop + +not_rodbm: + cmp ax,6 + jne not_subcall + + + push esi + xor eax,eax + mov ax,16[esi] ;get subobj offset + add esi,eax + call init_loop + pop esi + + add esi,20 + jmp init_loop +not_subcall: + cmp ax,7 ;defpoints + jne not_defpoints_st + xor eax,eax + mov ax,2[esi] ;get count + sal eax,1 + add ax,2[esi] ;*3 + lea esi,8[esi+eax*4] + jmp init_loop +not_defpoints_st: + cmp ax,8 + jne not_glow + add esi,4 + jmp init_loop +not_glow: + + debug_brk "Invalid opcode" + + jmp init_loop + + +;takes ecx=count, esi=ptr to point list +draw_outline: pushm eax,ebx,ecx,edx,esi,edi + + ;NO_INVERSE_TABLE xor eax,eax + ;NO_INVERSE_TABLE mov al,gr_inverse_table[7fffh] ;white + mov eax, 255 ; bright white + call gr_setcolor_ + + mov ebx,esi + + xor eax,eax + mov ax,[ebx] ;get first point + push eax ;save it + +outline_loop: xor esi,esi + xor edi,edi + mov si,[ebx] + dec ecx + jz done_loop + mov di,2[ebx] + push ebx + + imul esi,size g3s_point + add esi,Interp_point_list + imul edi,size g3s_point + add edi,Interp_point_list + + call g3_draw_line + pop ebx + + add ebx,2 + jmp outline_loop + +done_loop: pop edi ;get first point back + + imul esi,size g3s_point + add esi,Interp_point_list + imul edi,size g3s_point + add edi,Interp_point_list + + call g3_draw_line + + popm eax,ebx,ecx,edx,esi,edi + ret + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;Special code to draw morphing objects + +;define a list of points +morph_defpoints: xor ecx,ecx + mov cx,2[ebp] ;num points + mov edi,Interp_point_list + lea esi,4[ebp] +morph_rotate_list: lea eax,[ecx*2+ecx] ;eax=npoint * 3 + lea esi,[esi+eax*4] ;point past points + push esi + mov esi,morph_points ;get alternate points +morph_rotate_loop: call g3_rotate_point + add edi,size g3s_point + add esi,size vms_vector + dec ecx + jnz morph_rotate_loop + pop esi ;restore pointer + mov ebp,esi + next + +;define a list of points, with starting point num specified +morph_defp_start: xor ecx,ecx + xor eax,eax + mov ax,w 4[ebp] ;starting point num + imulc eax,size g3s_point ;get ofs of point + add eax,Interp_point_list + mov edi,eax + mov cx,2[ebp] ;num points + lea esi,8[ebp] + jmp morph_rotate_list + +;draw a flat-shaded polygon +morph_flatpoly: xor ecx,ecx + mov cx,2[ebp] ;num verts + lea esi,4[ebp] ;point + lea edi,16[ebp] ;vector + +;set color + xor eax,eax + mov ax,28[ebp] ;get color + mov ax,interp_color_table[eax*4] + call gr_setcolor_ ;set it + +;check and draw + lea esi,30[ebp] ;point number list + + xor eax,eax + lodsw + imulc eax,size g3s_point + add eax,Interp_point_list + mov morph_pointlist,eax + xor eax,eax + lodsw + imulc eax,size g3s_point + add eax,Interp_point_list + mov morph_pointlist+4,eax + xor eax,eax + lodsw + imulc eax,size g3s_point + add eax,Interp_point_list + mov morph_pointlist+8,eax + + cmp ecx,3 ;3 points is good! + je flat_got3 + sub ecx,2 ;tri count + +flat_tri_loop: xor edi,edi ;no normal, must compute + pushm ecx,esi + mov ecx,3 ;always draw triangle + lea esi,morph_pointlist + call g3_check_and_draw_poly + popm ecx,esi + + mov eax,morph_pointlist+8 + mov morph_pointlist+4,eax + xor eax,eax + lodsw + imulc eax,size g3s_point + add eax,Interp_point_list + mov morph_pointlist+8,eax + + dec ecx + jnz flat_tri_loop + jmp flat_done_draw + +flat_got3: + lea esi,morph_pointlist + xor edi,edi ;no normal, must compute + call g3_check_and_draw_poly + +flat_done_draw: xor ecx,ecx + mov cx,2[ebp] ;restore count + + and ecx,0fffffffeh + inc ecx ;adjust for pad + lea ebp,30[ebp+ecx*2] + next + +;draw a texture map +morph_tmappoly: xor ecx,ecx + mov cx,2[ebp] ;num verts + lea esi,4[ebp] ;point + lea edi,16[ebp] ;normal + +;get bitmap + xor edx,edx + mov dx,28[ebp] ;get bitmap number + mov eax,bitmap_ptr + mov edx,[eax+edx*4] + + lea esi,30[ebp] ;point number list + mov eax,ecx + and eax,0fffffffeh + inc eax + lea ebx,30[ebp+eax*2] ;get uvl list +;calculate light from surface normal + push esi + lea esi,View_matrix.fvec + lea edi,16[ebp] ;normal + call vm_vec_dotprod + neg eax +;scale light by model light + push edx + mov edx,eax + add eax,eax + add eax,edx ;eax *= 3 + sar eax,2 ;eax *= 3/4 + add eax,f1_0/4 ;eax = 1/4 + eax * 3/4 + fixmul model_light + + or eax,eax + jge not_zero + xor eax,eax +not_zero: + pop edx + pop esi + +;now eax=plane light value + + mov morph_uvls+8,eax + mov morph_uvls+20,eax + mov morph_uvls+32,eax + + xor eax,eax + lodsw + imulc eax,size g3s_point + add eax,Interp_point_list + mov morph_pointlist,eax + xor eax,eax + lodsw + imulc eax,size g3s_point + add eax,Interp_point_list + mov morph_pointlist+4,eax + xor eax,eax + lodsw + imulc eax,size g3s_point + add eax,Interp_point_list + mov morph_pointlist+8,eax + + cmp ecx,3 ;3 points is good! + jl tmap_done_draw ;something is bad, abort + je tmap_got3 + sub ecx,2 ;tri count + + push edx + + mov edx,[ebx] + mov morph_uvls,edx + mov edx,4[ebx] + mov morph_uvls+4,edx + + mov edx,12[ebx] + mov morph_uvls+12,edx + mov edx,16[ebx] + mov morph_uvls+16,edx + + mov edx,24[ebx] + mov morph_uvls+24,edx + mov edx,28[ebx] + mov morph_uvls+28,edx + + add ebx,3*12 + + pop edx + + +tmap_tri_loop: xor edi,edi ;no normal, must compute + pushm ebx,edx,ecx,esi + mov ecx,3 ;always draw triangle + lea esi,morph_pointlist + lea ebx,morph_uvls + call g3_check_and_draw_tmap + popm ebx,edx,ecx,esi + + mov eax,morph_pointlist+8 + mov morph_pointlist+4,eax + xor eax,eax + lodsw + imulc eax,size g3s_point + add eax,Interp_point_list + mov morph_pointlist+8,eax + + push edx + mov edx,morph_uvls+24 + mov morph_uvls+12,edx + mov edx,morph_uvls+28 + mov morph_uvls+16,edx + + mov edx,[ebx] + mov morph_uvls+24,edx + mov edx,4[ebx] + mov morph_uvls+28,edx + add ebx,12 + pop edx + + dec ecx + jnz tmap_tri_loop + jmp tmap_done_draw + +tmap_got3: +;poke in light values + pusha +tmap_l_loop: mov 8[ebx],eax + add ebx,12 + dec ecx + jnz tmap_l_loop + popa + + lea esi,morph_pointlist + + xor edi,edi ;no normal + call g3_check_and_draw_tmap + +tmap_done_draw: xor ecx,ecx + mov cx,2[ebp] ;restore count + +;jump to next opcode + mov ebx,ecx + and ebx,0fffffffeh + inc ebx ;adjust for pad + lea ebp,30[ebp+ebx*2] + + mov eax,ecx + sal ecx,1 + add ecx,eax + sal ecx,2 ;ecx=ecx*12 + add ebp,ecx ;point past uvls + + next + + +;interpreter to draw polygon model +;takes esi=ptr to object, edi=ptr to array of bitmap pointers, +;eax=ptr to anim angles, ebx=alternate points, edx=light value + +g3_draw_morphing_model: + pushm eax,ebx,ecx,edx,esi,edi,ebp + + mov bitmap_ptr,edi ;save ptr to bitmap array + mov anim_angles,eax + mov morph_points,ebx + mov model_light,edx + + mov ebp,esi ;ebp = interp ptr + + ;set alternate opcode pointers + + push opcode_table[1*4] ;defpoints + push opcode_table[2*4] ;flatpoly + push opcode_table[3*4] ;tmappoly + push opcode_table[7*4] ;defp_start + + mov opcode_table[1*4],offset morph_defpoints + mov opcode_table[2*4],offset morph_flatpoly + mov opcode_table[3*4],offset morph_tmappoly + mov opcode_table[7*4],offset morph_defp_start + + call_next + + pop opcode_table[7*4] ;defp_start + pop opcode_table[3*4] ;tmappoly + pop opcode_table[2*4] ;flatpoly + pop opcode_table[1*4] ;defpoints + + popm eax,ebx,ecx,edx,esi,edi,ebp + ret + +_TEXT ends + + end + diff --git a/3d/interp.c b/3d/interp.c new file mode 100644 index 00000000..9f0899bd --- /dev/null +++ b/3d/interp.c @@ -0,0 +1,537 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERV +*/ +/* + * $Source: /cvs/cvsroot/d2x/3d/interp.c,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:29:58 $ + * + * Polygon object interpreter + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 21:57:47 donut + * Import of d1x 1.37 source. + * + * Revision 1.4 1995/10/10 22:20:09 allender + * new morphing code from Matt + * + * Revision 1.3 1995/08/31 15:40:24 allender + * swap color data correctly + * + * Revision 1.2 1995/05/11 13:06:38 allender + * fix int --> short problem + * + * Revision 1.1 1995/05/05 08:51:41 allender + * Initial revision + * + * Revision 1.1 1995/04/17 06:44:33 matt + * Initial revision + * + * + */ + +#ifdef RCS +static char rcsid[] = "$Id: interp.c,v 1.1.1.1 2001-01-19 03:29:58 bradleyb Exp $"; +#endif + +#include +#include + +#include "fix.h" +#include "vecmat.h" +#include "gr.h" +#include "3d.h" +#include "globvars.h" +#include "error.h" + +#define OP_EOF 0 //eof +#define OP_DEFPOINTS 1 //defpoints +#define OP_FLATPOLY 2 //flat-shaded polygon +#define OP_TMAPPOLY 3 //texture-mapped polygon +#define OP_SORTNORM 4 //sort by normal +#define OP_RODBM 5 //rod bitmap +#define OP_SUBCALL 6 //call a subobject +#define OP_DEFP_START 7 //defpoints with start +#define OP_GLOW 8 //glow value for next poly + +#define N_OPCODES (sizeof(opcode_table) / sizeof(*opcode_table)) + +#define MAX_POINTS_PER_POLY 25 + +short highest_texture_num; +int g3d_interp_outline; + +g3s_point *Interp_point_list=NULL; + +#define MAX_INTERP_COLORS 100 + +//this is a table of mappings from RGB15 to palette colors +struct {short pal_entry,rgb15;} interp_color_table[MAX_INTERP_COLORS]; + +int n_interp_colors=0; + +//gives the interpreter an array of points to use +void g3_set_interp_points(g3s_point *pointlist) +{ + Interp_point_list = pointlist; +} + +#define w(p) (*((short *) (p))) +#define wp(p) ((short *) (p)) +#define vp(p) ((vms_vector *) (p)) + +void rotate_point_list(g3s_point *dest,vms_vector *src,int n) +{ + while (n--) + g3_rotate_point(dest++,src++); +} + +vms_angvec zero_angles = {0,0,0}; + +g3s_point *point_list[MAX_POINTS_PER_POLY]; + +int glow_num = -1; + +//calls the object interpreter to render an object. The object renderer +//is really a seperate pipeline. returns true if drew +bool g3_draw_polygon_model(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,fix model_light,fix *glow_values) +{ + ubyte *p = model_ptr; + + glow_num = -1; //glow off by default + + while (w(p) != OP_EOF) + + switch (w(p)) { + + case OP_DEFPOINTS: { + int n = w(p+2); + + rotate_point_list(Interp_point_list,vp(p+4),n); + p += n*sizeof(struct vms_vector) + 4; + + break; + } + + case OP_DEFP_START: { + int n = w(p+2); + int s = w(p+4); + + rotate_point_list(&Interp_point_list[s],vp(p+8),n); + p += n*sizeof(struct vms_vector) + 8; + + break; + } + + case OP_FLATPOLY: { + int nv = w(p+2); + + Assert( nv < MAX_POINTS_PER_POLY ); + if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) { + int i; + short c; + unsigned char cc; + int l; + +// DPH: Now we treat this color as 15bpp +// gr_setcolor(w(p+28)); + + //l = (32 * model_light) >> 16; + l = f2i(fixmul(i2f(32), model_light)); + if (l<0) l = 0; + else if (l>32) l = 32; + cc = gr_find_closest_color_15bpp(w(p+28)); + c = gr_fade_table[(l<<8)|cc]; + gr_setcolor(c); + + for (i=0;i 0) { + int i; + fix light; + + //calculate light from surface normal + + if (glow_num < 0) { //no glow + + light = -vm_vec_dot(&View_matrix.fvec,vp(p+16)); + light = f1_0/4 + (light*3)/4; + light = fixmul(light,model_light); + } + else { //yes glow + light = glow_values[glow_num]; + glow_num = -1; + } + + //now poke light into l values + + uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2); + + for (i=0;i 0) { //facing + + //draw back then front + + g3_draw_polygon_model(p+w(p+30),model_bitmaps,anim_angles,model_light,glow_values); + g3_draw_polygon_model(p+w(p+28),model_bitmaps,anim_angles,model_light,glow_values); + + } + else { //not facing. draw front then back + + g3_draw_polygon_model(p+w(p+28),model_bitmaps,anim_angles,model_light,glow_values); + g3_draw_polygon_model(p+w(p+30),model_bitmaps,anim_angles,model_light,glow_values); + } + + p += 32; + + break; + + + case OP_RODBM: { + g3s_point rod_bot_p,rod_top_p; + + g3_rotate_point(&rod_bot_p,vp(p+20)); + g3_rotate_point(&rod_top_p,vp(p+4)); + + g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),f1_0); + + p+=36; + break; + } + + case OP_SUBCALL: { + vms_angvec *a; + + if (anim_angles) + a = &anim_angles[w(p+2)]; + else + a = &zero_angles; + + g3_start_instance_angles(vp(p+4),a); + + g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values); + + g3_done_instance(); + + p += 20; + + break; + + } + + case OP_GLOW: + + if (glow_values) + glow_num = w(p+2); + p += 4; + break; + + default: + ; + } + return 1; +} + +extern int gr_find_closest_color_15bpp( int rgb ); + +#ifndef NDEBUG +int nest_count; +#endif + +//alternate interpreter for morphing object +bool g3_draw_morphing_model(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,fix model_light,vms_vector *new_points) +{ + ubyte *p = model_ptr; + fix *glow_values = NULL; + + glow_num = -1; //glow off by default + + while (w(p) != OP_EOF) + + switch (w(p)) { + + case OP_DEFPOINTS: { + int n = w(p+2); + + rotate_point_list(Interp_point_list,new_points,n); + p += n*sizeof(struct vms_vector) + 4; + + break; + } + + case OP_DEFP_START: { + int n = w(p+2); + int s = w(p+4); + + rotate_point_list(&Interp_point_list[s],new_points,n); + p += n*sizeof(struct vms_vector) + 8; + + break; + } + + case OP_FLATPOLY: { + int nv = w(p+2); + int i,ntris; + + gr_setcolor(w(p+28)); + + for (i=0;i<2;i++) + point_list[i] = Interp_point_list + wp(p+30)[i]; + + for (ntris=nv-2;ntris;ntris--) { + + point_list[2] = Interp_point_list + wp(p+30)[i++]; + + g3_check_and_draw_poly(3,point_list,NULL,NULL); + + point_list[1] = point_list[2]; + + } + + p += 30 + ((nv&~1)+1)*2; + + break; + } + + case OP_TMAPPOLY: { + int nv = w(p+2); + g3s_uvl *uvl_list; + g3s_uvl morph_uvls[3]; + int i,ntris; + fix light; + + //calculate light from surface normal + + if (glow_num < 0) { //no glow + + light = -vm_vec_dot(&View_matrix.fvec,vp(p+16)); + light = f1_0/4 + (light*3)/4; + light = fixmul(light,model_light); + } + else { //yes glow + light = glow_values[glow_num]; + glow_num = -1; + } + + //now poke light into l values + + uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2); + + for (i=0;i<3;i++) + morph_uvls[i].l = light; + + for (i=0;i<2;i++) { + point_list[i] = Interp_point_list + wp(p+30)[i]; + + morph_uvls[i].u = uvl_list[i].u; + morph_uvls[i].v = uvl_list[i].v; + } + + for (ntris=nv-2;ntris;ntris--) { + + point_list[2] = Interp_point_list + wp(p+30)[i]; + morph_uvls[2].u = uvl_list[i].u; + morph_uvls[2].v = uvl_list[i].v; + i++; + + g3_check_and_draw_tmap(3,point_list,uvl_list,model_bitmaps[w(p+28)],NULL,NULL); + + point_list[1] = point_list[2]; + morph_uvls[1].u = morph_uvls[2].u; + morph_uvls[1].v = morph_uvls[2].v; + + } + + p += 30 + ((nv&~1)+1)*2 + nv*12; + + break; + } + + case OP_SORTNORM: + + if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) { //facing + + //draw back then front + + g3_draw_morphing_model(p+w(p+30),model_bitmaps,anim_angles,model_light,new_points); + g3_draw_morphing_model(p+w(p+28),model_bitmaps,anim_angles,model_light,new_points); + + } + else { //not facing. draw front then back + + g3_draw_morphing_model(p+w(p+28),model_bitmaps,anim_angles,model_light,new_points); + g3_draw_morphing_model(p+w(p+30),model_bitmaps,anim_angles,model_light,new_points); + } + + p += 32; + + break; + + + case OP_RODBM: { + g3s_point rod_bot_p,rod_top_p; + + g3_rotate_point(&rod_bot_p,vp(p+20)); + g3_rotate_point(&rod_top_p,vp(p+4)); + + g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),f1_0); + + p+=36; + break; + } + + case OP_SUBCALL: { + vms_angvec *a; + + if (anim_angles) + a = &anim_angles[w(p+2)]; + else + a = &zero_angles; + + g3_start_instance_angles(vp(p+4),a); + + g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values); + + g3_done_instance(); + + p += 20; + + break; + + } + + case OP_GLOW: + + if (glow_values) + glow_num = w(p+2); + p += 4; + break; + } + + return 1; +} + +void init_model_sub(ubyte *p) +{ + Assert(++nest_count < 1000); + + while (w(p) != OP_EOF) { + + switch (w(p)) { + + case OP_DEFPOINTS: { + int n = w(p+2); + p += n*sizeof(struct vms_vector) + 4; + break; + } + + case OP_DEFP_START: { + int n = w(p+2); + p += n*sizeof(struct vms_vector) + 8; + break; + } + + case OP_FLATPOLY: { + int nv = w(p+2); + + Assert(nv > 2); //must have 3 or more points + +// *wp(p+28) = (short)gr_find_closest_color_15bpp(w(p+28)); + + p += 30 + ((nv&~1)+1)*2; + + break; + } + + case OP_TMAPPOLY: { + int nv = w(p+2); + + Assert(nv > 2); //must have 3 or more points + + if (w(p+28) > highest_texture_num) + highest_texture_num = w(p+28); + + p += 30 + ((nv&~1)+1)*2 + nv*12; + + break; + } + + case OP_SORTNORM: + + init_model_sub(p+w(p+28)); + init_model_sub(p+w(p+30)); + p += 32; + + break; + + + case OP_RODBM: + p += 36; + break; + + + case OP_SUBCALL: { + init_model_sub(p+w(p+16)); + p += 20; + break; + + } + + case OP_GLOW: + p += 4; + break; + } + } +} + +//init code for bitmap models +void g3_init_polygon_model(void *model_ptr) +{ + #ifndef NDEBUG + nest_count = 0; + #endif + + highest_texture_num = -1; + + init_model_sub((ubyte *) model_ptr); +} + diff --git a/3d/matrix.c b/3d/matrix.c new file mode 100644 index 00000000..e9301b5b --- /dev/null +++ b/3d/matrix.c @@ -0,0 +1,104 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/3d/matrix.c,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:29:58 $ + * + * Matrix setup & manipulation routines + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 21:57:48 donut + * Import of d1x 1.37 source. + * + * Revision 1.1 1995/05/05 08:52:11 allender + * Initial revision + * + * Revision 1.1 1995/04/17 04:14:34 matt + * Initial revision + * + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: matrix.c,v 1.1.1.1 2001-01-19 03:29:58 bradleyb Exp $"; +#endif + +#include +#include "fix.h" +#include "vecmat.h" +#include "gr.h" +#include "3d.h" +#include "globvars.h" + +void scale_matrix(void); + +//set view from x,y,z & p,b,h, zoom. Must call one of g3_set_view_*() +void g3_set_view_angles(vms_vector *view_pos,vms_angvec *view_orient,fix zoom) +{ + View_zoom = zoom; + View_position = *view_pos; + + vm_angles_2_matrix(&View_matrix,view_orient); + +#ifdef D1XD3D + Win32_set_view_matrix (); +#endif + + scale_matrix(); +} + +//set view from x,y,z, viewer matrix, and zoom. Must call one of g3_set_view_*() +void g3_set_view_matrix(vms_vector *view_pos,vms_matrix *view_matrix,fix zoom) +{ + View_zoom = zoom; + View_position = *view_pos; + + View_matrix = *view_matrix; + +#ifdef D1XD3D + Win32_set_view_matrix (); +#endif + + scale_matrix(); +} + +//performs aspect scaling on global view matrix +void scale_matrix(void) +{ + Unscaled_matrix = View_matrix; //so we can use unscaled if we want + + Matrix_scale = Window_scale; + + if (View_zoom <= f1_0) //zoom in by scaling z + + Matrix_scale.z = fixmul(Matrix_scale.z,View_zoom); + + else { //zoom out by scaling x&y + + fix s = fixdiv(f1_0,View_zoom); + + Matrix_scale.x = fixmul(Matrix_scale.x,s); + Matrix_scale.y = fixmul(Matrix_scale.y,s); + } + + //now scale matrix elements + + vm_vec_scale(&View_matrix.rvec,Matrix_scale.x); + vm_vec_scale(&View_matrix.uvec,Matrix_scale.y); + vm_vec_scale(&View_matrix.fvec,Matrix_scale.z); + +} + diff --git a/3d/points.c b/3d/points.c new file mode 100644 index 00000000..65473707 --- /dev/null +++ b/3d/points.c @@ -0,0 +1,231 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/3d/points.c,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:29:58 $ + * + * Routines for point definition, rotation, etc. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 21:57:49 donut + * Import of d1x 1.37 source. + * + * Revision 1.3 1995/09/21 17:29:40 allender + * changed project_point to overflow if z <= 0 + * + * Revision 1.2 1995/09/13 11:31:28 allender + * removed checkmuldiv from g3_project_point + * + * Revision 1.1 1995/05/05 08:52:35 allender + * Initial revision + * + * Revision 1.1 1995/04/17 04:32:25 matt + * Initial revision + * + * + */ + +#ifdef RCS +static char rcsid[] = "$Id: points.c,v 1.1.1.1 2001-01-19 03:29:58 bradleyb Exp $"; +#endif + + +#include +#include "fix.h" +#include "vecmat.h" +#include "gr.h" +#include "3d.h" +#include "globvars.h" + + +//code a point. fills in the p3_codes field of the point, and returns the codes +ubyte g3_code_point(g3s_point *p) +{ + ubyte cc=0; + + if (p->p3_x > p->p3_z) + cc |= CC_OFF_RIGHT; + + if (p->p3_y > p->p3_z) + cc |= CC_OFF_TOP; + + if (p->p3_x < -p->p3_z) + cc |= CC_OFF_LEFT; + + if (p->p3_y < -p->p3_z) + cc |= CC_OFF_BOT; + + if (p->p3_z < 0) + cc |= CC_BEHIND; + + return p->p3_codes = cc; + +} + +//rotates a point. returns codes. does not check if already rotated +ubyte g3_rotate_point(g3s_point *dest,vms_vector *src) +{ + vms_vector tempv; + +#ifdef D1XD3D + dest->p3_orig = *src; +#endif + + vm_vec_sub(&tempv,src,&View_position); + + vm_vec_rotate(&dest->p3_vec,&tempv,&View_matrix); + + dest->p3_flags = 0; //no projected + + return g3_code_point(dest); + +} + +//checks for overflow & divides if ok, fillig in r +//returns true if div is ok, else false +int checkmuldiv(fix *r,fix a,fix b,fix c) +{ + quad q,qt; + + q.low=q.high=0; + fixmulaccum(&q,a,b); + + qt = q; + if (qt.high < 0) + fixquadnegate(&qt); + + qt.high *= 2; + if (qt.low > 0x7fff) + qt.high++; + + if (qt.high >= c) + return 0; + else { + *r = fixdivquadlong(q.low,q.high,c); + return 1; + } +} + +//projects a point +void g3_project_point(g3s_point *p) +{ +#ifndef __powerc + fix tx,ty; + + if (p->p3_flags & PF_PROJECTED || p->p3_codes & CC_BEHIND) + return; + + if (checkmuldiv(&tx,p->p3_x,Canv_w2,p->p3_z) && checkmuldiv(&ty,p->p3_y,Canv_h2,p->p3_z)) { + p->p3_sx = Canv_w2 + tx; + p->p3_sy = Canv_h2 - ty; + p->p3_flags |= PF_PROJECTED; + } + else + p->p3_flags |= PF_OVERFLOW; +#else + double fz; + + if ((p->p3_flags & PF_PROJECTED) || (p->p3_codes & CC_BEHIND)) + return; + + if ( p->p3_z <= 0 ) { + p->p3_flags |= PF_OVERFLOW; + return; + } + + fz = f2fl(p->p3_z); + p->p3_sx = fl2f(fCanv_w2 + (f2fl(p->p3_x)*fCanv_w2 / fz)); + p->p3_sy = fl2f(fCanv_h2 - (f2fl(p->p3_y)*fCanv_h2 / fz)); + + p->p3_flags |= PF_PROJECTED; +#endif +} + +//from a 2d point, compute the vector through that point +void g3_point_2_vec(vms_vector *v,short sx,short sy) +{ + vms_vector tempv; + vms_matrix tempm; + + tempv.x = fixmuldiv(fixdiv((sx<<16) - Canv_w2,Canv_w2),Matrix_scale.z,Matrix_scale.x); + tempv.y = -fixmuldiv(fixdiv((sy<<16) - Canv_h2,Canv_h2),Matrix_scale.z,Matrix_scale.y); + tempv.z = f1_0; + + vm_vec_normalize(&tempv); + + vm_copy_transpose_matrix(&tempm,&Unscaled_matrix); + + vm_vec_rotate(v,&tempv,&tempm); + +} + +//delta rotation functions +vms_vector *g3_rotate_delta_x(vms_vector *dest,fix dx) +{ + dest->x = fixmul(View_matrix.rvec.x,dx); + dest->y = fixmul(View_matrix.uvec.x,dx); + dest->z = fixmul(View_matrix.fvec.x,dx); + + return dest; +} + +vms_vector *g3_rotate_delta_y(vms_vector *dest,fix dy) +{ + dest->x = fixmul(View_matrix.rvec.y,dy); + dest->y = fixmul(View_matrix.uvec.y,dy); + dest->z = fixmul(View_matrix.fvec.y,dy); + + return dest; +} + +vms_vector *g3_rotate_delta_z(vms_vector *dest,fix dz) +{ + dest->x = fixmul(View_matrix.rvec.z,dz); + dest->y = fixmul(View_matrix.uvec.z,dz); + dest->z = fixmul(View_matrix.fvec.z,dz); + + return dest; +} + + +vms_vector *g3_rotate_delta_vec(vms_vector *dest,vms_vector *src) +{ + return vm_vec_rotate(dest,src,&View_matrix); +} + +ubyte g3_add_delta_vec(g3s_point *dest,g3s_point *src,vms_vector *deltav) +{ + vm_vec_add(&dest->p3_vec,&src->p3_vec,deltav); + + dest->p3_flags = 0; //not projected + + return g3_code_point(dest); +} + +//calculate the depth of a point - returns the z coord of the rotated point +fix g3_calc_point_depth(vms_vector *pnt) +{ + quad q; + + q.low=q.high=0; + fixmulaccum(&q,(pnt->x - View_position.x),View_matrix.fvec.x); + fixmulaccum(&q,(pnt->y - View_position.y),View_matrix.fvec.y); + fixmulaccum(&q,(pnt->z - View_position.z),View_matrix.fvec.z); + + return fixquadadjust(&q); +} + + + diff --git a/3d/rod.c b/3d/rod.c new file mode 100644 index 00000000..9f5e9d8d --- /dev/null +++ b/3d/rod.c @@ -0,0 +1,223 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/3d/rod.c,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:29:58 $ + * + * Rod routines + * + * $Log: not supported by cvs2svn $ + * Revision 1.2 1999/09/21 04:05:55 donut + * mostly complete OGL implementation (still needs bitmap handling (reticle), and door/fan textures are corrupt) + * + * Revision 1.1.1.1 1999/06/14 21:57:50 donut + * Import of d1x 1.37 source. + * + * Revision 1.2 1995/09/13 11:31:46 allender + * removed checkmuldiv in PPC implemenation + * + * Revision 1.1 1995/05/05 08:52:45 allender + * Initial revision + * + * Revision 1.1 1995/04/17 06:42:08 matt + * Initial revision + * + * + */ + +#ifdef RCS +static char rcsid[] = "$Id: rod.c,v 1.1.1.1 2001-01-19 03:29:58 bradleyb Exp $"; +#endif + +#include +#include "fix.h" +#include "vecmat.h" +#include "gr.h" +#include "3d.h" +#include "globvars.h" + +grs_point blob_vertices[4]; +g3s_point rod_points[4]; +g3s_point *rod_point_list[] = {&rod_points[0],&rod_points[1],&rod_points[2],&rod_points[3]}; + +g3s_uvl uvl_list[4] = { { 0x0200,0x0200,0 }, + { 0xfe00,0x0200,0 }, + { 0xfe00,0xfe00,0 }, + { 0x0200,0xfe00,0 }}; + +//compute the corners of a rod. fills in vertbuf. +int calc_rod_corners(g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width) +{ + vms_vector delta_vec,top,tempv,rod_norm; + ubyte codes_and; + int i; + + //compute vector from one point to other, do cross product with vector + //from eye to get perpendiclar + + vm_vec_sub(&delta_vec,&bot_point->p3_vec,&top_point->p3_vec); + + //unscale for aspect + + delta_vec.x = fixdiv(delta_vec.x,Matrix_scale.x); + delta_vec.y = fixdiv(delta_vec.y,Matrix_scale.y); + + //calc perp vector + + //do lots of normalizing to prevent overflowing. When this code works, + //it should be optimized + + vm_vec_normalize(&delta_vec); + + vm_vec_copy_normalize(&top,&top_point->p3_vec); + + vm_vec_cross(&rod_norm,&delta_vec,&top); + + vm_vec_normalize(&rod_norm); + + //scale for aspect + + rod_norm.x = fixmul(rod_norm.x,Matrix_scale.x); + rod_norm.y = fixmul(rod_norm.y,Matrix_scale.y); + + //now we have the usable edge. generate four points + + //top points + + vm_vec_copy_scale(&tempv,&rod_norm,top_width); + tempv.z = 0; + + vm_vec_add(&rod_points[0].p3_vec,&top_point->p3_vec,&tempv); + vm_vec_sub(&rod_points[1].p3_vec,&top_point->p3_vec,&tempv); + + vm_vec_copy_scale(&tempv,&rod_norm,bot_width); + tempv.z = 0; + + vm_vec_sub(&rod_points[2].p3_vec,&bot_point->p3_vec,&tempv); + vm_vec_add(&rod_points[3].p3_vec,&bot_point->p3_vec,&tempv); + + + //now code the four points + + for (i=0,codes_and=0xff;i<4;i++) + codes_and &= g3_code_point(&rod_points[i]); + + if (codes_and) + return 1; //1 means off screen + + //clear flags for new points (not projected) + + for (i=0;i<4;i++) + rod_points[i].p3_flags = 0; + + return 0; +} + +//draw a polygon that is always facing you +//returns 1 if off screen, 0 if drew +bool g3_draw_rod_flat(g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width) +{ + if (calc_rod_corners(bot_point,bot_width,top_point,top_width)) + return 0; + + return g3_draw_poly(4,rod_point_list); + +} + +//draw a bitmap object that is always facing you +//returns 1 if off screen, 0 if drew +bool g3_draw_rod_tmap(grs_bitmap *bitmap,g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width,fix light) +{ + if (calc_rod_corners(bot_point,bot_width,top_point,top_width)) + return 0; + + uvl_list[0].l = uvl_list[1].l = uvl_list[2].l = uvl_list[3].l = light; + + return g3_draw_tmap(4,rod_point_list,uvl_list,bitmap); +} + +#ifndef __powerc +int checkmuldiv(fix *r,fix a,fix b,fix c); +#endif + +#if (!(defined(D1XD3D) || defined(OGL))) +//draws a bitmap with the specified 3d width & height +//returns 1 if off screen, 0 if drew +bool g3_draw_bitmap(vms_vector *pos,fix width,fix height,grs_bitmap *bm, int orientation) +{ +#ifndef __powerc + g3s_point pnt; + fix t,w,h; + + if (g3_rotate_point(&pnt,pos) & CC_BEHIND) + return 1; + + g3_project_point(&pnt); + + if (pnt.p3_flags & PF_OVERFLOW) + return 1; + + if (checkmuldiv(&t,width,Canv_w2,pnt.p3_z)) + w = fixmul(t,Matrix_scale.x); + else + return 1; + + if (checkmuldiv(&t,height,Canv_h2,pnt.p3_z)) + h = fixmul(t,Matrix_scale.y); + else + return 1; + + blob_vertices[0].x = pnt.p3_sx - w; + blob_vertices[0].y = blob_vertices[1].y = pnt.p3_sy - h; + blob_vertices[1].x = blob_vertices[2].x = pnt.p3_sx + w; + blob_vertices[2].y = pnt.p3_sy + h; + + scale_bitmap(bm,blob_vertices,0); + + return 0; +#else + g3s_point pnt; + fix w,h; + double fz; + + if (g3_rotate_point(&pnt,pos) & CC_BEHIND) + return 1; + + g3_project_point(&pnt); + + if (pnt.p3_flags & PF_OVERFLOW) + return 1; + + if (pnt.p3_z == 0) + return 1; + + fz = f2fl(pnt.p3_z); + w = fixmul(fl2f(((f2fl(width)*fCanv_w2) / fz)), Matrix_scale.x); + h = fixmul(fl2f(((f2fl(height)*fCanv_h2) / fz)), Matrix_scale.y); + + blob_vertices[0].x = pnt.p3_sx - w; + blob_vertices[0].y = blob_vertices[1].y = pnt.p3_sy - h; + blob_vertices[1].x = blob_vertices[2].x = pnt.p3_sx + w; + blob_vertices[2].y = pnt.p3_sy + h; + + scale_bitmap(bm,blob_vertices); + + return 0; +#endif +} +#endif + + + diff --git a/3d/setup.c b/3d/setup.c new file mode 100644 index 00000000..37ed8abc --- /dev/null +++ b/3d/setup.c @@ -0,0 +1,139 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/3d/setup.c,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:29:58 $ + * + * Setup for 3d library + * + * $Log: not supported by cvs2svn $ + * Revision 1.3 1999/10/07 02:27:14 donut + * OGL includes to remove warnings + * + * Revision 1.2 1999/09/21 04:05:55 donut + * mostly complete OGL implementation (still needs bitmap handling (reticle), and door/fan textures are corrupt) + * + * Revision 1.1.1.1 1999/06/14 21:57:50 donut + * Import of d1x 1.37 source. + * + * Revision 1.4 1995/10/11 00:27:04 allender + * bash free_num_points to 0 + * + * Revision 1.3 1995/09/13 11:31:58 allender + * calc for fCanv_w2 and fCanv_h2 + * + * Revision 1.2 1995/06/25 21:57:57 allender + * *** empty log message *** + * + * Revision 1.1 1995/05/05 08:52:54 allender + * Initial revision + * + * Revision 1.1 1995/04/17 03:59:01 matt + * Initial revision + * + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: setup.c,v 1.1.1.1 2001-01-19 03:29:58 bradleyb Exp $"; +#endif + +#include +#include + +#include "error.h" + +#include "fix.h" +#include "vecmat.h" +#include "gr.h" +#include "3d.h" +#include "globvars.h" +#include "clipper.h" + +#ifdef OGL +#include "ogl_init.h" +#endif + +//initialize the 3d system +void g3_init(void) +{ +// div0_init(DM_ERROR); + atexit(g3_close); +} + +//close down the 3d system +void g3_close(void) {} + +extern void init_interface_vars_to_assembler(void); + +//start the frame +void g3_start_frame(void) +{ + fix s; + + //set int w,h & fixed-point w,h/2 + Canv_w2 = (Canvas_width = grd_curcanv->cv_bitmap.bm_w)<<15; + Canv_h2 = (Canvas_height = grd_curcanv->cv_bitmap.bm_h)<<15; +#ifdef __powerc + fCanv_w2 = f2fl((Canvas_width = grd_curcanv->cv_bitmap.bm_w)<<15); + fCanv_h2 = f2fl((Canvas_height = grd_curcanv->cv_bitmap.bm_h)<<15); +#endif + + //compute aspect ratio for this canvas + + s = fixmuldiv(grd_curscreen->sc_aspect,Canvas_height,Canvas_width); + + if (s <= f1_0) { //scale x + Window_scale.x = s; + Window_scale.y = f1_0; + } + else { + Window_scale.y = fixdiv(f1_0,s); + Window_scale.x = f1_0; + } + + Window_scale.z = f1_0; //always 1 + + init_free_points(); + +#ifdef D1XD3D + Win32_start_frame (); +#else +#ifdef OGL + ogl_start_frame(); +#else + init_interface_vars_to_assembler(); //for the texture-mapper +#endif +#endif + +} + +//this doesn't do anything, but is here for completeness +void g3_end_frame(void) +{ +#ifdef D1XD3D + Win32_end_frame (); +#endif +#ifdef OGL + ogl_end_frame(); +#endif + +// Assert(free_point_num==0); + free_point_num = 0; + +} + + diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..5743b611 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Parallax Software Corporation (original authors) +Peter Hawkins diff --git a/COPYING b/COPYING new file mode 100644 index 00000000..b23848af --- /dev/null +++ b/COPYING @@ -0,0 +1,21 @@ +Original Descent 2 code license: + +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. + +We make no warranties as to the usability or correctness of this code. + +Additional restrictions: +Any executable created using files or code taken from this source tree +MUST be open source. By using this source, you are agreeing to this +term, in the interest of the descent and descent programming +communities. The only exception is if the writer of the original +source gives explicit permission for the code to be used otherwise. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 00000000..ac2fd95a --- /dev/null +++ b/ChangeLog @@ -0,0 +1,22 @@ +--- Version 0.0.8 --- +Added -nocdrom option, fixed cdrom code. +Made various error messages more helpful. +Big code cleanup - removed lots and lots of warnings. Still plenty left, but most are gone. +Kludge to allow the game to work with v1.0 datafiles. +Workaround for odd gcc bug (possible). +Fixed mission and demo loading. +Fixed nonetwork build. +Removed libtool dependancy. (Thanks to Falk Hueffner for pointing this out) +--- Version 0.0.7 --- +Added beginnings of console. (main/console.c main/cmd.c) +Added -debug command line option to show debug information. +Fixed -nosound option. +Changed malloc, calloc, free -> d_malloc, d_calloc and d_free to prevent ugly clashes between the real and the wrapped system calls. Added d_strdup +Removed dos linefeeds from the source files +Fixed palette problems with flat shaded polygons. + +Issues currently under investigation: +* Weird crash reported by Robert Linden - as yet unreproducable +--- Version 0.0.6 --- +Initial ChangeLog entry +No change from v0.0.5 except Makefile/config system cleanup. diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..c69d049c --- /dev/null +++ b/INSTALL @@ -0,0 +1,17 @@ +Firstly, compile d2x. + +Then stick it in a directory with these files from a Descent 2 Registered installation (the version _does not_ matter). Shareware may work if you hack at the shareware build system, but I haven't even attempted it. + +I needed these files: (in addition to the d2x binary) +alien1.pig +alien2.pig +descent2.ham +descent2.hog +descent2.s11 +descent2.s22 +fire.pig +groupa.pig +ice.pig +water.pig + +Note the filenames must be in _lower case_. It's important. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..e707d25c --- /dev/null +++ b/Makefile.am @@ -0,0 +1,7 @@ +SUBDIRS = 2d 3d maths mem cfile iff texmap misc input video sound arch main + +## to automatically rebuild aclocal.m4 if any of the macros in +## `macros/' change +@MAINT@include macros/macros.dep +@MAINT@macros/macros.dep: macros/Makefile.am +@MAINT@ cd macros && $(MAKE) macros.dep diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 00000000..be3ba77c --- /dev/null +++ b/Makefile.in @@ -0,0 +1,363 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +CFLAGS = @CFLAGS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +NASM = @NASM@ +NASMFLAGS = @NASMFLAGS@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_LIBS = @SDL_LIBS@ +VERSION = @VERSION@ + +SUBDIRS = 2d 3d maths mem cfile iff texmap misc input video sound arch main +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = conf.h +CONFIG_CLEAN_FILES = +DIST_COMMON = README ./stamp-h.in AUTHORS COPYING ChangeLog INSTALL \ +Makefile.am Makefile.in NEWS aclocal.m4 conf.h.in config.guess \ +config.sub configure configure.in install-sh ltconfig ltmain.sh missing \ +mkinstalldirs + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +all: all-redirect +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.in + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +conf.h: stamp-h + @if test ! -f $@; then \ + rm -f stamp-h; \ + $(MAKE) stamp-h; \ + else :; fi +stamp-h: $(srcdir)/conf.h.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES= CONFIG_HEADERS=conf.h \ + $(SHELL) ./config.status + @echo timestamp > stamp-h 2> /dev/null +$(srcdir)/conf.h.in: @MAINTAINER_MODE_TRUE@$(srcdir)/stamp-h.in + @if test ! -f $@; then \ + rm -f $(srcdir)/stamp-h.in; \ + $(MAKE) $(srcdir)/stamp-h.in; \ + else :; fi +$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOHEADER) + @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null + +mostlyclean-hdr: + +clean-hdr: + +distclean-hdr: + -rm -f conf.h + +maintainer-clean-hdr: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + +@SET_MAKE@ + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + test "$$subdir" = "." && dot_seen=yes; \ + done; \ + test "$$dot_seen" = "no" && rev=". $$rev"; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) conf.h.in $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)conf.h.in$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags conf.h.in $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) dist + -rm -rf $(distdir) + @banner="$(distdir).tar.gz is ready for distribution"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + fi; \ + done +info-am: +info: info-recursive +dvi-am: +dvi: dvi-recursive +check-am: all-am +check: check-recursive +installcheck-am: +installcheck: installcheck-recursive +all-recursive-am: conf.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +install-exec-am: +install-exec: install-exec-recursive + +install-data-am: +install-data: install-data-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-recursive +uninstall-am: +uninstall: uninstall-recursive +all-am: Makefile conf.h +all-redirect: all-recursive-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: installdirs-recursive +installdirs-am: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-hdr mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-recursive + +clean-am: clean-hdr clean-tags clean-generic mostlyclean-am + +clean: clean-recursive + +distclean-am: distclean-hdr distclean-tags distclean-generic clean-am + +distclean: distclean-recursive + -rm -f config.status + +maintainer-clean-am: maintainer-clean-hdr maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-recursive + -rm -f config.status + +.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ +install-data-recursive uninstall-data-recursive install-exec-recursive \ +uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \ +all-recursive check-recursive installcheck-recursive info-recursive \ +dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ +dvi-am dvi check check-am installcheck-am installcheck all-recursive-am \ +install-exec-am install-exec install-data-am install-data install-am \ +install uninstall-am uninstall all-redirect all-am all installdirs-am \ +installdirs mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +@MAINT@include macros/macros.dep +@MAINT@macros/macros.dep: macros/Makefile.am +@MAINT@ cd macros && $(MAKE) macros.dep + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/NEWS b/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/README b/README new file mode 100644 index 00000000..d78a083e --- /dev/null +++ b/README @@ -0,0 +1,96 @@ +Ok folks, this is the d2x port of descent 2. +At this stage most of descent 2 works under linux: + +Known bugs/unintentional features/missing stuff: +* Serial support doesn't work. (UDP and IPX networking does) +* Movies (unlikely ever to be supported) +* Sound glitches (due to stuff I haven't implemented) +* The mouse support is at the same level as it was in d1x (as in, it kind of works) +* Something went screwy with the control config system, it kinda got "d1xed"... +* OpenGL leaks memory like it is going out of fashion. It leaked about 64meg in a few minutes for me. I need to debug this =) + +Basically, to compile this under linux: +You need the SDL 1.0 or greater, and a thread-safe X server. +Do a ./autogen.sh then a make. Cross your fingers and pray, it worked on my machine. + +For OpenGL support, try building with --with-opengl. Your mileage may vary (but basically, you need an accelerated Mesa sitting somewhere where I can see it)... The OpenGL support isn't perfect, but it works... + +There are two ways to report bugs and give feedback: +1) Get on the descent-source mailing list by sending an email to majordomo@warpcore.org with the body as: "subscribe descent-source ". Discussions about the source code in general are available here, and is the main list that d2x and d1x, a similar project for descent 1 is discussed on. Patches and questions can be posted there, as well. + +2) Send feedback directly to me, peterhawkins@ozemail.com.au. I'll try to get back to you ASAP, depending on real-life concerns =) + + +/* THE OLD README FOLLOWS */ +Legal Stuff: + +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. + +We make no warranties as to the usability or correctness of this code. + +============================================ +Message from Matt Toschlog & Mike Kulas: + +Descent fans: + +Here, finally, is the source for Descent II. We've been so busy with +Descent 3, Mercenary, FreeSpace, FreeSpace 2, and several other +projects that we haven't given much thought to this old code. But we +know that many of you are eager to get it, so here you go. + +We were amazed and impressed at the cool things people did with +the Descent source we released a few years ago. It touches us +deeply how devoted some people are to the Descent series, and we +look forward to seeing what people can do with this Descent II +source. + +Matt Toschlog Mike Kulas +Outrage Entertainment Volition, Inc. + +============================================ + +About the Source Code: + +Included is almost all the source code to Descent 2, ver. 1.2. We removed +all code to which we did not own the copyright. This mainly involved low- +level sound and modem code and the movie code. + +The Descent Network has agreed to provide a list of mirror locations where +this code can be downloaded. The location is: + +http://www.descent2.com/ddn/sources/descent2 + +The following tools were used in the development of Descent: +Watcom C/C++, version 9.5 +Microsoft Macro Assembler, version 6.1x +Opus Make, version 6.01 + +Have fun with the code! +Parallax Software Corporation +12/14/1999 + + +As Packaged the code currently will not compile. Some code had to be removed +to release it, therefore you will get some missing file errors when building. + +Much of this code is very close to the Descent 1 source code. Many people have +put effort into porting that code, so if you are interested in porting D2, you +should be able to take advantage of some of that work. + +A few good web sites to check out are: + +The D1X Project: +http://d1x.warpcore.org + +The Descent Network: +http://www.descent-network.com + diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 00000000..f71fe8a5 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,160 @@ +dnl aclocal.m4 generated automatically by aclocal 1.4 + +dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. + +# Like AC_CONFIG_HEADER, but automatically create stamp file. + +AC_DEFUN(AM_CONFIG_HEADER, +[AC_PREREQ([2.12]) +AC_CONFIG_HEADER([$1]) +dnl When config.status generates a header, we must update the stamp-h file. +dnl This file resides in the same directory as the config header +dnl that is generated. We must strip everything past the first ":", +dnl and everything past the last "/". +AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl +ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>, +<>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>, +<>; do + case " <<$>>CONFIG_HEADERS " in + *" <<$>>am_file "*<<)>> + echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx + ;; + esac + am_indx=`expr "<<$>>am_indx" + 1` +done<<>>dnl>>) +changequote([,]))]) + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + +dnl Usage: +dnl AM_INIT_AUTOMAKE(package,version, [no-define]) + +AC_DEFUN(AM_INIT_AUTOMAKE, +[AC_REQUIRE([AC_PROG_INSTALL]) +PACKAGE=[$1] +AC_SUBST(PACKAGE) +VERSION=[$2] +AC_SUBST(VERSION) +dnl test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi +ifelse([$3],, +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) +AC_REQUIRE([AM_SANITY_CHECK]) +AC_REQUIRE([AC_ARG_PROGRAM]) +dnl FIXME This is truly gross. +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_REQUIRE([AC_PROG_MAKE_SET])]) + +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN(AM_SANITY_CHECK, +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "[$]*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "[$]*" != "X $srcdir/configure conftestfile" \ + && test "[$]*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "[$]2" = conftestfile + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT(yes)]) + +dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) +dnl The program must properly implement --version. +AC_DEFUN(AM_MISSING_PROG, +[AC_MSG_CHECKING(for working $2) +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if ($2 --version) < /dev/null > /dev/null 2>&1; then + $1=$2 + AC_MSG_RESULT(found) +else + $1="$3/missing $2" + AC_MSG_RESULT(missing) +fi +AC_SUBST($1)]) + +# Add --enable-maintainer-mode option to configure. +# From Jim Meyering + +# serial 1 + +AC_DEFUN(AM_MAINTAINER_MODE, +[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode is disabled by default + AC_ARG_ENABLE(maintainer-mode, +[ --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + USE_MAINTAINER_MODE=$enableval, + USE_MAINTAINER_MODE=no) + AC_MSG_RESULT($USE_MAINTAINER_MODE) + AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST(MAINT)dnl +] +) + +# Define a conditional. + +AC_DEFUN(AM_CONDITIONAL, +[AC_SUBST($1_TRUE) +AC_SUBST($1_FALSE) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi]) + diff --git a/arch/Makefile.am b/arch/Makefile.am new file mode 100644 index 00000000..4f88f13a --- /dev/null +++ b/arch/Makefile.am @@ -0,0 +1,5 @@ +SUBDIRS = linux sdl +noinst_LIBRARIES = libarch.a + +libarch_a_SOURCES = +libarch_a_LIBADD = sdl/init.o sdl/timer.o linux/ipx_bsd.o linux/ipx_lin.o linux/ipx_udp.o linux/linuxnet.o linux/init.o linux/findfile.o diff --git a/arch/Makefile.in b/arch/Makefile.in new file mode 100644 index 00000000..7398866b --- /dev/null +++ b/arch/Makefile.in @@ -0,0 +1,339 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +CFLAGS = @CFLAGS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +NASM = @NASM@ +NASMFLAGS = @NASMFLAGS@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_LIBS = @SDL_LIBS@ +VERSION = @VERSION@ + +SUBDIRS = linux sdl +noinst_LIBRARIES = libarch.a + +libarch_a_SOURCES = +libarch_a_LIBADD = sdl/init.o sdl/timer.o linux/ipx_bsd.o linux/ipx_lin.o linux/ipx_udp.o linux/linuxnet.o linux/init.o linux/findfile.o +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../conf.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +libarch_a_DEPENDENCIES = sdl/init.o sdl/timer.o linux/ipx_bsd.o \ +linux/ipx_lin.o linux/ipx_udp.o linux/linuxnet.o linux/init.o \ +linux/findfile.o +libarch_a_OBJECTS = +AR = ar +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +SOURCES = $(libarch_a_SOURCES) +OBJECTS = $(libarch_a_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu arch/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +libarch.a: $(libarch_a_OBJECTS) $(libarch_a_DEPENDENCIES) + -rm -f libarch.a + $(AR) cru libarch.a $(libarch_a_OBJECTS) $(libarch_a_LIBADD) + $(RANLIB) libarch.a + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + +@SET_MAKE@ + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + test "$$subdir" = "." && dot_seen=yes; \ + done; \ + test "$$dot_seen" = "no" && rev=". $$rev"; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = arch + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu arch/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + fi; \ + done +info-am: +info: info-recursive +dvi-am: +dvi: dvi-recursive +check-am: all-am +check: check-recursive +installcheck-am: +installcheck: installcheck-recursive +install-exec-am: +install-exec: install-exec-recursive + +install-data-am: +install-data: install-data-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-recursive +uninstall-am: +uninstall: uninstall-recursive +all-am: Makefile $(LIBRARIES) +all-redirect: all-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: installdirs-recursive +installdirs-am: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ + mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-recursive + +clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \ + mostlyclean-am + +clean: clean-recursive + +distclean-am: distclean-noinstLIBRARIES distclean-compile \ + distclean-tags distclean-generic clean-am + +distclean: distclean-recursive + +maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-recursive + +.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile install-data-recursive \ +uninstall-data-recursive install-exec-recursive \ +uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \ +all-recursive check-recursive installcheck-recursive info-recursive \ +dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs-am \ +installdirs mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/arch/dos/allg_snd/allg_snd.c b/arch/dos/allg_snd/allg_snd.c new file mode 100644 index 00000000..e3ac1fd5 --- /dev/null +++ b/arch/dos/allg_snd/allg_snd.c @@ -0,0 +1,368 @@ +/* + * Allegro Sound library support routines + * Arne de Bruijn + */ + +#include +#include +#include +#include +#include "cfile.h" +#include "internal.h" +#include +#include "error.h" +#include "timer.h" +#include "d_io.h" + +extern int digi_timer_rate; +int retrace_count; +char allegro_error[80]=""; + +#define TIMERS_PER_SECOND 1193181L +#define MSEC_TO_TIMER(x) ((long)(x) * (TIMERS_PER_SECOND / 1000)) +#define MAX_TIMERS 16 +static struct { /* list of active callbacks */ + void ((*proc)()); + long speed; + long counter; +} my_int_queue[MAX_TIMERS]; +static int find_timer_slot(void (*proc)()) +{ + int x; + + for (x=0; x= MAX_TIMERS) + return -1; + + waiting_list[waiting_list_size].proc = proc; + waiting_list[waiting_list_size].speed = speed; + waiting_list_size++; + return 0; + } +#endif + x = find_timer_slot(proc); /* find the handler position */ + + if (x < 0) /* if not there, find free slot */ + x = find_timer_slot(NULL); + + if (x < 0) /* are there any free slots? */ + return -1; + + if (proc != my_int_queue[x].proc) { /* add new entry */ + my_int_queue[x].counter = speed; + my_int_queue[x].proc = proc; + } + else { /* alter speed of existing entry */ + my_int_queue[x].counter -= my_int_queue[x].speed; + my_int_queue[x].counter += speed; + } + + my_int_queue[x].speed = speed; + + return 0; +} +int install_int(void (*proc)(), long speed) +{ + return install_int_ex(proc, MSEC_TO_TIMER(speed)); +} +void remove_int(void (*proc)()) +{ + int x = find_timer_slot(proc); + + if (x >= 0) { + my_int_queue[x].proc = NULL; + my_int_queue[x].speed = 0; + my_int_queue[x].counter = 0; + } +} + +void allg_snd_timer() { + int x; + for (x=0; x 0) || (shift == 0)) { + *(--p) = (delta & 127) | shift; + delta >>= 7; + shift = 128; + } + return data; +} + +/* + * read a MIDI type variabele length number + */ +static unsigned char *read_var(unsigned char *data, unsigned char *dataend, + unsigned long *value) { + unsigned long v = 0; + + while ((data < dataend) && (*data & 0x80)) + v = (v << 7) + (*(data++) & 0x7f); + if (data == dataend) + return NULL; + v = (v << 7) + *(data++); + if (value) *value = v; + return data; +} + +static int trans_data(unsigned char *data, int size) { + static int cmdlen[7]={3,3,3,3,2,2,3}; + unsigned char *dataend = data + size; + unsigned long v; + + while (data < dataend) { + if (!(data = conv_delta(data, dataend))) + return 1; + + if (data == dataend) + return 1; /* need something after delta */ + + if (*data < 0x80) + return 1; /* invalid command */ + if (*data < 0xf0) { + data += cmdlen[((*data) >> 4) - 8]; + } else if (*data == 0xff) { + data += 2; + if (data >= dataend) + return 1; + if (!(data = read_var(data, dataend, &v))) + return 1; + data += v; + } else /* sysex -> error */ + return 1; + } + return (data != dataend); /* processed as many as received? */ +} + +/* + * load HMP file into Allegro MIDI structure by translating the deltas + * and adding tempo information + */ +MIDI *load_hmp(char *filename) { + static unsigned char hmp_tempo[7] = + {0x00, 0xff, 0x51, 0x03, 0x0f, 0x42, 0x40}; + int c; + char buf[256]; + long data; + CFILE *fp; + MIDI *midi; + int num_tracks; + unsigned char *p; + + // try .mid first + removeext(filename, buf); + strcat(buf, ".mid"); + if ((midi = load_midi(buf))) + return midi; + if (!(fp = cfopen(filename, "rb"))) + return NULL; + + midi = malloc(sizeof(MIDI)); /* get some memory */ + if (!midi) { + cfclose(fp); + return NULL; + } + + for (c=0; ctrack[c].data = NULL; + midi->track[c].len = 0; + } + + if ((cfread(buf, 1, 8, fp) != 8) || (memcmp(buf, "HMIMIDIP", 8))) + goto err; + + if (cfseek(fp, 0x30, SEEK_SET)) + goto err; + + if (cfread(&num_tracks, 4, 1, fp) != 1) + goto err; + + if ((num_tracks < 1) || (num_tracks > MIDI_TRACKS)) + goto err; + + midi->divisions = 120; + + if (cfseek(fp, 0x308, SEEK_SET)) + goto err; + + for (c=0; ctrack[c].len = data; + + if (!(p = midi->track[c].data = malloc(data))) /* allocate memory */ + goto err; + + if (c == 0) { /* track 0: add tempo */ + memcpy(p, hmp_tempo, sizeof(hmp_tempo)); + p += sizeof(hmp_tempo); + data -= sizeof(hmp_tempo); + } + /* finally, read track data */ + if ((cfseek(fp, 4, SEEK_CUR)) || (cfread(p, data, 1, fp) != 1)) + goto err; + + if (trans_data(p, data)) /* translate deltas hmp -> midi */ + goto err; + } + + cfclose(fp); + lock_midi(midi); + return midi; + +err: + cfclose(fp); + destroy_midi(midi); + return NULL; +} + +char *pack_fgets(char *p, int max, PACKFILE *f) { + int c; + + if (pack_feof(f)) { + p[0] = 0; + return NULL; + } + + for (c=0; c=p) && (*(p-1)!='/') && (*(p-1)!='\\') + && (*(p-1)!=':')) { *(p++)='/'; *p=0;} +} + +void allg_snd_init() { + if (LOCK_VARIABLE(my_int_queue) || + LOCK_VARIABLE(digi_timer_rate) || + LOCK_VARIABLE(retrace_count) || + LOCK_FUNCTION(allg_snd_timer)) + Error("Error locking sound timer"); + timer_set_function(allg_snd_timer); +} + +// return true if using the digmid driver +int allegro_using_digmid() { + return get_config_int("sound", "midi_card", MIDI_AUTODETECT) == MIDI_DIGMID; +} diff --git a/arch/dos/allg_snd/internal.h b/arch/dos/allg_snd/internal.h new file mode 100644 index 00000000..3e7d46cf --- /dev/null +++ b/arch/dos/allg_snd/internal.h @@ -0,0 +1,529 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * By Shawn Hargreaves, + * 1 Salisbury Road, + * Market Drayton, + * Shropshire, + * England, TF9 1AJ. + * + * Some definitions for internal use by the library code. + * This should not be included by user programs. + * + * See readme.txt for copyright information. + */ + + +#ifndef INTERNAL_H +#define INTERNAL_H + +#include "allegro.h" + +#ifdef DJGPP +#include "interndj.h" +#else +#include "internli.h" +#endif +#include +#include + +#define rest delay +#define PACKFILE FILE +#define pack_fopen fopen +#define pack_fputs fputs +#define pack_fread(x,y,z) fread(x,1,y,z) +#define pack_fclose fclose +#define pack_getc(f) fgetc(f) +#define pack_igetw(f) (fgetc(f) | (fgetc(f) << 8)) +#define pack_igetl(f) (pack_igetw(f) | (pack_igetw(f) << 16)) +#define pack_mgetw(f) ((fgetc(f) << 8) | fgetc(f)) +#define pack_mgetl(f) ((pack_mgetw(f) << 16) | pack_mgetw(f)) +#define pack_feof(f) feof(f) +#define file_exists(n,x,z) (file_size(n)!=-1) +#define F_READ "rb" +#define F_WRITE "wb" + +char *pack_fgets(char *p, int max, PACKFILE *f); +long file_size(const char *n); +char *get_filename(const char *s); +char *get_extension(const char *s); + +void put_backslash(char *n); + + +/* flag for how many times we have been initialised */ +extern int _allegro_count; + + +/* some Allegro functions need a block of scratch memory */ +extern void *_scratch_mem; +extern int _scratch_mem_size; + +__INLINE__ void _grow_scratch_mem(int size) +{ + if (size > _scratch_mem_size) { + size = (size+1023) & 0xFFFFFC00; + _scratch_mem = realloc(_scratch_mem, size); + _scratch_mem_size = size; + } +} + + +/* list of functions to call at program cleanup */ +void _add_exit_func(void (*func)()); +void _remove_exit_func(void (*func)()); + + +/* various bits of mouse stuff */ +void _set_mouse_range(); +extern BITMAP *_mouse_screen; + + +/* various bits of timer stuff */ +extern int _timer_use_retrace; +extern volatile int _retrace_hpp_value; + + +/* asm joystick polling routine */ +int _poll_joystick(int *x, int *y, int *x2, int *y2, int poll_mask); + + +/* caches and tables for svga bank switching */ +extern int _last_bank_1, _last_bank_2; +extern int *_gfx_bank; + + +/* bank switching routines */ +void _stub_bank_switch(); +void _stub_bank_switch_end(); + + +/* stuff for setting up bitmaps */ +typedef struct _GFX_MODE_INFO +{ + int w, h; + int bpp; + int bios_num; + int bios_int; + int (*setter)(int w, int h, int bpp); +} _GFX_MODE_INFO; + +void _check_gfx_virginity(); +BITMAP *_gfx_mode_set_helper(int w, int h, int v_w, int v_h, int color_depth, GFX_DRIVER *driver, int (*detect)(), _GFX_MODE_INFO *mode_list, void (*set_width)(int w)); +BITMAP *_make_bitmap(int w, int h, unsigned long addr, GFX_DRIVER *driver, int color_depth, int bpl); +void _sort_out_virtual_width(int *width, GFX_DRIVER *driver); + +GFX_VTABLE *_get_vtable(int color_depth); + +extern int _sub_bitmap_id_count; + +#define BYTES_PER_PIXEL(bpp) (((int)(bpp) + 7) / 8) + +int _color_load_depth(int depth); + +BITMAP *_fixup_loaded_bitmap(BITMAP *bmp, PALETTE pal, int bpp); + + +/* truecolor pixel blending information */ +extern BLENDER_MAP *_blender_map15; +extern BLENDER_MAP *_blender_map16; +extern BLENDER_MAP *_blender_map24; + +extern int _blender_col_15; +extern int _blender_col_16; +extern int _blender_col_24; +extern int _blender_col_32; + +extern int _blender_alpha; + + +/* VGA register access routines */ +void _vga_vsync(); +void _vga_set_pallete_range(PALLETE p, int from, int to, int vsync); + +extern int _crtc; + + +/* _read_vga_register: + * Reads the contents of a VGA register. + */ +__INLINE__ int _read_vga_register(int port, int index) +{ + if (port==0x3C0) + inportb(_crtc+6); + + outportb(port, index); + return inportb(port+1); +} + + +/* _write_vga_register: + * Writes a byte to a VGA register. + */ +__INLINE__ void _write_vga_register(int port, int index, int v) +{ + if (port==0x3C0) { + inportb(_crtc+6); + outportb(port, index); + outportb(port, v); + } + else { + outportb(port, index); + outportb(port+1, v); + } +} + + +/* _alter_vga_register: + * Alters specific bits of a VGA register. + */ +__INLINE__ void _alter_vga_register(int port, int index, int mask, int v) +{ + int temp; + temp = _read_vga_register(port, index); + temp &= (~mask); + temp |= (v & mask); + _write_vga_register(port, index, temp); +} + + +/* _vsync_out_h: + * Waits until the VGA is not in either a vertical or horizontal retrace. + */ +__INLINE__ void _vsync_out_h() +{ + do { + } while (inportb(0x3DA) & 1); +} + + +/* _vsync_out_v: + * Waits until the VGA is not in a vertical retrace. + */ +__INLINE__ void _vsync_out_v() +{ + do { + } while (inportb(0x3DA) & 8); +} + + +/* _vsync_in: + * Waits until the VGA is in the vertical retrace period. + */ +__INLINE__ void _vsync_in() +{ + if (_timer_use_retrace) { + int t = retrace_count; + + do { + } while (t == retrace_count); + } + else { + do { + } while (!(inportb(0x3DA) & 8)); + } +} + + +/* _write_hpp: + * Writes to the VGA pelpan register. + */ +__INLINE__ void _write_hpp(int value) +{ + if (_timer_use_retrace) { + _retrace_hpp_value = value; + + do { + } while (_retrace_hpp_value == value); + } + else { + do { + } while (!(inportb(0x3DA) & 8)); + + _write_vga_register(0x3C0, 0x33, value); + } +} + + +int _test_vga_register(int port, int index, int mask); +int _test_register(int port, int mask); +void _set_vga_virtual_width(int old_width, int new_width); + + +/* current drawing mode */ +extern int _drawing_mode; +extern BITMAP *_drawing_pattern; +extern int _drawing_x_anchor; +extern int _drawing_y_anchor; +extern unsigned int _drawing_x_mask; +extern unsigned int _drawing_y_mask; + + +/* graphics drawing routines */ +void _normal_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color); +void _normal_rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color); + +int _linear_getpixel8(struct BITMAP *bmp, int x, int y); +void _linear_putpixel8(struct BITMAP *bmp, int x, int y, int color); +void _linear_vline8(struct BITMAP *bmp, int x, int y1, int y2, int color); +void _linear_hline8(struct BITMAP *bmp, int x1, int y, int x2, int color); +void _linear_draw_sprite8(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_sprite_v_flip8(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_sprite_h_flip8(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_sprite_vh_flip8(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_trans_sprite8(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_lit_sprite8(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); +void _linear_draw_rle_sprite8(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); +void _linear_draw_trans_rle_sprite8(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); +void _linear_draw_lit_rle_sprite8(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color); +void _linear_draw_character8(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); +void _linear_textout_fixed8(struct BITMAP *bmp, void *f, int h, unsigned char *str, int x, int y, int color); +void _linear_blit8(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _linear_blit_backward8(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _linear_masked_blit8(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _linear_clear_to_color8(struct BITMAP *bitmap, int color); + +#ifdef ALLEGRO_COLOR16 + +void _linear_putpixel15(struct BITMAP *bmp, int x, int y, int color); +void _linear_vline15(struct BITMAP *bmp, int x, int y1, int y2, int color); +void _linear_hline15(struct BITMAP *bmp, int x1, int y, int x2, int color); +void _linear_draw_trans_sprite15(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_lit_sprite15(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); +void _linear_draw_rle_sprite15(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); +void _linear_draw_trans_rle_sprite15(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); +void _linear_draw_lit_rle_sprite15(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color); + +int _linear_getpixel16(struct BITMAP *bmp, int x, int y); +void _linear_putpixel16(struct BITMAP *bmp, int x, int y, int color); +void _linear_vline16(struct BITMAP *bmp, int x, int y1, int y2, int color); +void _linear_hline16(struct BITMAP *bmp, int x1, int y, int x2, int color); +void _linear_draw_sprite16(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_256_sprite16(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_sprite_v_flip16(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_sprite_h_flip16(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_sprite_vh_flip16(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_trans_sprite16(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_lit_sprite16(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); +void _linear_draw_rle_sprite16(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); +void _linear_draw_trans_rle_sprite16(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); +void _linear_draw_lit_rle_sprite16(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color); +void _linear_draw_character16(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); +void _linear_textout_fixed16(struct BITMAP *bmp, void *f, int h, unsigned char *str, int x, int y, int color); +void _linear_blit16(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _linear_blit_backward16(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _linear_masked_blit16(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _linear_clear_to_color16(struct BITMAP *bitmap, int color); + +#endif + +#ifdef ALLEGRO_COLOR24 + +int _linear_getpixel24(struct BITMAP *bmp, int x, int y); +void _linear_putpixel24(struct BITMAP *bmp, int x, int y, int color); +void _linear_vline24(struct BITMAP *bmp, int x, int y1, int y2, int color); +void _linear_hline24(struct BITMAP *bmp, int x1, int y, int x2, int color); +void _linear_draw_sprite24(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_256_sprite24(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_sprite_v_flip24(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_sprite_h_flip24(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_sprite_vh_flip24(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_trans_sprite24(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_lit_sprite24(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); +void _linear_draw_rle_sprite24(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); +void _linear_draw_trans_rle_sprite24(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); +void _linear_draw_lit_rle_sprite24(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color); +void _linear_draw_character24(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); +void _linear_textout_fixed24(struct BITMAP *bmp, void *f, int h, unsigned char *str, int x, int y, int color); +void _linear_blit24(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _linear_blit_backward24(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _linear_masked_blit24(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _linear_clear_to_color24(struct BITMAP *bitmap, int color); + +#endif + +#ifdef ALLEGRO_COLOR32 + +int _linear_getpixel32(struct BITMAP *bmp, int x, int y); +void _linear_putpixel32(struct BITMAP *bmp, int x, int y, int color); +void _linear_vline32(struct BITMAP *bmp, int x, int y1, int y2, int color); +void _linear_hline32(struct BITMAP *bmp, int x1, int y, int x2, int color); +void _linear_draw_sprite32(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_256_sprite32(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_sprite_v_flip32(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_sprite_h_flip32(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_sprite_vh_flip32(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_trans_sprite32(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _linear_draw_lit_sprite32(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); +void _linear_draw_rle_sprite32(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); +void _linear_draw_trans_rle_sprite32(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); +void _linear_draw_lit_rle_sprite32(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color); +void _linear_draw_character32(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); +void _linear_textout_fixed32(struct BITMAP *bmp, void *f, int h, unsigned char *str, int x, int y, int color); +void _linear_blit32(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _linear_blit_backward32(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _linear_masked_blit32(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _linear_clear_to_color32(struct BITMAP *bitmap, int color); + +#endif + +int _x_getpixel(struct BITMAP *bmp, int x, int y); +void _x_putpixel(struct BITMAP *bmp, int x, int y, int color); +void _x_vline(struct BITMAP *bmp, int x, int y1, int y2, int color); +void _x_hline(struct BITMAP *bmp, int x1, int y, int x2, int color); +void _x_draw_sprite(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _x_draw_sprite_v_flip(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _x_draw_sprite_h_flip(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _x_draw_sprite_vh_flip(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _x_draw_trans_sprite(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); +void _x_draw_lit_sprite(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); +void _x_draw_rle_sprite(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); +void _x_draw_trans_rle_sprite(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); +void _x_draw_lit_rle_sprite(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color); +void _x_draw_character(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); +void _x_textout_fixed(struct BITMAP *bmp, void *f, int h, unsigned char *str, int x, int y, int color); +void _x_blit_from_memory(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _x_blit_to_memory(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _x_blit(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _x_blit_forward(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _x_blit_backward(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _x_masked_blit(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void _x_clear_to_color(struct BITMAP *bitmap, int color); + + +/* asm helper for stretch_blit() */ +void _do_stretch(BITMAP *source, BITMAP *dest, void *drawer, int sx, fixed sy, fixed syd, int dx, int dy, int dh, int color_depth); + + +/* information for polygon scanline fillers */ +typedef struct POLYGON_SEGMENT +{ + fixed u, v, du, dv; /* fixed point u/v coordinates */ + fixed c, dc; /* single color gouraud shade values */ + fixed r, g, b, dr, dg, db; /* RGB gouraud shade values */ + float z, dz; /* polygon depth (1/z) */ + float fu, fv, dfu, dfv; /* floating point u/v coordinates */ + unsigned char *texture; /* the texture map */ + int umask, vmask, vshift; /* texture map size information */ + int seg; /* destination bitmap selector */ +} POLYGON_SEGMENT; + + +/* polygon scanline filler functions */ +void _poly_scanline_flat(unsigned long addr, int w, POLYGON_SEGMENT *info); +void _poly_scanline_gcol(unsigned long addr, int w, POLYGON_SEGMENT *info); +void _poly_scanline_grgb(unsigned long addr, int w, POLYGON_SEGMENT *info); +void _poly_scanline_atex(unsigned long addr, int w, POLYGON_SEGMENT *info); +void _poly_scanline_ptex(unsigned long addr, int w, POLYGON_SEGMENT *info); +void _poly_scanline_atex_mask(unsigned long addr, int w, POLYGON_SEGMENT *info); +void _poly_scanline_ptex_mask(unsigned long addr, int w, POLYGON_SEGMENT *info); +void _poly_scanline_atex_lit(unsigned long addr, int w, POLYGON_SEGMENT *info); +void _poly_scanline_ptex_lit(unsigned long addr, int w, POLYGON_SEGMENT *info); + + +/* sound lib stuff */ +extern int _digi_volume; +extern int _midi_volume; +extern int _flip_pan; + +extern int (*_midi_init)(); +extern void (*_midi_exit)(); + +int _midi_allocate_voice(int min, int max); + +extern volatile long _midi_tick; + +int _digmid_find_patches(char *dir, char *file); + +#define VIRTUAL_VOICES 256 + + +typedef struct /* a virtual (as seen by the user) soundcard voice */ +{ + SAMPLE *sample; /* which sample are we playing? (NULL = free) */ + int num; /* physical voice number (-1 = been killed off) */ + int autokill; /* set to free the voice when the sample finishes */ + long time; /* when we were started (for voice allocation) */ + int priority; /* how important are we? */ +} VOICE; + +extern VOICE _voice[VIRTUAL_VOICES]; + + +typedef struct /* a physical (as used by hardware) soundcard voice */ +{ + int num; /* the virtual voice currently using me (-1 = free) */ + int playmode; /* are we looping? */ + int vol; /* current volume (fixed point .12) */ + int dvol; /* volume delta, for ramping */ + int target_vol; /* target volume, for ramping */ + int pan; /* current pan (fixed point .12) */ + int dpan; /* pan delta, for sweeps */ + int target_pan; /* target pan, for sweeps */ + int freq; /* current frequency (fixed point .12) */ + int dfreq; /* frequency delta, for sweeps */ + int target_freq; /* target frequency, for sweeps */ +} PHYS_VOICE; + +extern PHYS_VOICE _phys_voice[DIGI_VOICES]; + + +#define MIXER_DEF_SFX 8 +#define MIXER_MAX_SFX 32 + +int _mixer_init(int bufsize, int freq, int stereo, int is16bit, int *voices); +void _mixer_exit(); +void _mix_some_samples(unsigned long buf, unsigned short seg, int issigned); + +void _mixer_init_voice(int voice, SAMPLE *sample); +void _mixer_release_voice(int voice); +void _mixer_start_voice(int voice); +void _mixer_stop_voice(int voice); +void _mixer_loop_voice(int voice, int loopmode); +int _mixer_get_position(int voice); +void _mixer_set_position(int voice, int position); +int _mixer_get_volume(int voice); +void _mixer_set_volume(int voice, int volume); +void _mixer_ramp_volume(int voice, int time, int endvol); +void _mixer_stop_volume_ramp(int voice); +int _mixer_get_frequency(int voice); +void _mixer_set_frequency(int voice, int frequency); +void _mixer_sweep_frequency(int voice, int time, int endfreq); +void _mixer_stop_frequency_sweep(int voice); +int _mixer_get_pan(int voice); +void _mixer_set_pan(int voice, int pan); +void _mixer_sweep_pan(int voice, int time, int endpan); +void _mixer_stop_pan_sweep(int voice); +void _mixer_set_echo(int voice, int strength, int delay); +void _mixer_set_tremolo(int voice, int rate, int depth); +void _mixer_set_vibrato(int voice, int rate, int depth); + +/* dummy functions for the NoSound drivers */ +int _dummy_detect(); +int _dummy_init(int voices); +void _dummy_exit(); +int _dummy_mixer_volume(int volume); +void _dummy_init_voice(int voice, SAMPLE *sample); +void _dummy_noop1(int p); +void _dummy_noop2(int p1, int p2); +void _dummy_noop3(int p1, int p2, int p3); +int _dummy_get_position(int voice); +int _dummy_get(int voice); +void _dummy_raw_midi(unsigned char data); +int _dummy_load_patches(char *patches, char *drums); +void _dummy_adjust_patches(char *patches, char *drums); +void _dummy_key_on(int inst, int note, int bend, int vol, int pan); + + +/* from djgpp's libc, needed to find which directory we were run from */ +extern int __crt0_argc; +extern char **__crt0_argv; + + +#endif /* ifndef INTERNAL_H */ diff --git a/arch/dos/allg_snd/sound/allegro.h b/arch/dos/allg_snd/sound/allegro.h new file mode 100644 index 00000000..efe5f7ec --- /dev/null +++ b/arch/dos/allg_snd/sound/allegro.h @@ -0,0 +1,2716 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * By Shawn Hargreaves, + * 1 Salisbury Road, + * Market Drayton, + * Shropshire, + * England, TF9 1AJ. + * + * Main header file for the Allegro library. + * This should be included by everyone and everything. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_H +#define ALLEGRO_H + +#ifdef LINUX +#error Linux version not finished. Want to help? +#endif + +#ifndef DJGPP +#error Allegro can only be used with djgpp +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define ALLEGRO_VERSION 3 +#define ALLEGRO_SUB_VERSION 0 +#define ALLEGRO_VERSION_STR "3.0" +#define ALLEGRO_DATE_STR "1997" + +/* remove these if you only want 256 color graphics support */ +#define ALLEGRO_COLOR16 +#define ALLEGRO_COLOR24 +#define ALLEGRO_COLOR32 + + + +/*******************************************/ +/************ Some global stuff ************/ +/*******************************************/ + +#include +#include +#include + +#ifdef DJGPP +#include +#include +#endif + +#ifndef TRUE +#define TRUE -1 +#define FALSE 0 +#endif + +#ifndef MIN +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#define MAX(x,y) (((x) > (y)) ? (x) : (y)) +#define MID(x,y,z) MAX((x), MIN((y), (z))) +#endif + +#ifndef ABS +#define ABS(x) (((x) >= 0) ? (x) : (-(x))) +#endif + +#ifndef SGN +#define SGN(x) (((x) >= 0) ? 1 : -1) +#endif + +#ifndef __INLINE__ +#define __INLINE__ extern inline +#endif + +typedef long fixed; + +struct RGB; +struct BITMAP; +struct RLE_SPRITE; +struct SAMPLE; +struct MIDI; + +extern char allegro_id[]; +extern char allegro_error[]; + +#define OSTYPE_UNKNOWN 0 +#define OSTYPE_WIN3 1 +#define OSTYPE_WIN95 2 +#define OSTYPE_WINNT 3 +#define OSTYPE_OS2 4 +#define OSTYPE_WARP 5 +#define OSTYPE_DOSEMU 6 +#define OSTYPE_OPENDOS 7 + +extern int os_type; + +extern int windows_version, windows_sub_version; + +int allegro_init(); +void allegro_exit(); + +void check_cpu(); + +extern char cpu_vendor[]; +extern int cpu_family; +extern int cpu_model; +extern int cpu_fpu; +extern int cpu_mmx; +extern int cpu_cpuid; + +void lock_bitmap(struct BITMAP *bmp); +void lock_sample(struct SAMPLE *spl); +void lock_midi(struct MIDI *midi); + +#ifdef DJGPP + +/* for djgpp */ +#define END_OF_FUNCTION(x) void x##_end() { } +#define LOCK_VARIABLE(x) _go32_dpmi_lock_data((void *)&x, sizeof(x)) +#define LOCK_FUNCTION(x) _go32_dpmi_lock_code(x, (long)x##_end - (long)x) + +#else + +/* for linux */ +#define END_OF_FUNCTION(x) +#define LOCK_VARIABLE(x) +#define LOCK_FUNCTION(x) + +#endif + + + +/************************************************/ +/************ Configuration routines ************/ +/************************************************/ + +void set_config_file(char *filename); +void set_config_data(char *data, int length); +void override_config_file(char *filename); +void override_config_data(char *data, int length); + +void push_config_state(); +void pop_config_state(); + +char *get_config_string(char *section, char *name, char *def); +int get_config_int(char *section, char *name, int def); +int get_config_hex(char *section, char *name, int def); +float get_config_float(char *section, char *name, float def); +char **get_config_argv(char *section, char *name, int *argc); + +void set_config_string(char *section, char *name, char *val); +void set_config_int(char *section, char *name, int val); +void set_config_hex(char *section, char *name, int val); +void set_config_float(char *section, char *name, float val); + + + +/****************************************/ +/************ Mouse routines ************/ +/****************************************/ + +#if !defined alleg_mouse_unused + +int install_mouse(); +void remove_mouse(); + +extern volatile int mouse_x; +extern volatile int mouse_y; +extern volatile int mouse_b; +extern volatile int mouse_pos; + +extern int freeze_mouse_flag; + +#define MOUSE_FLAG_MOVE 1 +#define MOUSE_FLAG_LEFT_DOWN 2 +#define MOUSE_FLAG_LEFT_UP 4 +#define MOUSE_FLAG_RIGHT_DOWN 8 +#define MOUSE_FLAG_RIGHT_UP 16 +#define MOUSE_FLAG_MIDDLE_DOWN 32 +#define MOUSE_FLAG_MIDDLE_UP 64 + +extern void (*mouse_callback)(int flags); + +void show_mouse(struct BITMAP *bmp); +void position_mouse(int x, int y); +void set_mouse_range(int x1, int y1, int x2, int y2); +void set_mouse_speed(int xspeed, int yspeed); +void set_mouse_sprite(struct BITMAP *sprite); +void set_mouse_sprite_focus(int x, int y); +void get_mouse_mickeys(int *mickeyx, int *mickeyy); + +#endif + + + +/****************************************/ +/************ Timer routines ************/ +/****************************************/ + +#if !defined alleg_timer_unused + +#define TIMERS_PER_SECOND 1193181L +#define SECS_TO_TIMER(x) ((long)(x) * TIMERS_PER_SECOND) +#define MSEC_TO_TIMER(x) ((long)(x) * (TIMERS_PER_SECOND / 1000)) +#define BPS_TO_TIMER(x) (TIMERS_PER_SECOND / (long)(x)) +#define BPM_TO_TIMER(x) ((60 * TIMERS_PER_SECOND) / (long)(x)) + +int install_timer(); +void remove_timer(); + +int install_int_ex(void (*proc)(), long speed); +int install_int(void (*proc)(), long speed); +void remove_int(void (*proc)()); + +extern int i_love_bill; + +extern volatile int retrace_count; +extern void (*retrace_proc)(); + +void timer_simulate_retrace(int enable); + +void rest(long time); +void rest_callback(long time, void (*callback)()); + +#endif + + + +/*******************************************/ +/************ Keyboard routines ************/ +/*******************************************/ + +#if !defined alleg_keyboard_unused + +int install_keyboard(); +void remove_keyboard(); + +extern int (*keyboard_callback)(int key); + +void install_keyboard_hooks(int (*keypressed)(), int (*readkey)()); + +extern volatile char key[128]; +extern volatile int key_shifts; + +extern int three_finger_flag; +extern int key_led_flag; + +int keypressed(); +int readkey(); +void simulate_keypress(int key); +void clear_keybuf(); +void set_leds(int leds); + +extern unsigned char key_ascii_table[128]; +extern unsigned char key_capslock_table[128]; +extern unsigned char key_shift_table[128]; +extern unsigned char key_control_table[128]; +extern unsigned char key_altgr_table[128]; +extern unsigned char key_accent1_lower_table[128]; +extern unsigned char key_accent1_upper_table[128]; +extern unsigned char key_accent1_shift_lower_table[128]; +extern unsigned char key_accent1_shift_upper_table[128]; +extern unsigned char key_accent2_lower_table[128]; +extern unsigned char key_accent2_upper_table[128]; +extern unsigned char key_accent2_shift_lower_table[128]; +extern unsigned char key_accent2_shift_upper_table[128]; +extern unsigned char key_numlock_table[128]; +extern unsigned char key_extended_table[128]; +extern unsigned short key_special_table[128]; + +#define SCANCODE_TO_KEY(c) (((c)<<8) + (int)key_ascii_table[c]) +#define SCANCODE_TO_CAPS(c) (((c)<<8) + (int)key_capslock_table[c]) +#define SCANCODE_TO_SHIFT(c) (((c)<<8) + (int)key_shift_table[c]) +#define SCANCODE_TO_CONTROL(c) (((c)<<8) + (int)key_control_table[c]) +#define SCANCODE_TO_ALTGR(c) (((c)<<8) + (int)key_altgr_table[c]) +#define SCANCODE_TO_ALT(c) ((c)<<8) + +#define KB_SHIFT_FLAG 0x0001 +#define KB_CTRL_FLAG 0x0002 +#define KB_ALT_FLAG 0x0004 +#define KB_LWIN_FLAG 0x0008 +#define KB_RWIN_FLAG 0x0010 +#define KB_MENU_FLAG 0x0020 +#define KB_SCROLOCK_FLAG 0x0100 +#define KB_NUMLOCK_FLAG 0x0200 +#define KB_CAPSLOCK_FLAG 0x0400 +#define KB_INALTSEQ_FLAG 0x0800 +#define KB_ACCENT1_FLAG 0x1000 +#define KB_ACCENT1_S_FLAG 0x2000 +#define KB_ACCENT2_FLAG 0x4000 +#define KB_ACCENT2_S_FLAG 0x8000 + +#define KB_NORMAL 1 +#define KB_EXTENDED 2 + +#define KEY_ESC 1 /* keyboard scan codes */ +#define KEY_1 2 +#define KEY_2 3 +#define KEY_3 4 +#define KEY_4 5 +#define KEY_5 6 +#define KEY_6 7 +#define KEY_7 8 +#define KEY_8 9 +#define KEY_9 10 +#define KEY_0 11 +#define KEY_MINUS 12 +#define KEY_EQUALS 13 +#define KEY_BACKSPACE 14 +#define KEY_TAB 15 +#define KEY_Q 16 +#define KEY_W 17 +#define KEY_E 18 +#define KEY_R 19 +#define KEY_T 20 +#define KEY_Y 21 +#define KEY_U 22 +#define KEY_I 23 +#define KEY_O 24 +#define KEY_P 25 +#define KEY_OPENBRACE 26 +#define KEY_CLOSEBRACE 27 +#define KEY_ENTER 28 +#define KEY_CONTROL 29 +#define KEY_LCONTROL 29 +#define KEY_A 30 +#define KEY_S 31 +#define KEY_D 32 +#define KEY_F 33 +#define KEY_G 34 +#define KEY_H 35 +#define KEY_J 36 +#define KEY_K 37 +#define KEY_L 38 +#define KEY_COLON 39 +#define KEY_QUOTE 40 +#define KEY_TILDE 41 +#define KEY_LSHIFT 42 +#define KEY_BACKSLASH 43 +#define KEY_Z 44 +#define KEY_X 45 +#define KEY_C 46 +#define KEY_V 47 +#define KEY_B 48 +#define KEY_N 49 +#define KEY_M 50 +#define KEY_COMMA 51 +#define KEY_STOP 52 +#define KEY_SLASH 53 +#define KEY_RSHIFT 54 +#define KEY_ASTERISK 55 +#define KEY_ALT 56 +#define KEY_SPACE 57 +#define KEY_CAPSLOCK 58 +#define KEY_F1 59 +#define KEY_F2 60 +#define KEY_F3 61 +#define KEY_F4 62 +#define KEY_F5 63 +#define KEY_F6 64 +#define KEY_F7 65 +#define KEY_F8 66 +#define KEY_F9 67 +#define KEY_F10 68 +#define KEY_NUMLOCK 69 +#define KEY_SCRLOCK 70 +#define KEY_HOME 71 +#define KEY_UP 72 +#define KEY_PGUP 73 +#define KEY_MINUS_PAD 74 +#define KEY_LEFT 75 +#define KEY_5_PAD 76 +#define KEY_RIGHT 77 +#define KEY_PLUS_PAD 78 +#define KEY_END 79 +#define KEY_DOWN 80 +#define KEY_PGDN 81 +#define KEY_INSERT 82 +#define KEY_DEL 83 +#define KEY_PRTSCR 84 +#define KEY_F11 87 +#define KEY_F12 88 +#define KEY_LWIN 91 +#define KEY_RWIN 92 +#define KEY_MENU 93 +#define KEY_PAD 100 +#define KEY_RCONTROL 120 +#define KEY_ALTGR 121 +#define KEY_SLASH2 122 +#define KEY_PAUSE 123 + +#endif + + + +/*******************************************/ +/************ Joystick routines ************/ +/*******************************************/ + +#if !defined alleg_joystick_unused + +extern int joy_type; + +/* values for joy_type */ +#define JOY_TYPE_STANDARD 0 +#define JOY_TYPE_FSPRO 1 +#define JOY_TYPE_4BUTTON 2 +#define JOY_TYPE_6BUTTON 3 +#define JOY_TYPE_2PADS 4 +#define JOY_TYPE_WINGEX 5 + +/* values for joy_hat */ +#define JOY_HAT_CENTRE 0 +#define JOY_HAT_LEFT 1 +#define JOY_HAT_DOWN 2 +#define JOY_HAT_RIGHT 3 +#define JOY_HAT_UP 4 + +/* aliases for FSPro buttons */ +#define joy_FSPRO_trigger joy_b1 +#define joy_FSPRO_butleft joy_b2 +#define joy_FSPRO_butright joy_b3 +#define joy_FSPRO_butmiddle joy_b4 + +/* aliases for Wingman Extreme buttons */ +#define joy_WINGEX_trigger joy_b1 +#define joy_WINGEX_buttop joy_b2 +#define joy_WINGEX_butthumb joy_b3 +#define joy_WINGEX_butmiddle joy_b4 + +/* some Yankified aliases ;) */ +#define JOY_HAT_CENTER JOY_HAT_CENTRE + +/* joystick status variables */ +extern int joy_x, joy_y; +extern int joy_left, joy_right, joy_up, joy_down; +extern int joy_b1, joy_b2, joy_b3, joy_b4, joy_b5, joy_b6; +extern int joy_hat; +extern int joy_throttle; +extern int joy2_x, joy2_y; +extern int joy2_left, joy2_right, joy2_up, joy2_down; +extern int joy2_b1, joy2_b2; + +int initialise_joystick(); +int calibrate_joystick_tl(); +int calibrate_joystick_br(); +int calibrate_joystick_throttle_min(); +int calibrate_joystick_throttle_max(); +int calibrate_joystick_hat(int direction); + +void poll_joystick(); + +int save_joystick_data(char *filename); +int load_joystick_data(char *filename); + +#endif + + + +/************************************************/ +/************ Screen/bitmap routines ************/ +/************************************************/ + +#if !defined alleg_gfx_driver_unused || \ + !defined alleg_graphics_unused || \ + !defined alleg_vidmem_unused || \ + !defined alleg_palette_unused + +#define GFX_TEXT -1 +#define GFX_AUTODETECT 0 +#define GFX_VGA 1 +#define GFX_MODEX 2 + +#ifdef DJGPP + +/* for djgpp */ +#define GFX_VESA1 3 +#define GFX_VESA2B 4 +#define GFX_VESA2L 5 +#define GFX_VBEAF 6 +#define GFX_XTENDED 7 +#define GFX_ATI 8 +#define GFX_MACH64 9 +#define GFX_CIRRUS64 10 +#define GFX_CIRRUS54 11 +#define GFX_PARADISE 12 +#define GFX_S3 13 +#define GFX_TRIDENT 14 +#define GFX_ET3000 15 +#define GFX_ET4000 16 +#define GFX_VIDEO7 17 + +#else + +/* for linux */ +#define GFX_SVGALIB 3 + +#endif + + +typedef struct GFX_DRIVER /* creates and manages the screen bitmap */ +{ + char *name; /* driver name */ + char *desc; /* description (VESA version, etc) */ + struct BITMAP *(*init)(int w, int h, int v_w, int v_h, int color_depth); + void (*exit)(struct BITMAP *b); + int (*scroll)(int x, int y); + void (*vsync)(); + void (*set_pallete)(struct RGB *p, int from, int to, int vsync); + int w, h; /* physical (not virtual!) screen size */ + int linear; /* true if video memory is linear */ + long bank_size; /* bank size, in bytes */ + long bank_gran; /* bank granularity, in bytes */ + long vid_mem; /* video memory size, in bytes */ + long vid_phys_base; /* physical address of video memory */ +} GFX_DRIVER; + + +extern GFX_DRIVER gfx_vga, gfx_modex; + +#ifdef DJGPP + +/* for djgpp */ +extern GFX_DRIVER gfx_vesa_1, gfx_vesa_2b, gfx_vesa_2l, gfx_vbeaf, + gfx_xtended, gfx_ati, gfx_mach64, gfx_cirrus64, + gfx_cirrus54, gfx_realtek, gfx_s3, gfx_trident, + gfx_et3000, gfx_et4000, gfx_paradise, gfx_video7; + +#else + +/* for linux */ +extern GFX_DRIVER gfx_svgalib; + +#endif + + +typedef struct _GFX_DRIVER_INFO /* info about a graphics driver */ +{ + int driver_id; /* integer ID */ + GFX_DRIVER *driver; /* the driver structure */ + int autodetect; /* set to allow autodetection */ +} _GFX_DRIVER_INFO; + + +/* driver table for autodetection */ +extern _GFX_DRIVER_INFO _gfx_driver_list[]; + + +/* macros for constructing the driver list */ +#define DECLARE_GFX_DRIVER_LIST(list...) \ + _GFX_DRIVER_INFO _gfx_driver_list[] = \ + { \ + list \ + { 0, NULL, 0 } \ + }; + +#define GFX_DRIVER_VGA \ + { GFX_VGA, &gfx_vga, TRUE }, + +#define GFX_DRIVER_MODEX \ + { GFX_MODEX, &gfx_modex, TRUE }, + +#define GFX_DRIVER_VBEAF \ + { GFX_VBEAF, &gfx_vbeaf, FALSE }, + +#define GFX_DRIVER_VESA2L \ + { GFX_VESA2L, &gfx_vesa_2l, TRUE }, + +#define GFX_DRIVER_VESA2B \ + { GFX_VESA2B, &gfx_vesa_2b, TRUE }, + +#define GFX_DRIVER_XTENDED \ + { GFX_XTENDED, &gfx_xtended, FALSE }, + +#define GFX_DRIVER_ATI \ + { GFX_ATI, &gfx_ati, TRUE }, + +#define GFX_DRIVER_MACH64 \ + { GFX_MACH64, &gfx_mach64, TRUE }, + +#define GFX_DRIVER_CIRRUS64 \ + { GFX_CIRRUS64, &gfx_cirrus64, FALSE }, + +#define GFX_DRIVER_CIRRUS54 \ + { GFX_CIRRUS54, &gfx_cirrus54, TRUE }, + +#define GFX_DRIVER_PARADISE \ + { GFX_PARADISE, &gfx_paradise, TRUE }, + +#define GFX_DRIVER_S3 \ + { GFX_S3, &gfx_s3, TRUE }, + +#define GFX_DRIVER_TRIDENT \ + { GFX_TRIDENT, &gfx_trident, TRUE }, + +#define GFX_DRIVER_ET3000 \ + { GFX_ET3000, &gfx_et3000, FALSE }, + +#define GFX_DRIVER_ET4000 \ + { GFX_ET4000, &gfx_et4000, TRUE }, + +#define GFX_DRIVER_VIDEO7 \ + { GFX_VIDEO7, &gfx_video7, TRUE }, + +#define GFX_DRIVER_VESA1 \ + { GFX_VESA1, &gfx_vesa_1, TRUE }, + + +extern GFX_DRIVER *gfx_driver; /* the driver currently in use */ + + +#define BMP_TYPE_LINEAR 1 /* memory bitmaps, mode 13h, SVGA */ +#define BMP_TYPE_PLANAR 2 /* mode-X bitmaps */ + + +typedef struct GFX_VTABLE /* functions for drawing onto bitmaps */ +{ + int bitmap_type; + int color_depth; + int mask_color; + + int (*getpixel)(struct BITMAP *bmp, int x, int y); + void (*putpixel)(struct BITMAP *bmp, int x, int y, int color); + void (*vline)(struct BITMAP *bmp, int x, int y1, int y2, int color); + void (*hline)(struct BITMAP *bmp, int x1, int y, int x2, int color); + void (*line)(struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color); + void (*rectfill)(struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color); + void (*draw_sprite)(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); + void (*draw_256_sprite)(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); + void (*draw_sprite_v_flip)(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); + void (*draw_sprite_h_flip)(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); + void (*draw_sprite_vh_flip)(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); + void (*draw_trans_sprite)(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); + void (*draw_lit_sprite)(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); + void (*draw_rle_sprite)(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); + void (*draw_trans_rle_sprite)(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); + void (*draw_lit_rle_sprite)(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color); + void (*draw_character)(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); + void (*textout_fixed)(struct BITMAP *bmp, void *f, int h, unsigned char *str, int x, int y, int color); + void (*blit_from_memory)(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); + void (*blit_to_memory)(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); + void (*blit_to_self)(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); + void (*blit_to_self_forward)(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); + void (*blit_to_self_backward)(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); + void (*masked_blit)(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); + void (*clear_to_color)(struct BITMAP *bitmap, int color); + void (*draw_sprite_end)(void); + void (*blit_end)(void); +} GFX_VTABLE; + + +extern GFX_VTABLE __linear_vtable8, __linear_vtable15, __linear_vtable16, + __linear_vtable24, __linear_vtable32, __modex_vtable; + + +typedef struct _VTABLE_INFO +{ + int color_depth; + GFX_VTABLE *vtable; +} _VTABLE_INFO; + +extern _VTABLE_INFO _vtable_list[]; + + +/* macros for constructing the vtable list */ +#define DECLARE_COLOR_DEPTH_LIST(list...) \ + _VTABLE_INFO _vtable_list[] = \ + { \ + list \ + { 0, NULL } \ + }; + +#define COLOR_DEPTH_8 \ + { 8, &__linear_vtable8 }, + +#define COLOR_DEPTH_15 \ + { 15, &__linear_vtable15 }, + +#define COLOR_DEPTH_16 \ + { 16, &__linear_vtable16 }, + +#define COLOR_DEPTH_24 \ + { 24, &__linear_vtable24 }, + +#define COLOR_DEPTH_32 \ + { 32, &__linear_vtable32 }, + + + +typedef struct BITMAP /* a bitmap structure */ +{ + int w, h; /* width and height in pixels */ + int clip; /* flag if clipping is turned on */ + int cl, cr, ct, cb; /* clip left, right, top and bottom values */ + GFX_VTABLE *vtable; /* drawing functions */ + void (*write_bank)(); /* write bank selector, see bank.s */ + void (*read_bank)(); /* read bank selector, see bank.s */ + void *dat; /* the memory we allocated for the bitmap */ + int bitmap_id; /* for identifying sub-bitmaps */ + void *extra; /* points to a structure with more info */ + int line_ofs; /* line offset (for screen sub-bitmaps) */ + int seg; /* bitmap segment */ + unsigned char *line[0]; /* pointers to the start of each line */ +} BITMAP; + + +extern BITMAP *screen; + +#define SCREEN_W (gfx_driver ? gfx_driver->w : 0) +#define SCREEN_H (gfx_driver ? gfx_driver->h : 0) + +#define VIRTUAL_W (screen ? screen->w : 0) +#define VIRTUAL_H (screen ? screen->h : 0) + +#define COLORCONV_EXPAND_256 1 /* 8 -> 15/16/24/32 */ +#define COLORCONV_REDUCE_TO_256 2 /* 15/16/24/32 -> 8 */ +#define COLORCONV_EXPAND_15_TO_16 4 /* 15 -> 16 */ +#define COLORCONV_REDUCE_16_TO_15 8 /* 16 -> 15 */ +#define COLORCONV_EXPAND_HI_TO_TRUE 16 /* 15/16 -> 24/32 */ +#define COLORCONV_REDUCE_TRUE_TO_HI 32 /* 24/32 -> 15/16 */ +#define COLORCONV_24_EQUALS_32 64 /* 24/32 -> 24/32 */ + +#define COLORCONV_NONE 0 +#define COLORCONV_TOTAL 0xFFFF + +#define COLORCONV_PARTIAL (COLORCONV_EXPAND_15_TO_16 | \ + COLORCONV_REDUCE_16_TO_15 | \ + COLORCONV_24_EQUALS_32) + +#define COLORCONV_MOST (COLORCONV_EXPAND_15_TO_16 | \ + COLORCONV_REDUCE_16_TO_15 | \ + COLORCONV_EXPAND_HI_TO_TRUE | \ + COLORCONV_REDUCE_TRUE_TO_HI | \ + COLORCONV_24_EQUALS_32) + +void set_color_depth(int depth); +void set_color_conversion(int mode); +int set_gfx_mode(int card, int w, int h, int v_w, int v_h); +int scroll_screen(int x, int y); +void request_modex_scroll(int x, int y); +int poll_modex_scroll(); +void split_modex_screen(int line); + +BITMAP *create_bitmap(int width, int height); +BITMAP *create_bitmap_ex(int color_depth, int width, int height); +BITMAP *create_sub_bitmap(BITMAP *parent, int x, int y, int width, int height); +void destroy_bitmap(BITMAP *bitmap); + + +__INLINE__ int bitmap_color_depth(BITMAP *bmp) +{ + return bmp->vtable->color_depth; +} + + +__INLINE__ int bitmap_mask_color(BITMAP *bmp) +{ + return bmp->vtable->mask_color; +} + + +__INLINE__ int is_same_bitmap(BITMAP *bmp1, BITMAP *bmp2) +{ + return ((bmp1 == bmp2) || + ((bmp1->bitmap_id != 0) && (bmp1->bitmap_id == bmp2->bitmap_id))); +} + + +__INLINE__ int is_linear_bitmap(BITMAP *bmp) +{ + return (bmp->vtable->bitmap_type == BMP_TYPE_LINEAR); +} + + +__INLINE__ int is_planar_bitmap(BITMAP *bmp) +{ + return (bmp->vtable->bitmap_type == BMP_TYPE_PLANAR); +} + + +__INLINE__ int is_memory_bitmap(BITMAP *bmp) +{ + return (bmp->dat != NULL); +} + + +__INLINE__ int is_screen_bitmap(BITMAP *bmp) +{ + return is_same_bitmap(bmp, screen); +} + + +__INLINE__ int is_sub_bitmap(BITMAP *bmp) +{ + return ((bmp->dat == NULL) && (bmp != screen)); +} + +#endif + + + +/************************************************/ +/************ Color/Pallete routines ************/ +/************************************************/ + +#if !defined alleg_palette_unused || !defined alleg_flic_unused + +typedef struct RGB +{ + unsigned char r, g, b; + unsigned char filler; +} RGB; + +#define PAL_SIZE 256 + +typedef RGB PALLETE[PAL_SIZE]; + +extern RGB black_rgb; +extern PALLETE black_pallete, desktop_pallete, _current_pallete; + +typedef struct { + unsigned char data[32][32][32]; +} RGB_MAP; + +typedef struct { + unsigned char data[PAL_SIZE][PAL_SIZE]; +} COLOR_MAP; + +extern RGB_MAP *rgb_map; +extern COLOR_MAP *color_map; + +typedef unsigned long (*BLENDER_FUNC)(unsigned long x, unsigned long y); + +typedef struct { + BLENDER_FUNC blend[256]; +} BLENDER_MAP; + +extern int _color_depth; + +extern int _rgb_r_shift_15, _rgb_g_shift_15, _rgb_b_shift_15, + _rgb_r_shift_16, _rgb_g_shift_16, _rgb_b_shift_16, + _rgb_r_shift_24, _rgb_g_shift_24, _rgb_b_shift_24, + _rgb_r_shift_32, _rgb_g_shift_32, _rgb_b_shift_32; + +extern int _rgb_scale_5[32], _rgb_scale_6[64]; + +#define MASK_COLOR_8 0 +#define MASK_COLOR_15 0x7C1F +#define MASK_COLOR_16 0xF81F +#define MASK_COLOR_24 0xFF00FF +#define MASK_COLOR_32 0xFF00FF + +extern int pallete_color[256]; + +void set_color(int index, RGB *p); +void set_pallete(PALLETE p); +void set_pallete_range(PALLETE p, int from, int to, int vsync); + +void get_color(int index, RGB *p); +void get_pallete(PALLETE p); +void get_pallete_range(PALLETE p, int from, int to); + +void fade_interpolate(PALLETE source, PALLETE dest, PALLETE output, int pos, int from, int to); +void fade_from_range(PALLETE source, PALLETE dest, int speed, int from, int to); +void fade_in_range(PALLETE p, int speed, int from, int to); +void fade_out_range(int speed, int from, int to); +void fade_from(PALLETE source, PALLETE dest, int speed); +void fade_in(PALLETE p, int speed); +void fade_out(int speed); + +void select_pallete(PALLETE p); +void unselect_pallete(); + +void generate_332_palette(PALLETE pal); +int generate_optimized_palette(BITMAP *image, PALLETE pal, char rsvdcols[256]); + +void create_rgb_table(RGB_MAP *table, PALLETE pal, void (*callback)(int pos)); +void create_light_table(COLOR_MAP *table, PALLETE pal, int r, int g, int b, void (*callback)(int pos)); +void create_trans_table(COLOR_MAP *table, PALLETE pal, int r, int g, int b, void (*callback)(int pos)); +void create_color_table(COLOR_MAP *table, PALLETE pal, RGB (*blend)(PALLETE pal, int x, int y), void (*callback)(int pos)); + +void set_blender_mode(BLENDER_MAP *b15, BLENDER_MAP *b16, BLENDER_MAP *b24, int r, int g, int b, int a); +void set_trans_blender(int r, int g, int b, int a); + +void hsv_to_rgb(float h, float s, float v, int *r, int *g, int *b); +void rgb_to_hsv(int r, int g, int b, float *h, float *s, float *v); + +int bestfit_color(PALLETE pal, int r, int g, int b); + +int makecol(int r, int g, int b); +int makecol8(int r, int g, int b); +int makecol_depth(int color_depth, int r, int g, int b); + +int getr(int c); +int getg(int c); +int getb(int c); + +int getr_depth(int color_depth, int c); +int getg_depth(int color_depth, int c); +int getb_depth(int color_depth, int c); + + +__INLINE__ void vsync() +{ + gfx_driver->vsync(); +} + + +__INLINE__ void _set_color(int index, RGB *p) +{ + outportb(0x3C8, index); + outportb(0x3C9, p->r); + outportb(0x3C9, p->g); + outportb(0x3C9, p->b); + + _current_pallete[index] = *p; +} + + +__INLINE__ int makecol15(int r, int g, int b) +{ + return (((r >> 3) << _rgb_r_shift_15) | + ((g >> 3) << _rgb_g_shift_15) | + ((b >> 3) << _rgb_b_shift_15)); +} + + +__INLINE__ int makecol16(int r, int g, int b) +{ + return (((r >> 3) << _rgb_r_shift_16) | + ((g >> 2) << _rgb_g_shift_16) | + ((b >> 3) << _rgb_b_shift_16)); +} + + +__INLINE__ int makecol24(int r, int g, int b) +{ + return ((r << _rgb_r_shift_24) | + (g << _rgb_g_shift_24) | + (b << _rgb_b_shift_24)); +} + + +__INLINE__ int makecol32(int r, int g, int b) +{ + return ((r << _rgb_r_shift_32) | + (g << _rgb_g_shift_32) | + (b << _rgb_b_shift_32)); +} + + +__INLINE__ int getr8(int c) +{ + return _rgb_scale_6[(int)_current_pallete[c].r]; +} + + +__INLINE__ int getg8(int c) +{ + return _rgb_scale_6[(int)_current_pallete[c].g]; +} + + +__INLINE__ int getb8(int c) +{ + return _rgb_scale_6[(int)_current_pallete[c].b]; +} + + +__INLINE__ int getr15(int c) +{ + return _rgb_scale_5[(c >> _rgb_r_shift_15) & 0x1F]; +} + + +__INLINE__ int getg15(int c) +{ + return _rgb_scale_5[(c >> _rgb_g_shift_15) & 0x1F]; +} + + +__INLINE__ int getb15(int c) +{ + return _rgb_scale_5[(c >> _rgb_b_shift_15) & 0x1F]; +} + + +__INLINE__ int getr16(int c) +{ + return _rgb_scale_5[(c >> _rgb_r_shift_16) & 0x1F]; +} + + +__INLINE__ int getg16(int c) +{ + return _rgb_scale_6[(c >> _rgb_g_shift_16) & 0x3F]; +} + + +__INLINE__ int getb16(int c) +{ + return _rgb_scale_5[(c >> _rgb_b_shift_16) & 0x1F]; +} + + +__INLINE__ int getr24(int c) +{ + return ((c >> _rgb_r_shift_24) & 0xFF); +} + + +__INLINE__ int getg24(int c) +{ + return ((c >> _rgb_g_shift_24) & 0xFF); +} + + +__INLINE__ int getb24(int c) +{ + return ((c >> _rgb_b_shift_24) & 0xFF); +} + + +__INLINE__ int getr32(int c) +{ + return ((c >> _rgb_r_shift_32) & 0xFF); +} + + +__INLINE__ int getg32(int c) +{ + return ((c >> _rgb_g_shift_32) & 0xFF); +} + + +__INLINE__ int getb32(int c) +{ + return ((c >> _rgb_b_shift_32) & 0xFF); +} + + +/* in case you want to spell 'pallete' as 'palette' */ +#define PALETTE PALLETE +#define black_palette black_pallete +#define desktop_palette desktop_pallete +#define set_palette set_pallete +#define get_palette get_pallete +#define set_palette_range set_pallete_range +#define get_palette_range get_pallete_range +#define fli_palette fli_pallete +#define palette_color pallete_color +#define DAT_PALETTE DAT_PALLETE +#define select_palette select_pallete +#define unselect_palette unselect_pallete +#define generate_332_pallete generate_332_palette +#define generate_optimised_pallete generate_optimised_palette + +#endif + + + +/******************************************************/ +/************ Graphics and sprite routines ************/ +/******************************************************/ + +#if !defined alleg_graphics_unused + +void set_clip(BITMAP *bitmap, int x1, int y1, int x2, int y2); + +#define DRAW_MODE_SOLID 0 /* flags for drawing_mode() */ +#define DRAW_MODE_XOR 1 +#define DRAW_MODE_COPY_PATTERN 2 +#define DRAW_MODE_SOLID_PATTERN 3 +#define DRAW_MODE_MASKED_PATTERN 4 +#define DRAW_MODE_TRANS 5 + +void drawing_mode(int mode, BITMAP *pattern, int x_anchor, int y_anchor); +void xor_mode(int xor); +void solid_mode(); + + +__INLINE__ int getpixel(BITMAP *bmp, int x, int y) +{ + return bmp->vtable->getpixel(bmp, x, y); +} + + +__INLINE__ void putpixel(BITMAP *bmp, int x, int y, int color) +{ + bmp->vtable->putpixel(bmp, x, y, color); +} + + +__INLINE__ void vline(BITMAP *bmp, int x, int y1, int y2, int color) +{ + bmp->vtable->vline(bmp, x, y1, y2, color); +} + + +__INLINE__ void hline(BITMAP *bmp, int x1, int y, int x2, int color) +{ + bmp->vtable->hline(bmp, x1, y, x2, color); +} + + +__INLINE__ void line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) +{ + bmp->vtable->line(bmp, x1, y1, x2, y2, color); +} + + +__INLINE__ void rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) +{ + bmp->vtable->rectfill(bmp, x1, y1, x2, y2, color); +} + + +__INLINE__ void draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y) +{ + if (sprite->vtable->color_depth == 8) + bmp->vtable->draw_256_sprite(bmp, sprite, x, y); + else + bmp->vtable->draw_sprite(bmp, sprite, x, y); +} + + +__INLINE__ void draw_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y) +{ + bmp->vtable->draw_sprite_v_flip(bmp, sprite, x, y); +} + + +__INLINE__ void draw_sprite_h_flip(BITMAP *bmp, BITMAP *sprite, int x, int y) +{ + bmp->vtable->draw_sprite_h_flip(bmp, sprite, x, y); +} + + +__INLINE__ void draw_sprite_vh_flip(BITMAP *bmp, BITMAP *sprite, int x, int y) +{ + bmp->vtable->draw_sprite_vh_flip(bmp, sprite, x, y); +} + + +__INLINE__ void draw_trans_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y) +{ + bmp->vtable->draw_trans_sprite(bmp, sprite, x, y); +} + + +__INLINE__ void draw_lit_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int color) +{ + bmp->vtable->draw_lit_sprite(bmp, sprite, x, y, color); +} + + +__INLINE__ void draw_character(BITMAP *bmp, BITMAP *sprite, int x, int y, int color) +{ + bmp->vtable->draw_character(bmp, sprite, x, y, color); +} + + +__INLINE__ void draw_rle_sprite(BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y) +{ + bmp->vtable->draw_rle_sprite(bmp, sprite, x, y); +} + + +__INLINE__ void draw_trans_rle_sprite(BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y) +{ + bmp->vtable->draw_trans_rle_sprite(bmp, sprite, x, y); +} + + +__INLINE__ void draw_lit_rle_sprite(BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color) +{ + bmp->vtable->draw_lit_rle_sprite(bmp, sprite, x, y, color); +} + + +__INLINE__ void clear_to_color(BITMAP *bitmap, int color) +{ + bitmap->vtable->clear_to_color(bitmap, color); +} + + +void do_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int d, void (*proc)(BITMAP *, int, int, int)); +void triangle(BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int color); +void polygon(BITMAP *bmp, int vertices, int *points, int color); +void rect(BITMAP *bmp, int x1, int y1, int x2, int y2, int color); +void do_circle(BITMAP *bmp, int x, int y, int radius, int d, void (*proc)(BITMAP *, int, int, int)); +void circle(BITMAP *bmp, int x, int y, int radius, int color); +void circlefill(BITMAP *bmp, int x, int y, int radius, int color); +void do_ellipse(BITMAP *bmp, int x, int y, int rx, int ry, int d, void (*proc)(BITMAP *, int, int, int)); +void ellipse(BITMAP *bmp, int x, int y, int rx, int ry, int color); +void ellipsefill(BITMAP *bmp, int cx, int cy, int rx, int ry, int color); +void calc_spline(int points[8], int npts, int *x, int *y); +void spline(BITMAP *bmp, int points[8], int color); +void floodfill(BITMAP *bmp, int x, int y, int color); +void blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void masked_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void stretch_blit(BITMAP *s, BITMAP *d, int s_x, int s_y, int s_w, int s_h, int d_x, int d_y, int d_w, int d_h); +void stretch_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int w, int h); +void rotate_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle); +void rotate_scaled_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale); +void clear(BITMAP *bitmap); + + +typedef struct RLE_SPRITE /* a RLE compressed sprite */ +{ + int w, h; /* width and height in pixels */ + int color_depth; /* color depth of the image */ + int size; /* size of sprite data in bytes */ + signed char dat[0]; /* RLE bitmap data */ +} RLE_SPRITE; + + +RLE_SPRITE *get_rle_sprite(BITMAP *bitmap); +void destroy_rle_sprite(RLE_SPRITE *sprite); + + +typedef struct COMPILED_SPRITE /* a compiled sprite */ +{ + short planar; /* set if it's a planar (mode-X) sprite */ + short color_depth; /* color depth of the image */ + short w, h; /* size of the sprite */ + struct { + void *draw; /* routines to draw the image */ + int len; /* length of the drawing functions */ + } proc[4]; +} COMPILED_SPRITE; + + +COMPILED_SPRITE *get_compiled_sprite(BITMAP *bitmap, int planar); +void destroy_compiled_sprite(COMPILED_SPRITE *sprite); +void draw_compiled_sprite(BITMAP *bmp, COMPILED_SPRITE *sprite, int x, int y); + + +#define FONT_SIZE 224 /* number of characters in a font */ + + +typedef struct FONT_8x8 /* a simple 8x8 font */ +{ + unsigned char dat[FONT_SIZE][8]; +} FONT_8x8; + + +typedef struct FONT_8x16 /* a simple 8x16 font */ +{ + unsigned char dat[FONT_SIZE][16]; +} FONT_8x16; + + +typedef struct FONT_PROP /* a proportional font */ +{ + BITMAP *dat[FONT_SIZE]; +} FONT_PROP; + + +typedef struct FONT /* can be either */ +{ + int height; + union { + FONT_8x8 *dat_8x8; + FONT_8x16 *dat_8x16; + FONT_PROP *dat_prop; + } dat; +} FONT; + + +extern FONT *font; + +void text_mode(int mode); +void textout(BITMAP *bmp, FONT *f, unsigned char *str, int x, int y, int color); +void textout_centre(BITMAP *bmp, FONT *f, unsigned char *str, int x, int y, int color); +void textout_justify(BITMAP *bmp, FONT *f, unsigned char *str, int x1, int x2, int y, int diff, int color); +void textprintf(BITMAP *bmp, FONT *f, int x, int y, int color, char *format, ...) __attribute__ ((format (printf, 6, 7))); +void textprintf_centre(BITMAP *bmp, FONT *f, int x, int y, int color, char *format, ...) __attribute__ ((format (printf, 6, 7))); + +int text_length(FONT *f, unsigned char *str); +int text_height(FONT *f); +void destroy_font(FONT *f); + + +#ifdef __cplusplus + +} /* end of extern "C" */ + + +__INLINE__ void textout(BITMAP *bmp, FONT *f, char *str, int x, int y, int color) +{ + textout(bmp, f, (unsigned char *)str, x, y, color); +} + + +__INLINE__ void textout_centre(BITMAP *bmp, FONT *f, char *str, int x, int y, int color) +{ + textout_centre(bmp, f, (unsigned char *)str, x, y, color); +} + + +__INLINE__ void textout_justify(BITMAP *bmp, FONT *f, char *str, int x1, int x2, int y, int diff, int color) +{ + textout_justify(bmp, f, (unsigned char *)str, x1, x2, diff, y, color); +} + + +__INLINE__ int text_length(FONT *f, char *str) +{ + return text_length(f, (unsigned char *)str); +} + + +extern "C" { + +#endif /* ifdef __cplusplus */ + + +typedef struct V3D /* a 3d point (fixed point version) */ +{ + fixed x, y, z; /* position */ + fixed u, v; /* texture map coordinates */ + int c; /* color */ +} V3D; + + +typedef struct V3D_f /* a 3d point (floating point version) */ +{ + float x, y, z; /* position */ + float u, v; /* texture map coordinates */ + int c; /* color */ +} V3D_f; + + +#define POLYTYPE_FLAT 0 +#define POLYTYPE_GCOL 1 +#define POLYTYPE_GRGB 2 +#define POLYTYPE_ATEX 3 +#define POLYTYPE_PTEX 4 +#define POLYTYPE_ATEX_MASK 5 +#define POLYTYPE_PTEX_MASK 6 +#define POLYTYPE_ATEX_LIT 7 +#define POLYTYPE_PTEX_LIT 8 + + +void polygon3d(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D *vtx[]); +void polygon3d_f(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D_f *vtx[]); +void triangle3d(BITMAP *bmp, int type, BITMAP *texture, V3D *v1, V3D *v2, V3D *v3); +void triangle3d_f(BITMAP *bmp, int type, BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3); +void quad3d(BITMAP *bmp, int type, BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4); +void quad3d_f(BITMAP *bmp, int type, BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4); + +#endif + + + +/*********************************************/ +/************ Video memory access ************/ +/*********************************************/ + +#if !defined alleg_vidmem_unused + +__INLINE__ unsigned long bmp_write_line(BITMAP *bmp, int line) +{ + unsigned long result; + + asm volatile ( + " call *%3 " + + : "=a" (result) /* result in eax */ + + : "d" (bmp), /* bitmap in edx */ + "0" (line), /* line number in eax */ + "r" (bmp->write_bank) /* the bank switch routine */ + ); + + return result; +} + + +__INLINE__ unsigned long bmp_read_line(BITMAP *bmp, int line) +{ + unsigned long result; + + asm volatile ( + " call *%3 " + + : "=a" (result) /* result in eax */ + + : "d" (bmp), /* bitmap in edx */ + "0" (line), /* line number in eax */ + "r" (bmp->read_bank) /* the bank switch routine */ + ); + + return result; +} + + +__INLINE__ void _putpixel(BITMAP *bmp, int x, int y, unsigned char color) +{ + asm ( + " movw %w0, %%fs ; " + " .byte 0x64 ; " + " movb %b3, (%1, %2) " + : /* no outputs */ + + : "rm" (bmp->seg), /* segment selector in reg or mem */ + "r" (bmp_write_line(bmp, y)), /* line pointer in reg */ + "r" (x), /* line offset in reg */ + "qi" (color) /* the pixel in reg or immediate */ + ); +} + + +__INLINE__ unsigned char _getpixel(BITMAP *bmp, int x, int y) +{ + unsigned char result; + + asm ( + " movw %w1, %%fs ; " + " .byte 0x64 ; " + " movb (%2, %3), %b0" + + : "=&q" (result) /* result in al, bl, cl, or dl */ + + : "rm" (bmp->seg), /* segment selector in reg or mem */ + "r" (bmp_read_line(bmp, y)), /* line pointer in reg */ + "r" (x) /* line offset in reg */ + ); + + return result; +} + +#endif + + + +/******************************************/ +/************ FLI/FLC routines ************/ +/******************************************/ + +#if !defined alleg_flic_unused + +#define FLI_OK 0 /* FLI player return values */ +#define FLI_EOF -1 +#define FLI_ERROR -2 +#define FLI_NOT_OPEN -3 + +int play_fli(char *filename, BITMAP *bmp, int loop, int (*callback)()); +int play_memory_fli(void *fli_data, BITMAP *bmp, int loop, int (*callback)()); + +int open_fli(char *filename); +int open_memory_fli(void *fli_data); +void close_fli(); +int next_fli_frame(int loop); +void reset_fli_variables(); + +extern BITMAP *fli_bitmap; /* current frame of the FLI */ +extern PALLETE fli_pallete; /* current FLI pallete */ + +extern int fli_bmp_dirty_from; /* what part of fli_bitmap is dirty */ +extern int fli_bmp_dirty_to; +extern int fli_pal_dirty_from; /* what part of fli_pallete is dirty */ +extern int fli_pal_dirty_to; + +extern int fli_frame; /* current frame number */ + +extern volatile int fli_timer; /* for timing FLI playback */ + +#endif + + + +/****************************************/ +/************ Sound routines ************/ +/****************************************/ + +#if !defined alleg_sound_unused + +#define DIGI_VOICES 32 /* Theoretical maximums: */ +#define MIDI_VOICES 32 /* actual drivers may not be */ +#define MIDI_TRACKS 32 /* able to handle this many */ + + +typedef struct SAMPLE /* a sample */ +{ + int bits; /* 8 or 16 */ + int freq; /* sample frequency */ + int priority; /* 0-255 */ + unsigned long len; /* length (in samples) */ + unsigned long loop_start; /* loop start position */ + unsigned long loop_end; /* loop finish position */ + unsigned long param; /* for internal use by the driver */ + void *data; /* sample data */ +} SAMPLE; + + +typedef struct MIDI /* a midi file */ +{ + int divisions; /* number of ticks per quarter note */ + struct { + unsigned char *data; /* MIDI message stream */ + int len; /* length of the track data */ + } track[MIDI_TRACKS]; +} MIDI; + + +typedef struct AUDIOSTREAM +{ + int voice; /* the voice we are playing on */ + SAMPLE *samp; /* the sample we are using */ + void *b1, *b2; /* two audio buffers */ + int bufnum; /* which buffer is currently playing */ + int len; /* buffer length */ +} AUDIOSTREAM; + + +#define DIGI_AUTODETECT -1 /* for passing to install_sound() */ +#define DIGI_NONE 0 + +#ifdef DJGPP + +/* for djgpp */ +#define DIGI_SB 1 +#define DIGI_SB10 2 +#define DIGI_SB15 3 +#define DIGI_SB20 4 +#define DIGI_SBPRO 5 +#define DIGI_SB16 6 +#define DIGI_GUS 7 + +#else + +/* for linux */ +#define DIGI_LINUX_SOUND_NOT_IMPLEMENTED_YET + +#endif + +#define MIDI_AUTODETECT -1 +#define MIDI_NONE 0 + +#ifdef DJGPP + +/* for djgpp */ +#define MIDI_ADLIB 1 +#define MIDI_OPL2 2 +#define MIDI_2XOPL2 3 +#define MIDI_OPL3 4 +#define MIDI_SB_OUT 5 +#define MIDI_MPU 6 +#define MIDI_GUS 7 +#define MIDI_DIGMID 8 +#define MIDI_AWE32 9 + +#else + +/* for linux */ +#define MIDI_LINUX_SOUND_NOT_IMPLEMENTED_YET + +#endif + + +typedef struct DIGI_DRIVER /* driver for playing digital sfx */ +{ + char *name; /* driver name */ + char *desc; /* description string */ + int voices; /* available voices */ + int basevoice; /* voice number offset */ + int max_voices; /* maximum voices we can support */ + int def_voices; /* default number of voices to use */ + + /* setup routines */ + int (*detect)(); + int (*init)(int voices); + void (*exit)(); + int (*mixer_volume)(int volume); + + /* voice control functions */ + void (*init_voice)(int voice, SAMPLE *sample); + void (*release_voice)(int voice); + void (*start_voice)(int voice); + void (*stop_voice)(int voice); + void (*loop_voice)(int voice, int playmode); + + /* position control functions */ + int (*get_position)(int voice); + void (*set_position)(int voice, int position); + + /* volume control functions */ + int (*get_volume)(int voice); + void (*set_volume)(int voice, int volume); + void (*ramp_volume)(int voice, int time, int endvol); + void (*stop_volume_ramp)(int voice); + + /* pitch control functions */ + int (*get_frequency)(int voice); + void (*set_frequency)(int voice, int frequency); + void (*sweep_frequency)(int voice, int time, int endfreq); + void (*stop_frequency_sweep)(int voice); + + /* pan control functions */ + int (*get_pan)(int voice); + void (*set_pan)(int voice, int pan); + void (*sweep_pan)(int voice, int time, int endpan); + void (*stop_pan_sweep)(int voice); + + /* effect control functions */ + void (*set_echo)(int voice, int strength, int delay); + void (*set_tremolo)(int voice, int rate, int depth); + void (*set_vibrato)(int voice, int rate, int depth); +} DIGI_DRIVER; + + +typedef struct MIDI_DRIVER /* driver for playing midi music */ +{ + char *name; /* driver name */ + char *desc; /* description string */ + int voices; /* available voices */ + int basevoice; /* voice number offset */ + int max_voices; /* maximum voices we can support */ + int def_voices; /* default number of voices to use */ + int xmin, xmax; /* reserved voice range */ + + /* setup routines */ + int (*detect)(); + int (*init)(int voices); + void (*exit)(); + int (*mixer_volume)(int volume); + + /* raw MIDI output to MPU-401, etc. */ + void (*raw_midi)(unsigned char data); + + /* dynamic patch loading routines */ + int (*load_patches)(char *patches, char *drums); + void (*adjust_patches)(char *patches, char *drums); + + /* note control functions */ + void (*key_on)(int inst, int note, int bend, int vol, int pan); + void (*key_off)(int voice); + void (*set_volume)(int voice, int vol); + void (*set_pitch)(int voice, int note, int bend); + void (*set_pan)(int voice, int pan); + void (*set_vibrato)(int voice, int amount); +} MIDI_DRIVER; + + +extern DIGI_DRIVER digi_none; + +#ifdef DJGPP +/* for djgpp */ +extern DIGI_DRIVER digi_sb, digi_gus; +#else +/* for linux */ +extern DIGI_DRIVER digi_linux_sound_not_implemented_yet; +#endif + +extern MIDI_DRIVER midi_none; + +#ifdef DJGPP +/* for djgpp */ +extern MIDI_DRIVER midi_adlib, midi_sb_out, midi_mpu401, midi_gus, midi_digmid, midi_awe32; +#else +/* for linux */ +extern MIDI_DRIVER midi_linux_sound_not_implemented_yet; +#endif + + +typedef struct _DIGI_DRIVER_INFO /* info about a digital driver */ +{ + int driver_id; /* integer ID */ + DIGI_DRIVER *driver; /* the driver structure */ + int autodetect; /* set to allow autodetection */ +} _DIGI_DRIVER_INFO; + + +typedef struct _MIDI_DRIVER_INFO /* info about a MIDI driver */ +{ + int driver_id; /* integer ID */ + MIDI_DRIVER *driver; /* the driver structure */ + int autodetect; /* set to allow autodetection */ +} _MIDI_DRIVER_INFO; + + +/* driver tables for autodetection */ +extern _DIGI_DRIVER_INFO _digi_driver_list[]; +extern _MIDI_DRIVER_INFO _midi_driver_list[]; + + +/* macros for constructing the driver lists */ +#define DECLARE_DIGI_DRIVER_LIST(list...) \ + _DIGI_DRIVER_INFO _digi_driver_list[] = \ + { \ + list \ + { DIGI_NONE, &digi_none, TRUE }, \ + { 0, NULL, 0 } \ + }; + +#define DECLARE_MIDI_DRIVER_LIST(list...) \ + _MIDI_DRIVER_INFO _midi_driver_list[] = \ + { \ + list \ + { MIDI_NONE, &midi_none, TRUE }, \ + { 0, NULL, 0 } \ + }; + +#define DIGI_DRIVER_GUS \ + { DIGI_GUS, &digi_gus, TRUE }, + +#define DIGI_DRIVER_SB \ + { DIGI_SB, &digi_sb, TRUE }, \ + { DIGI_SB10, &digi_sb, FALSE }, \ + { DIGI_SB15, &digi_sb, FALSE }, \ + { DIGI_SB20, &digi_sb, FALSE }, \ + { DIGI_SBPRO, &digi_sb, FALSE }, \ + { DIGI_SB16, &digi_sb, FALSE }, + +#define MIDI_DRIVER_AWE32 \ + { MIDI_AWE32, &midi_awe32, TRUE }, + +#define MIDI_DRIVER_DIGMID \ + { MIDI_DIGMID, &midi_digmid, TRUE }, + +#define MIDI_DRIVER_ADLIB \ + { MIDI_ADLIB, &midi_adlib, TRUE }, \ + { MIDI_OPL2, &midi_adlib, FALSE }, \ + { MIDI_2XOPL2, &midi_adlib, FALSE }, \ + { MIDI_OPL3, &midi_adlib, FALSE }, + +#define MIDI_DRIVER_SB_OUT \ + { MIDI_SB_OUT, &midi_sb_out, FALSE }, + +#define MIDI_DRIVER_MPU \ + { MIDI_MPU, &midi_mpu401, FALSE }, + + +extern DIGI_DRIVER *digi_driver; /* the drivers currently in use */ +extern MIDI_DRIVER *midi_driver; + +extern int digi_card, midi_card; + +extern volatile long midi_pos; /* current position in the midi file */ + +extern long midi_loop_start; /* where to loop back to at EOF */ +extern long midi_loop_end; /* loop when we hit this position */ + +int detect_digi_driver(int driver_id); +int detect_midi_driver(int driver_id); + +void reserve_voices(int digi_voices, int midi_voices); +int install_sound(int digi_card, int midi_card, char *cfg_path); +void remove_sound(); +void set_volume(int digi_volume, int midi_volume); + +int load_ibk(char *filename, int drums); + +SAMPLE *load_sample(char *filename); +SAMPLE *load_wav(char *filename); +SAMPLE *load_voc(char *filename); +void destroy_sample(SAMPLE *spl); + +int play_sample(SAMPLE *spl, int vol, int pan, int freq, int loop); +void stop_sample(SAMPLE *spl); +void adjust_sample(SAMPLE *spl, int vol, int pan, int freq, int loop); + +int allocate_voice(SAMPLE *spl); +void deallocate_voice(int voice); +void reallocate_voice(int voice, SAMPLE *spl); +void release_voice(int voice); +void voice_start(int voice); +void voice_stop(int voice); +void voice_set_priority(int voice, int priority); +SAMPLE *voice_check(int voice); + +#define PLAYMODE_PLAY 0 +#define PLAYMODE_LOOP 1 +#define PLAYMODE_FORWARD 0 +#define PLAYMODE_BACKWARD 2 +#define PLAYMODE_BIDIR 4 + +void voice_set_playmode(int voice, int playmode); + +int voice_get_position(int voice); +void voice_set_position(int voice, int position); + +int voice_get_volume(int voice); +void voice_set_volume(int voice, int volume); +void voice_ramp_volume(int voice, int time, int endvol); +void voice_stop_volumeramp(int voice); + +int voice_get_frequency(int voice); +void voice_set_frequency(int voice, int frequency); +void voice_sweep_frequency(int voice, int time, int endfreq); +void voice_stop_frequency_sweep(int voice); + +int voice_get_pan(int voice); +void voice_set_pan(int voice, int pan); +void voice_sweep_pan(int voice, int time, int endpan); +void voice_stop_pan_sweep(int voice); + +void voice_set_echo(int voice, int strength, int delay); +void voice_set_tremolo(int voice, int rate, int depth); +void voice_set_vibrato(int voice, int rate, int depth); + +MIDI *load_midi(char *filename); +void destroy_midi(MIDI *midi); +int play_midi(MIDI *midi, int loop); +int play_looped_midi(MIDI *midi, int loop_start, int loop_end); +void stop_midi(); +void midi_pause(); +void midi_resume(); +int midi_seek(int target); +void midi_out(unsigned char *data, int length); +int load_midi_patches(); + +extern void (*midi_msg_callback)(int msg, int byte1, int byte2); +extern void (*midi_meta_callback)(int type, unsigned char *data, int length); +extern void (*midi_sysex_callback)(unsigned char *data, int length); + +AUDIOSTREAM *play_audio_stream(int len, int bits, int freq, int vol, int pan); +void stop_audio_stream(AUDIOSTREAM *stream); +void *get_audio_stream_buffer(AUDIOSTREAM *stream); +void free_audio_stream_buffer(AUDIOSTREAM *stream); + +#endif + + + +/***********************************************************/ +/************ File I/O and compression routines ************/ +/***********************************************************/ + +#if 0 +#if !defined alleg_file_unused + +char *get_filename(char *path); +char *get_extension(char *filename); +void put_backslash(char *filename); +int file_exists(char *filename, int attrib, int *aret); +int exists(char *filename); +long file_size(char *filename); +long file_time(char *filename); +int delete_file(char *filename); +int for_each_file(char *name, int attrib, void (*callback)(), int param); + +#ifndef EOF +#define EOF -1 +#endif + +#define F_READ "r" /* for use with pack_fopen() */ +#define F_WRITE "w" +#define F_READ_PACKED "rp" +#define F_WRITE_PACKED "wp" +#define F_WRITE_NOPACK "w!" + +#define F_BUF_SIZE 4096 /* 4K buffer for caching data */ +#define F_PACK_MAGIC 0x736C6821L /* magic number for packed files */ +#define F_NOPACK_MAGIC 0x736C682EL /* magic number for autodetect */ +#define F_EXE_MAGIC 0x736C682BL /* magic number for appended data */ + +#define PACKFILE_FLAG_WRITE 1 /* the file is being written */ +#define PACKFILE_FLAG_PACK 2 /* data is compressed */ +#define PACKFILE_FLAG_CHUNK 4 /* file is a sub-chunk */ +#define PACKFILE_FLAG_EOF 8 /* reached the end-of-file */ +#define PACKFILE_FLAG_ERROR 16 /* an error has occurred */ + + +typedef struct PACKFILE /* our very own FILE structure... */ +{ + int hndl; /* DOS file handle */ + int flags; /* PACKFILE_FLAG_* constants */ + unsigned char *buf_pos; /* position in buffer */ + int buf_size; /* number of bytes in the buffer */ + long todo; /* number of bytes still on the disk */ + struct PACKFILE *parent; /* nested, parent file */ + void *pack_data; /* for LZSS compression */ + char *filename; /* name of the file */ + char *password; /* current encryption position */ + unsigned char buf[F_BUF_SIZE]; /* the actual data buffer */ +} PACKFILE; + + +void packfile_password(char *password); +PACKFILE *pack_fopen(char *filename, char *mode); +int pack_fclose(PACKFILE *f); +int pack_fseek(PACKFILE *f, int offset); +PACKFILE *pack_fopen_chunk(PACKFILE *f, int pack); +PACKFILE *pack_fclose_chunk(PACKFILE *f); +int pack_igetw(PACKFILE *f); +long pack_igetl(PACKFILE *f); +int pack_iputw(int w, PACKFILE *f); +long pack_iputl(long l, PACKFILE *f); +int pack_mgetw(PACKFILE *f); +long pack_mgetl(PACKFILE *f); +int pack_mputw(int w, PACKFILE *f); +long pack_mputl(long l, PACKFILE *f); +long pack_fread(void *p, long n, PACKFILE *f); +long pack_fwrite(void *p, long n, PACKFILE *f); +char *pack_fgets(char *p, int max, PACKFILE *f); +int pack_fputs(char *p, PACKFILE *f); + +int _sort_out_getc(PACKFILE *f); +int _sort_out_putc(int c, PACKFILE *f); + +#define pack_feof(f) ((f)->flags & PACKFILE_FLAG_EOF) +#define pack_ferror(f) ((f)->flags & PACKFILE_FLAG_ERROR) + + +__INLINE__ int pack_getc(PACKFILE *f) +{ + f->buf_size--; + if (f->buf_size > 0) + return *(f->buf_pos++); + else + return _sort_out_getc(f); +} + + +__INLINE__ int pack_putc(int c, PACKFILE *f) +{ + f->buf_size++; + if (f->buf_size >= F_BUF_SIZE) + return _sort_out_putc(c, f); + else + return (*(f->buf_pos++) = c); +} +#endif + + + +/*******************************************/ +/************ Datafile routines ************/ +/*******************************************/ + +#if !defined alleg_datafile_unused + +#define DAT_ID(a,b,c,d) ((a<<24) | (b<<16) | (c<<8) | d) + +#define DAT_MAGIC DAT_ID('A','L','L','.') +#define DAT_FILE DAT_ID('F','I','L','E') +#define DAT_DATA DAT_ID('D','A','T','A') +#define DAT_FONT DAT_ID('F','O','N','T') +#define DAT_SAMPLE DAT_ID('S','A','M','P') +#define DAT_MIDI DAT_ID('M','I','D','I') +#define DAT_PATCH DAT_ID('P','A','T',' ') +#define DAT_FLI DAT_ID('F','L','I','C') +#define DAT_BITMAP DAT_ID('B','M','P',' ') +#define DAT_RLE_SPRITE DAT_ID('R','L','E',' ') +#define DAT_C_SPRITE DAT_ID('C','M','P',' ') +#define DAT_XC_SPRITE DAT_ID('X','C','M','P') +#define DAT_PALLETE DAT_ID('P','A','L',' ') +#define DAT_PROPERTY DAT_ID('p','r','o','p') +#define DAT_NAME DAT_ID('N','A','M','E') +#define DAT_END -1 + + +typedef struct DATAFILE_PROPERTY +{ + char *dat; /* pointer to the data */ + int type; /* property type */ +} DATAFILE_PROPERTY; + + +typedef struct DATAFILE +{ + void *dat; /* pointer to the data */ + int type; /* object type */ + long size; /* size of the object */ + DATAFILE_PROPERTY *prop; /* object properties */ +} DATAFILE; + + +DATAFILE *load_datafile(char *filename); +void unload_datafile(DATAFILE *dat); + +DATAFILE *load_datafile_object(char *filename, char *objectname); +void unload_datafile_object(DATAFILE *dat); + +char *get_datafile_property(DATAFILE *dat, int type); +void register_datafile_object(int id, void *(*load)(PACKFILE *f, long size), void (*destroy)(void *data)); + +void fixup_datafile(DATAFILE *data); + +BITMAP *load_bitmap(char *filename, RGB *pal); +BITMAP *load_bmp(char *filename, RGB *pal); +BITMAP *load_lbm(char *filename, RGB *pal); +BITMAP *load_pcx(char *filename, RGB *pal); +BITMAP *load_tga(char *filename, RGB *pal); + +int save_bitmap(char *filename, BITMAP *bmp, RGB *pal); +int save_bmp(char *filename, BITMAP *bmp, RGB *pal); +int save_pcx(char *filename, BITMAP *bmp, RGB *pal); +int save_tga(char *filename, BITMAP *bmp, RGB *pal); + +void register_bitmap_file_type(char *ext, BITMAP *(*load)(char *filename, RGB *pal), int (*save)(char *filename, BITMAP *bmp, RGB *pal)); + +#endif +#endif + + + +/***************************************/ +/************ Math routines ************/ +/***************************************/ + +#if !defined alleg_math_unused + +__INLINE__ fixed itofix(int x) +{ + return x << 16; +} + + +__INLINE__ int fixtoi(fixed x) +{ + return (x >> 16) + ((x & 0x8000) >> 15); +} + + +__INLINE__ fixed ftofix(double x) +{ + if (x > 32767.0) { + errno = ERANGE; + return 0x7FFFFFFF; + } + + if (x < -32768.0) { + errno = ERANGE; + return -0x80000000; + } + + return (long)(x * 65536.0 + (x < 0 ? -0.5 : 0.5)); +} + + +__INLINE__ double fixtof(fixed x) +{ + return (double)x / 65536.0; +} + + +fixed fsqrt(fixed x); +fixed fatan(fixed x); +fixed fatan2(fixed y, fixed x); + +extern fixed _cos_tbl[]; +extern fixed _tan_tbl[]; +extern fixed _acos_tbl[]; + + +__INLINE__ fixed fcos(fixed x) +{ + return _cos_tbl[((x & 0x4000) ? (x >> 15) + 1 : (x >> 15)) & 0x1ff]; +} + + +__INLINE__ fixed fsin(fixed x) +{ + return _cos_tbl[(((x & 0x4000) ? (x >> 15) + 1 : (x >> 15)) -128) & 0x1ff]; +} + + +__INLINE__ fixed ftan(fixed x) +{ + return _tan_tbl[((x & 0x4000) ? (x >> 15) + 1 : (x >> 15)) & 0xff]; +} + + +__INLINE__ fixed facos(fixed x) +{ + if ((x < -65536L) || (x > 65536L)) { + errno = EDOM; + return 0L; + } + + return _acos_tbl[(x+65536L)>>8]; +} + + +__INLINE__ fixed fasin(fixed x) +{ + if ((x < -65536L) || (x > 65536L)) { + errno = EDOM; + return 0L; + } + + return 0x00400000L - _acos_tbl[(x+65536L)>>8]; +} + + +__INLINE__ fixed fadd(fixed x, fixed y) +{ + fixed result; + + asm ( + " addl %2, %0 ; " /* do the addition */ + " jno 0f ; " /* check for overflow */ + + " movl $2, _errno ; " /* on overflow, set errno */ + " movl $0x7fffffff, %0 ; " /* and return MAXINT */ + " cmpl $0, %2 ; " + " jg 0f ; " + " negl %0 ; " + + " 0: " /* finished */ + + : "=r" (result) /* result in a register */ + + : "0" (x), /* x in the output register */ + "g" (y) /* y can go anywhere */ + + : "%cc" /* clobbers flags */ + ); + + return result; +} + + +__INLINE__ fixed fsub(fixed x, fixed y) +{ + fixed result; + + asm ( + " subl %2, %0 ; " /* do the subtraction */ + " jno 0f ; " /* check for overflow */ + + " movl $2, _errno ; " /* on overflow, set errno */ + " movl $0x7fffffff, %0 ; " /* and return MAXINT */ + " cmpl $0, %2 ; " + " jl 0f ; " + " negl %0 ; " + + " 0: " /* finished */ + + : "=r" (result) /* result in a register */ + + : "0" (x), /* x in the output register */ + "g" (y) /* y can go anywhere */ + + : "%cc" /* clobbers flags */ + ); + + return result; +} + + +__INLINE__ fixed fmul(fixed x, fixed y) +{ + fixed result; + + asm ( + " movl %1, %0 ; " + " imull %2 ; " /* do the multiply */ + " shrdl $16, %%edx, %0 ; " + + " shrl $16, %%edx ; " /* check for overflow */ + " jz 0f ; " + " cmpw $0xFFFF, %%dx ; " + " je 0f ; " + + " movl $2, _errno ; " /* on overflow, set errno */ + " movl $0x7fffffff, %0 ; " /* and return MAXINT */ + " cmpl $0, %1 ; " + " jge 1f ; " + " negl %0 ; " + " 1: " + " cmpl $0, %2 ; " + " jge 0f ; " + " negl %0 ; " + + " 0: " /* finished */ + + : "=&a" (result) /* the result has to go in eax */ + + : "mr" (x), /* x and y can be regs or mem */ + "mr" (y) + + : "%edx", "%cc" /* clobbers edx and flags */ + ); + + return result; +} + + +__INLINE__ fixed fdiv(fixed x, fixed y) +{ + fixed result; + + asm ( + " movl %2, %%ecx ; " + " xorl %%ebx, %%ebx ; " + + " orl %0, %0 ; " /* test sign of x */ + " jns 0f ; " + + " negl %0 ; " + " incl %%ebx ; " + + " 0: " + " orl %%ecx, %%ecx ; " /* test sign of y */ + " jns 1f ; " + + " negl %%ecx ; " + " incb %%ebx ; " + + " 1: " + " movl %0, %%edx ; " /* check the range is ok */ + " shrl $16, %%edx ; " + " shll $16, %0 ; " + " cmpl %%ecx, %%edx ; " + " jae 2f ; " + + " divl %%ecx ; " /* do the divide */ + " orl %0, %0 ; " + " jns 3f ; " + + " 2: " + " movl $2, _errno ; " /* on overflow, set errno */ + " movl $0x7fffffff, %0 ; " /* and return MAXINT */ + + " 3: " + " testl $1, %%ebx ; " /* fix up the sign of the result */ + " jz 4f ; " + + " negl %0 ; " + + " 4: " /* finished */ + + : "=a" (result) /* the result has to go in eax */ + + : "0" (x), /* x in eax */ + "g" (y) /* y can be anywhere */ + + : "%ebx", "%ecx", "%edx", "%cc" /* clobbers ebx, ecx, edx + flags */ + ); + + return result; +} + + +#ifdef __cplusplus + +} /* end of extern "C" */ + + +class fix /* C++ wrapper for the fixed point routines */ +{ +public: + fixed v; + + fix() { } + fix(const fix &x) { v = x.v; } + fix(const int x) { v = itofix(x); } + fix(const long x) { v = itofix(x); } + fix(const unsigned int x) { v = itofix(x); } + fix(const unsigned long x) { v = itofix(x); } + fix(const float x) { v = ftofix(x); } + fix(const double x) { v = ftofix(x); } + + operator int() const { return fixtoi(v); } + operator long() const { return fixtoi(v); } + operator unsigned int() const { return fixtoi(v); } + operator unsigned long() const { return fixtoi(v); } + operator float() const { return fixtof(v); } + operator double() const { return fixtof(v); } + + fix& operator = (const fix &x) { v = x.v; return *this; } + fix& operator = (const int x) { v = itofix(x); return *this; } + fix& operator = (const long x) { v = itofix(x); return *this; } + fix& operator = (const unsigned int x) { v = itofix(x); return *this; } + fix& operator = (const unsigned long x) { v = itofix(x); return *this; } + fix& operator = (const float x) { v = ftofix(x); return *this; } + fix& operator = (const double x) { v = ftofix(x); return *this; } + + fix& operator += (const fix x) { v += x.v; return *this; } + fix& operator -= (const fix x) { v -= x.v; return *this; } + fix& operator *= (const fix x) { v = fmul(v, x.v); return *this; } + fix& operator *= (const int x) { v *= x; return *this; } + fix& operator /= (const fix x) { v = fdiv(v, x.v); return *this; } + fix& operator /= (const int x) { v /= x; return *this; } + fix& operator <<= (const int x) { v <<= x; return *this; } + fix& operator >>= (const int x) { v >>= x; return *this; } + + fix& operator ++ () { v += itofix(1); return *this; } + fix& operator -- () { v -= itofix(1); return *this; } + + fix operator - () { fix t; t.v = -v; return t; } + + inline friend fix operator + (const fix x, const fix y) { fix t; t.v = x.v + y.v; return t; } + inline friend fix operator - (const fix x, const fix y) { fix t; t.v = x.v - y.v; return t; } + inline friend fix operator * (const fix x, const fix y) { fix t; t.v = fmul(x.v, y.v); return t; } + inline friend fix operator * (const fix x, const int y) { fix t; t.v = x.v * y; return t; } + inline friend fix operator * (const int x, const fix y) { fix t; t.v = y.v * x; return t; } + inline friend fix operator / (const fix x, const fix y) { fix t; t.v = fdiv(x.v, y.v); return t; } + inline friend fix operator / (const fix x, const int y) { fix t; t.v = x.v / y; return t; } + inline friend fix operator << (const fix x, const int y) { fix t; t.v = x.v << y; return t; } + inline friend fix operator >> (const fix x, const int y) { fix t; t.v = x.v >> y; return t; } + + inline friend int operator == (const fix x, const fix y) { return (x.v == y.v); } + inline friend int operator != (const fix x, const fix y) { return (x.v != y.v); } + inline friend int operator < (const fix x, const fix y) { return (x.v < y.v); } + inline friend int operator > (const fix x, const fix y) { return (x.v > y.v); } + inline friend int operator <= (const fix x, const fix y) { return (x.v <= y.v); } + inline friend int operator >= (const fix x, const fix y) { return (x.v >= y.v); } + + inline friend fix sqrt(fix x) { fix t; t.v = fsqrt(x.v); return t; } + inline friend fix cos(fix x) { fix t; t.v = fcos(x.v); return t; } + inline friend fix sin(fix x) { fix t; t.v = fsin(x.v); return t; } + inline friend fix tan(fix x) { fix t; t.v = ftan(x.v); return t; } + inline friend fix acos(fix x) { fix t; t.v = facos(x.v); return t; } + inline friend fix asin(fix x) { fix t; t.v = fasin(x.v); return t; } + inline friend fix atan(fix x) { fix t; t.v = fatan(x.v); return t; } + inline friend fix atan2(fix x, fix y) { fix t; t.v = fatan2(x.v, y.v); return t; } +}; + + +extern "C" { + +#endif /* ifdef __cplusplus */ + + +typedef struct MATRIX /* transformation matrix (fixed point) */ +{ + fixed v[3][3]; /* scaling and rotation */ + fixed t[3]; /* translation */ +} MATRIX; + + +typedef struct MATRIX_f /* transformation matrix (floating point) */ +{ + float v[3][3]; /* scaling and rotation */ + float t[3]; /* translation */ +} MATRIX_f; + + +extern MATRIX identity_matrix; +extern MATRIX_f identity_matrix_f; + + +void get_translation_matrix(MATRIX *m, fixed x, fixed y, fixed z); +void get_translation_matrix_f(MATRIX_f *m, float x, float y, float z); + +void get_scaling_matrix(MATRIX *m, fixed x, fixed y, fixed z); +void get_scaling_matrix_f(MATRIX_f *m, float x, float y, float z); + +void get_x_rotate_matrix(MATRIX *m, fixed r); +void get_x_rotate_matrix_f(MATRIX_f *m, float r); + +void get_y_rotate_matrix(MATRIX *m, fixed r); +void get_y_rotate_matrix_f(MATRIX_f *m, float r); + +void get_z_rotate_matrix(MATRIX *m, fixed r); +void get_z_rotate_matrix_f(MATRIX_f *m, float r); + +void get_rotation_matrix(MATRIX *m, fixed x, fixed y, fixed z); +void get_rotation_matrix_f(MATRIX_f *m, float x, float y, float z); + +void get_align_matrix(MATRIX *m, fixed xfront, fixed yfront, fixed zfront, fixed xup, fixed yup, fixed zup); +void get_align_matrix_f(MATRIX_f *m, float xfront, float yfront, float zfront, float xup, float yup, float zup); + +void get_vector_rotation_matrix(MATRIX *m, fixed x, fixed y, fixed z, fixed a); +void get_vector_rotation_matrix_f(MATRIX_f *m, float x, float y, float z, float a); + +void get_transformation_matrix(MATRIX *m, fixed scale, fixed xrot, fixed yrot, fixed zrot, fixed x, fixed y, fixed z); +void get_transformation_matrix_f(MATRIX_f *m, float scale, float xrot, float yrot, float zrot, float x, float y, float z); + +void get_camera_matrix(MATRIX *m, fixed x, fixed y, fixed z, fixed xfront, fixed yfront, fixed zfront, fixed xup, fixed yup, fixed zup, fixed fov, fixed aspect); +void get_camera_matrix_f(MATRIX_f *m, float x, float y, float z, float xfront, float yfront, float zfront, float xup, float yup, float zup, float fov, float aspect); + +void qtranslate_matrix(MATRIX *m, fixed x, fixed y, fixed z); +void qtranslate_matrix_f(MATRIX_f *m, float x, float y, float z); + +void qscale_matrix(MATRIX *m, fixed scale); +void qscale_matrix_f(MATRIX_f *m, float scale); + +void matrix_mul(MATRIX *m1, MATRIX *m2, MATRIX *out); +void matrix_mul_f(MATRIX_f *m1, MATRIX_f *m2, MATRIX_f *out); + +fixed vector_length(fixed x, fixed y, fixed z); +float vector_length_f(float x, float y, float z); + +void normalize_vector(fixed *x, fixed *y, fixed *z); +void normalize_vector_f(float *x, float *y, float *z); + +void cross_product(fixed x1, fixed y1, fixed z1, fixed x2, fixed y2, fixed z2, fixed *xout, fixed *yout, fixed *zout); +void cross_product_f(float x1, float y1, float z1, float x2, float y2, float z2, float *xout, float *yout, float *zout); + +fixed polygon_z_normal(V3D *v1, V3D *v2, V3D *v3); +float polygon_z_normal_f(V3D_f *v1, V3D_f *v2, V3D_f *v3); + + +__INLINE__ fixed dot_product(fixed x1, fixed y1, fixed z1, fixed x2, fixed y2, fixed z2) +{ + return fmul(x1, x2) + fmul(y1, y2) + fmul(z1, z2); +} + + +__INLINE__ float dot_product_f(float x1, float y1, float z1, float x2, float y2, float z2) +{ + return (x1 * x2) + (y1 * y2) + (z1 * z2); +} + + +__INLINE__ void apply_matrix(MATRIX *m, fixed x, fixed y, fixed z, fixed *xout, fixed *yout, fixed *zout) +{ + #define CALC_ROW(n) (fmul(x, m->v[n][0]) + \ + fmul(y, m->v[n][1]) + \ + fmul(z, m->v[n][2]) + \ + m->t[n]) + + *xout = CALC_ROW(0); + *yout = CALC_ROW(1); + *zout = CALC_ROW(2); + + #undef CALC_ROW +} + + +void apply_matrix_f(MATRIX_f *m, float x, float y, float z, float *xout, float *yout, float *zout); + +extern fixed _persp_xscale, _persp_yscale, _persp_xoffset, _persp_yoffset; +extern float _persp_xscale_f, _persp_yscale_f, _persp_xoffset_f, _persp_yoffset_f; + +void set_projection_viewport(int x, int y, int w, int h); + + +__INLINE__ void persp_project(fixed x, fixed y, fixed z, fixed *xout, fixed *yout) +{ + *xout = fmul(fdiv(x, z), _persp_xscale) + _persp_xoffset; + *yout = fmul(fdiv(y, z), _persp_yscale) + _persp_yoffset; +} + + +__INLINE__ void persp_project_f(float x, float y, float z, float *xout, float *yout) +{ + float z1 = 1.0 / z; + *xout = ((x * z1) * _persp_xscale_f) + _persp_xoffset_f; + *yout = ((y * z1) * _persp_yscale_f) + _persp_yoffset_f; +} + + +#ifdef __cplusplus + +} /* end of extern "C" */ + +/* overloaded functions for use with the fix class */ + + +__INLINE__ void get_translation_matrix(MATRIX *m, fix x, fix y, fix z) +{ + get_translation_matrix(m, x.v, y.v, z.v); +} + + +__INLINE__ void get_scaling_matrix(MATRIX *m, fix x, fix y, fix z) +{ + get_scaling_matrix(m, x.v, y.v, z.v); +} + + +__INLINE__ void get_x_rotate_matrix(MATRIX *m, fix r) +{ + get_x_rotate_matrix(m, r.v); +} + + +__INLINE__ void get_y_rotate_matrix(MATRIX *m, fix r) +{ + get_y_rotate_matrix(m, r.v); +} + + +__INLINE__ void get_z_rotate_matrix(MATRIX *m, fix r) +{ + get_z_rotate_matrix(m, r.v); +} + + +__INLINE__ void get_rotation_matrix(MATRIX *m, fix x, fix y, fix z) +{ + get_rotation_matrix(m, x.v, y.v, z.v); +} + + +__INLINE__ void get_align_matrix(MATRIX *m, fix xfront, fix yfront, fix zfront, fix xup, fix yup, fix zup) +{ + get_align_matrix(m, xfront.v, yfront.v, zfront.v, xup.v, yup.v, zup.v); +} + + +__INLINE__ void get_vector_rotation_matrix(MATRIX *m, fix x, fix y, fix z, fix a) +{ + get_vector_rotation_matrix(m, x.v, y.v, z.v, a.v); +} + + +__INLINE__ void get_transformation_matrix(MATRIX *m, fix scale, fix xrot, fix yrot, fix zrot, fix x, fix y, fix z) +{ + get_transformation_matrix(m, scale.v, xrot.v, yrot.v, zrot.v, x.v, y.v, z.v); +} + + +__INLINE__ void get_camera_matrix(MATRIX *m, fix x, fix y, fix z, fix xfront, fix yfront, fix zfront, fix xup, fix yup, fix zup, fix fov, fix aspect) +{ + get_camera_matrix(m, x.v, y.v, z.v, xfront.v, yfront.v, zfront.v, xup.v, yup.v, zup.v, fov.v, aspect.v); +} + + +__INLINE__ void qtranslate_matrix(MATRIX *m, fix x, fix y, fix z) +{ + qtranslate_matrix(m, x.v, y.v, z.v); +} + + +__INLINE__ void qscale_matrix(MATRIX *m, fix scale) +{ + qscale_matrix(m, scale.v); +} + + +__INLINE__ fix vector_length(fix x, fix y, fix z) +{ + fix t; + t.v = vector_length(x.v, y.v, z.v); + return t; +} + + +__INLINE__ void normalize_vector(fix *x, fix *y, fix *z) +{ + normalize_vector(&x->v, &y->v, &z->v); +} + + +__INLINE__ void cross_product(fix x1, fix y1, fix z1, fix x2, fix y2, fix z2, fix *xout, fix *yout, fix *zout) +{ + cross_product(x1.v, y1.v, z1.v, x2.v, y2.v, z2.v, &xout->v, &yout->v, &zout->v); +} + + +__INLINE__ fix dot_product(fix x1, fix y1, fix z1, fix x2, fix y2, fix z2) +{ + fix t; + t.v = dot_product(x1.v, y1.v, z1.v, x2.v, y2.v, z2.v); + return t; +} + + +__INLINE__ void apply_matrix(MATRIX *m, fix x, fix y, fix z, fix *xout, fix *yout, fix *zout) +{ + apply_matrix(m, x.v, y.v, z.v, &xout->v, &yout->v, &zout->v); +} + + +__INLINE__ void persp_project(fix x, fix y, fix z, fix *xout, fix *yout) +{ + persp_project(x.v, y.v, z.v, &xout->v, &yout->v); +} + + +extern "C" { + +#endif /* ifdef __cplusplus */ + +#endif + + + +/***************************************/ +/************ GUI routines ************/ +/***************************************/ + +#if !defined alleg_gui_unused + +/* a GUI object */ +typedef struct DIALOG +{ + int (*proc)(int, struct DIALOG *, int ); /* dialog procedure */ + int x, y, w, h; /* position and size of the object */ + int fg, bg; /* foreground and background colors */ + int key; /* keyboard shortcut (ASCII code) */ + int flags; /* flags about the object state */ + int d1, d2; /* any data the object might require */ + void *dp, *dp2, *dp3; /* pointers to more object data */ +} DIALOG; + + +/* a popup menu */ +typedef struct MENU +{ + char *text; /* menu item text */ + int (*proc)(void); /* callback function */ + struct MENU *child; /* to allow nested menus */ + int flags; /* flags about the menu state */ + void *dp; /* any data the menu might require */ +} MENU; + + +/* stored information about the state of an active GUI dialog */ +typedef struct DIALOG_PLAYER +{ + int obj; + int res; + int mouse_obj; + int focus_obj; + int joy_on; + int click_wait; + int mouse_visible; + int mouse_ox, mouse_oy; + DIALOG *dialog; + DIALOG *previous_dialog; +} DIALOG_PLAYER; + + +#define SEND_MESSAGE(d, msg, c) (d)->proc(msg, d, c) + +/* bits for the flags field */ +#define D_EXIT 1 /* object makes the dialog exit */ +#define D_SELECTED 2 /* object is selected */ +#define D_GOTFOCUS 4 /* object has the input focus */ +#define D_GOTMOUSE 8 /* mouse is on top of object */ +#define D_HIDDEN 16 /* object is not visible */ +#define D_DISABLED 32 /* object is visible but inactive */ +#define D_INTERNAL 64 /* reserved for internal use */ +#define D_USER 128 /* from here on is free for your own use */ + +/* return values for the dialog procedures */ +#define D_O_K 0 /* normal exit status */ +#define D_CLOSE 1 /* request to close the dialog */ +#define D_REDRAW 2 /* request to redraw the dialog */ +#define D_WANTFOCUS 4 /* this object wants the input focus */ +#define D_USED_CHAR 8 /* object has used the keypress */ + +/* messages for the dialog procedures */ +#define MSG_START 1 /* start the dialog, initialise */ +#define MSG_END 2 /* dialog is finished - cleanup */ +#define MSG_DRAW 3 /* draw the object */ +#define MSG_CLICK 4 /* mouse click on the object */ +#define MSG_DCLICK 5 /* double click on the object */ +#define MSG_KEY 6 /* keyboard shortcut */ +#define MSG_CHAR 7 /* other keyboard input */ +#define MSG_XCHAR 8 /* broadcast character to all objects */ +#define MSG_WANTFOCUS 9 /* does object want the input focus? */ +#define MSG_GOTFOCUS 10 /* got the input focus */ +#define MSG_LOSTFOCUS 11 /* lost the input focus */ +#define MSG_GOTMOUSE 12 /* mouse on top of object */ +#define MSG_LOSTMOUSE 13 /* mouse moved away from object */ +#define MSG_IDLE 14 /* update any background stuff */ +#define MSG_RADIO 15 /* clear radio buttons */ +#define MSG_USER 16 /* from here on are free... */ + +/* some dialog procedures */ +int d_clear_proc(int msg, DIALOG *d, int c); +int d_box_proc(int msg, DIALOG *d, int c); +int d_shadow_box_proc(int msg, DIALOG *d, int c); +int d_bitmap_proc(int msg, DIALOG *d, int c); +int d_text_proc(int msg, DIALOG *d, int c); +int d_ctext_proc(int msg, DIALOG *d, int c); +int d_button_proc(int msg, DIALOG *d, int c); +int d_check_proc(int msg, DIALOG *d, int c); +int d_radio_proc(int msg, DIALOG *d, int c); +int d_icon_proc(int msg, DIALOG *d, int c); +int d_keyboard_proc(int msg, DIALOG *d, int c); +int d_edit_proc(int msg, DIALOG *d, int c); +int d_list_proc(int msg, DIALOG *d, int c); +int d_textbox_proc(int msg, DIALOG *d, int c); +int d_slider_proc(int msg, DIALOG *d, int c); +int d_menu_proc(int msg, DIALOG *d, int c); + +extern DIALOG *active_dialog; +extern MENU *active_menu; + +extern int gui_mouse_focus; +extern int gui_fg_color, gui_mg_color, gui_bg_color; +extern int gui_font_baseline; + +int gui_textout(BITMAP *bmp, unsigned char *s, int x, int y, int color, int centre); +int gui_strlen(unsigned char *s); +void centre_dialog(DIALOG *dialog); +void set_dialog_color(DIALOG *dialog, int fg, int bg); +int find_dialog_focus(DIALOG *dialog); +int dialog_message(DIALOG *dialog, int msg, int c, int *obj); +int broadcast_dialog_message(int msg, int c); +int do_dialog(DIALOG *dialog, int focus_obj); +int popup_dialog(DIALOG *dialog, int focus_obj); +DIALOG_PLAYER *init_dialog(DIALOG *dialog, int focus_obj); +int update_dialog(DIALOG_PLAYER *player); +int shutdown_dialog(DIALOG_PLAYER *player); +int do_menu(MENU *menu, int x, int y); +int alert(char *s1, char *s2, char *s3, char *b1, char *b2, int c1, int c2); +int alert3(char *s1, char *s2, char *s3, char *b1, char *b2, char *b3, int c1, int c2, int c3); +int file_select(char *message, char *path, char *ext); +int gfx_mode_select(int *card, int *w, int *h); +int gfx_mode_select_ex(int *card, int *w, int *h, int *color_depth); + +#endif + + + +#ifdef __cplusplus +} +#endif + +#endif /* ifndef ALLEGRO_H */ + + diff --git a/arch/dos/allg_snd/sound/config.c b/arch/dos/allg_snd/sound/config.c new file mode 100644 index 00000000..69a080e1 --- /dev/null +++ b/arch/dos/allg_snd/sound/config.c @@ -0,0 +1,755 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * By Shawn Hargreaves, + * 1 Salisbury Road, + * Market Drayton, + * Shropshire, + * England, TF9 1AJ. + * + * Configuration routines. + * + * See readme.txt for copyright information. + */ + + +#include +#include +#include +#include +#include + +#include "allegro.h" +#include "internal.h" + +typedef struct CONFIG_ENTRY +{ + char *name; /* variable name (NULL if comment) */ + char *data; /* variable value */ + struct CONFIG_ENTRY *next; /* linked list */ +} CONFIG_ENTRY; + + +typedef struct CONFIG +{ + CONFIG_ENTRY *head; /* linked list of config entries */ + char *filename; /* where were we loaded from? */ + int dirty; /* has our data changed? */ +} CONFIG; + + +#define MAX_CONFIGS 4 + +static CONFIG *config[MAX_CONFIGS] = { NULL, NULL, NULL, NULL }; +static CONFIG *config_override = NULL; + +static int config_installed = FALSE; + + + +/* destroy_config: + * Destroys a config structure, writing it out to disk if the contents + * have changed. + */ +static void destroy_config(CONFIG *cfg) +{ + CONFIG_ENTRY *pos, *prev; + + if (cfg) { + if (cfg->filename) { + if (cfg->dirty) { + /* write changed data to disk */ + PACKFILE *f = pack_fopen(cfg->filename, F_WRITE); + + if (f) { + pos = cfg->head; + + while (pos) { + if (pos->name) { + pack_fputs(pos->name, f); + if (pos->name[0] != '[') + pack_fputs(" = ", f); + } + if (pos->data) + pack_fputs(pos->data, f); + + pack_fputs("\n", f); + pos = pos->next; + } + + pack_fclose(f); + } + } + + free(cfg->filename); + } + + /* destroy the variable list */ + pos = cfg->head; + + while (pos) { + prev = pos; + pos = pos->next; + + if (prev->name) + free(prev->name); + + if (prev->data) + free(prev->data); + + free(prev); + } + + free(cfg); + } +} + + + +/* config_cleanup: + * Called at shutdown time to free memory being used by the config routines, + * and write any changed data out to disk. + */ +static void config_cleanup() +{ + int i; + + for (i=0; i= 4) + set_config_file(buf[0]); + } +} + + + +/* get_line: + * Helper for splitting files up into individual lines. + */ +static int get_line(char *data, int length, char *name, char *val) +{ + char buf[256], buf2[256]; + int pos, i, j; + + for (pos=0; (poshead; + + if (prev) + *prev = NULL; + + while (p) { + if (p->name) { + if ((p->name[0] == '[') && (p->name[strlen(p->name)-1] == ']')) { + /* change section */ + in_section = (stricmp(section_name, p->name) == 0); + } + if ((in_section) || (name[0] == '[')) { + /* is this the one? */ + if (stricmp(p->name, name) == 0) + return p; + } + } + + if (prev) + *prev = p; + + p = p->next; + } + } + + return NULL; +} + + + +/* get_config_string: + * Reads a string from the configuration file. + */ +char *get_config_string(char *section, char *name, char *def) +{ + CONFIG_ENTRY *p; + + init_config(TRUE); + + p = find_config_string(config_override, section, name, NULL); + + if (!p) + p = find_config_string(config[0], section, name, NULL); + + if (p) + return (p->data ? p->data : ""); + else + return def; +} + + + +/* get_config_int: + * Reads an integer from the configuration file. + */ +int get_config_int(char *section, char *name, int def) +{ + char *s = get_config_string(section, name, NULL); + + if ((s) && (*s)) + return strtol(s, NULL, 0); + + return def; +} + + + +/* get_config_hex: + * Reads a hexadecimal integer from the configuration file. + */ +int get_config_hex(char *section, char *name, int def) +{ + char *s = get_config_string(section, name, NULL); + int i; + + if ((s) && (*s)) { + i = strtol(s, NULL, 16); + if ((i == 0x7FFFFFFF) && (stricmp(s, "7FFFFFFF") != 0)) + i = -1; + return i; + } + + return def; +} + + + +/* get_config_float: + * Reads a float from the configuration file. + */ +float get_config_float(char *section, char *name, float def) +{ + char *s = get_config_string(section, name, NULL); + + if ((s) && (*s)) + return atof(s); + + return def; +} + + + +/* get_config_argv: + * Reads an argc/argv style token list from the configuration file. + */ +char **get_config_argv(char *section, char *name, int *argc) +{ + #define MAX_ARGV 16 + + static char buf[256]; + static char *argv[MAX_ARGV]; + int pos, ac; + + char *s = get_config_string(section, name, NULL); + + if (!s) { + *argc = 0; + return NULL; + } + + strcpy(buf, s); + pos = 0; + ac = 0; + + while ((acname = malloc(strlen(name)+1); + strcpy(n->name, name); + } + else + n->name = NULL; + + if (data) { + n->data = malloc(strlen(data)+1); + strcpy(n->data, data); + } + else + n->data = NULL; + + if (p) { + n->next = p->next; + p->next = n; + } + else { + n->next = NULL; + config[0]->head = n; + } + + return n; +} + + + +/* set_config_string: + * Writes a string to the configuration file. + */ +void set_config_string(char *section, char *name, char *val) +{ + CONFIG_ENTRY *p, *prev; + char section_name[256]; + + init_config(TRUE); + + if (config[0]) { + p = find_config_string(config[0], section, name, &prev); + + if (p) { + if ((val) && (*val)) { + /* modify existing variable */ + if (p->data) + free(p->data); + + p->data = malloc(strlen(val)+1); + strcpy(p->data, val); + } + else { + /* delete variable */ + if (p->name) + free(p->name); + + if (p->data) + free(p->data); + + if (prev) + prev->next = p->next; + else + config[0]->head = p->next; + + free(p); + } + } + else { + if ((val) && (*val)) { + /* add a new variable */ + prettify_section_name(section, section_name); + + if (section_name[0]) { + p = find_config_string(config[0], NULL, section_name, &prev); + + if (!p) { + /* create a new section */ + p = config[0]->head; + while ((p) && (p->next)) + p = p->next; + + if ((p) && (p->data) && (*p->data)) + p = insert_variable(p, NULL, NULL); + + p = insert_variable(p, section_name, NULL); + } + + /* append to the end of the section */ + while ((p) && (p->next) && + (((p->next->name) && (*p->next->name)) || + ((p->next->data) && (*p->next->data)))) + p = p->next; + + p = insert_variable(p, name, val); + } + else { + /* global variable */ + p = config[0]->head; + insert_variable(NULL, name, val); + config[0]->head->next = p; + } + } + } + + config[0]->dirty = TRUE; + } +} + + + +/* set_config_int: + * Writes an integer to the configuration file. + */ +void set_config_int(char *section, char *name, int val) +{ + char buf[32]; + sprintf(buf, "%d", val); + set_config_string(section, name, buf); +} + + + +/* set_config_hex: + * Writes a hexadecimal integer to the configuration file. + */ +void set_config_hex(char *section, char *name, int val) +{ + if (val >= 0) { + char buf[32]; + sprintf(buf, "%X", val); + set_config_string(section, name, buf); + } + else + set_config_string(section, name, "-1"); +} + + + +/* set_config_float: + * Writes a float to the configuration file. + */ +void set_config_float(char *section, char *name, float val) +{ + char buf[32]; + sprintf(buf, "%f", val); + set_config_string(section, name, buf); +} + diff --git a/arch/dos/allg_snd/sound/digmid.c b/arch/dos/allg_snd/sound/digmid.c new file mode 100644 index 00000000..6cd9c82f --- /dev/null +++ b/arch/dos/allg_snd/sound/digmid.c @@ -0,0 +1,998 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * By Shawn Hargreaves, + * 1 Salisbury Road, + * Market Drayton, + * Shropshire, + * England, TF9 1AJ. + * + * Digitized sample driver for the MIDI player. + * + * Based on code by Tom Novelli. + * + * See readme.txt for copyright information. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "allegro.h" +#include "internal.h" + + +/* external interface to the Digmid driver */ +static int digmid_detect(); +static int digmid_init(int voices); +static void digmid_exit(); +static int digmid_load_patches(char *patches, char *drums); +static void digmid_key_on(int inst, int note, int bend, int vol, int pan); +static void digmid_key_off(int voice); +static void digmid_set_volume(int voice, int vol); +static void digmid_set_pitch(int voice, int note, int bend); + + +MIDI_DRIVER midi_digmid = +{ + "DIGMID", + "Software wavetable synth", + 0, 0, -1, 24, -1, -1, + digmid_detect, + digmid_init, + digmid_exit, + NULL, + NULL, + digmid_load_patches, + _dummy_adjust_patches, + digmid_key_on, + digmid_key_off, + digmid_set_volume, + digmid_set_pitch, + _dummy_noop2, + _dummy_noop2 +}; + + +#define MAX_LAYERS 64 + + +typedef struct PATCH_EXTRA /* additional data for a Gravis PATCH */ +{ + int low_note; + int high_note; + int base_note; + int play_mode; + int decay_time; + int release_time; + int sustain_level; + int scale_freq; + int scale_factor; + int pan; +} PATCH_EXTRA; + + +typedef struct PATCH /* Gravis PATCH structure */ +{ + int samples; /* number of samples in this instrument */ + SAMPLE *sample[MAX_LAYERS]; /* the waveform data */ + PATCH_EXTRA *extra[MAX_LAYERS]; /* additional waveform information */ + int master_vol; /* overall volume level */ +} PATCH; + + +/* our instruments */ +static PATCH *patch[256]; + + +/* frequency table (generated by digmid_init) */ +static float ftbl[130]; + + +/* stored information about active voices */ +typedef struct DIGMID_VOICE +{ + SAMPLE *s; + PATCH_EXTRA *e; + int inst; + int vol; +} DIGMID_VOICE; + + +static DIGMID_VOICE digmid_voice[MIDI_VOICES]; + + + +/* destroy_patch: + * Frees a PATCH struct and all samples it contains. + */ +static void destroy_patch(PATCH *pat) +{ + int i; + + if (pat) { + for (i=0; i < pat->samples; i++) { + destroy_sample(pat->sample[i]); + + _unlock_dpmi_data(pat->extra[i], sizeof(PATCH_EXTRA)); + free(pat->extra[i]); + } + + _unlock_dpmi_data(pat, sizeof(PATCH)); + free(pat); + } +} + + + +/* load_patch: + * Reads a GUS format patch file from disk. + */ +static PATCH *load_patch(PACKFILE *f, int drum) +{ + int trashtmp; + PATCH *p = NULL; + char buf[256]; + char mode; + int env_rate[6]; + int env_offset[6]; + int i, j; + int diff; + int odd_len; + + pack_fread(buf, 22, f); /* ID tag */ + if (memcmp(buf, "GF1PATCH110\0", 12) || memcmp(buf+12, "ID#000002\0", 10)) + goto getout; + + p = malloc(sizeof(PATCH)); + if (!p) { + errno = ENOMEM; + goto getout; + } + + pack_fread(buf, 65, f); /* description */ + p->master_vol = pack_igetw(f); /* volume */ + + pack_fread(buf, 109, f); /* skip */ + + p->samples = pack_getc(f); /* number of samples */ + pack_fread(buf, 40, f); /* skip */ + + if (p->samples > MAX_LAYERS) + p->samples = MAX_LAYERS; + + for (i=0; isamples; i++) { /* for each sample... */ + p->sample[i] = malloc(sizeof(SAMPLE)); + if (!p->sample[i]) { + p->samples = i; + destroy_patch(p); + p = NULL; + goto getout; + } + + p->extra[i] = malloc(sizeof(PATCH_EXTRA)); + if (!p->extra[i]) { + free(p->sample[i]); + p->samples = i; + destroy_patch(p); + p = NULL; + goto getout; + } + + pack_fread(buf, 8, f); /* layer name */ + + p->sample[i]->len = pack_igetl(f); /* sample length */ + p->sample[i]->loop_start = pack_igetl(f); /* loop start */ + p->sample[i]->loop_end = pack_igetl(f); /* loop end */ + p->sample[i]->freq = pack_igetw(f); /* sample frequency */ + + p->extra[i]->low_note = pack_igetl(f); /* key min */ + p->extra[i]->high_note = pack_igetl(f); /* key max */ + p->extra[i]->base_note = pack_igetl(f); /* base key */ + trashtmp=pack_igetw(f); /* skip finetune */ + + p->extra[i]->pan = pack_getc(f) * 255/15; /* pan position */ + + for (j=0; j<6; j++) /* envelope rate */ + env_rate[j] = pack_getc(f); + + for (j=0; j<6; j++) /* envelope value */ + env_offset[j] = pack_getc(f); + + pack_fread(buf, 6, f); /* skip trem and vib */ + + mode = pack_getc(f); /* sample flags */ + + p->sample[i]->bits = (mode & 1) ? 16 : 8; /* how many bits? */ + + p->extra[i]->play_mode = 0; /* sort out loop flags */ + + if (mode & 4) + p->extra[i]->play_mode |= PLAYMODE_LOOP; + + if (mode & 8) + p->extra[i]->play_mode |= (PLAYMODE_BIDIR | PLAYMODE_LOOP); + + if (mode & 16) + p->extra[i]->play_mode |= (PLAYMODE_BACKWARD | PLAYMODE_LOOP); + + /* convert envelope rates (GUS uses a 2.6 floating point format) */ + for (j=0; j<6; j++) { + static int vexp[4] = { 1, 8, 64, 512 }; + int e = (env_rate[j] >> 6); + int m = (env_rate[j] & 0x3F); + env_rate[j] = ((65536 * vexp[e] / ((m) ? m : 1)) >> 12); + } + + if ((mode & 32) && (!drum)) { + /* sustained volume envelope */ + p->extra[i]->sustain_level = env_offset[2]; + p->extra[i]->decay_time = 0; + + diff = env_offset[0]; + p->extra[i]->decay_time += env_rate[0] * diff / 256; + + diff = ABS(env_offset[1] - env_offset[0]); + p->extra[i]->decay_time += env_rate[1] * diff / 256; + + diff = ABS(env_offset[2] - env_offset[1]); + p->extra[i]->decay_time += env_rate[2] * diff / 256; + + j = 3; + } + else { + /* one-shot volume envelope */ + p->extra[i]->decay_time = 0; + p->extra[i]->sustain_level = 0; + + for (j=0; j<6; j++) { + diff = ABS(env_offset[j] - ((j) ? env_offset[j-1] : 0)); + p->extra[i]->decay_time += env_rate[j] * diff / 256; + if (env_offset[j] < 16) { + j++; + break; + } + } + } + + /* measure release time */ + p->extra[i]->release_time = 0; + + while (j < 6) { + diff = ABS(env_offset[j] - env_offset[j-1]); + p->extra[i]->release_time += env_rate[j] * diff / 256; + if (env_offset[j] < 16) + break; + j++; + } + + /* clamp very large/small sustain levels to zero or maximum */ + if (p->extra[i]->sustain_level < 16) + p->extra[i]->sustain_level = 0; + else if (p->extra[i]->sustain_level > 192) + p->extra[i]->sustain_level = 255; + + if (p->extra[i]->release_time < 10) + p->extra[i]->release_time = 0; + + if ((p->extra[i]->sustain_level == 0) && + (p->extra[i]->decay_time == 0)) { + p->extra[i]->sustain_level = 255; + p->extra[i]->play_mode &= ~PLAYMODE_LOOP; + } + + p->extra[i]->scale_freq = pack_igetw(f); /* scale values */ + p->extra[i]->scale_factor = pack_igetw(f); + + pack_fread(buf, 36, f); /* skip reserved */ + + if (p->sample[i]->bits == 16) { /* adjust 16 bit loops */ + odd_len = (p->sample[i]->len & 1); + p->sample[i]->len /= 2; + p->sample[i]->loop_start /= 2; + p->sample[i]->loop_end /= 2; + } + else + odd_len = FALSE; + + p->sample[i]->priority = 255; /* set some defaults */ + p->sample[i]->param = -1; + + p->sample[i]->data = malloc(p->sample[i]->len); + if (!p->sample[i]->data) { + free(p->sample[i]); + free(p->extra[i]); + p->samples = i; + destroy_patch(p); + p = NULL; + goto getout; + } + + if (p->sample[i]->bits == 8) { + /* read 8 bit sample data */ + pack_fread(p->sample[i]->data, p->sample[i]->len, f); + if (!(mode & 2)) { + /* signed data - convert to unsigned */ + for (j=0; j<(int)p->sample[i]->len; j++) + ((unsigned char *)p->sample[i]->data)[j] ^= 0x80; + } + } + else { + /* reduce 16 bits to 8 bit waveform */ + for (j=0; j < (int)p->sample[i]->len; j++) { + ((unsigned char *)p->sample[i]->data)[j] = pack_igetw(f) >> 8; + } + if (!(mode & 2)) { + /* signed data - convert to unsigned */ + for (j=0; j<(int)p->sample[i]->len; j++) + ((unsigned char *)p->sample[i]->data)[j] ^= 0x80; + } + p->sample[i]->bits = 8; + if (odd_len) + pack_getc(f); + } + } + + getout: + + /* lock the data into physical memory */ + if (p) { + _go32_dpmi_lock_data(p, sizeof(PATCH)); + + for (i=0; isamples; i++) { + lock_sample(p->sample[i]); + _go32_dpmi_lock_data(p->extra[i], sizeof(PATCH_EXTRA)); + } + } + + return p; +} + + + +/* try_patch_location: + * Looks for a GUS patch set in the specified location, storing the dir + * and config file name if found. + */ +static int try_patch_location(char *where, char *dir, char *file) +{ + /* could it be a direct .cfg file reference? */ + if (stricmp(get_extension(where), "cfg") == 0) { + if (!file_exists(where, FA_RDONLY | FA_ARCH, NULL)) + return FALSE; + strcpy(dir, where); + *get_filename(dir) = 0; + strcpy(file, get_filename(where)); + return TRUE; + } + + /* could it be a direct .dat file reference? */ + if (stricmp(get_extension(where), "dat") == 0) { + strcpy(dir, where); + strcat(dir, "#default_cfg"); + if (!file_exists(dir, FA_RDONLY | FA_ARCH, NULL)) + return FALSE; + strcpy(dir, where); + strcat(dir, "#"); + strcpy(file, "default_cfg"); + return TRUE; + } + + /* could it be a directory containing default.cfg? */ + strcpy(dir, where); + put_backslash(dir); + strcat(dir, "default.cfg"); + if (file_exists(dir, FA_RDONLY | FA_ARCH, NULL)) { + strcpy(dir, where); + put_backslash(dir); + strcpy(file, "default.cfg"); + return TRUE; + } + + /* could it be a directory containing patches.dat? */ + strcpy(dir, where); + put_backslash(dir); + strcat(dir, "patches.dat#default_cfg"); + if (file_exists(dir, FA_RDONLY | FA_ARCH, NULL)) { + strcpy(dir, where); + put_backslash(dir); + strcat(dir, "patches.dat#"); + strcpy(file, "default_cfg"); + return TRUE; + } + + /* could it be the root directory of midi/default.cfg? */ + strcpy(dir, where); + put_backslash(dir); + strcat(dir, "midi/default.cfg"); + if (file_exists(dir, FA_RDONLY | FA_ARCH, NULL)) { + strcpy(dir, where); + put_backslash(dir); + strcat(dir, "midi/"); + strcpy(file, "default.cfg"); + return TRUE; + } + + return FALSE; +} + + + +/* _digmid_find_patches: + * Tries to locate the GUS patch set directory and index file (default.cfg). + */ +int _digmid_find_patches(char *dir, char *file) +{ + char *name = get_config_string("sound", "patches", NULL); + char path[256], *s; + + /* look where the config file says */ + if ((name) && (*name)) + return try_patch_location(name, dir, file); + + /* look in the same directory as the program */ + strcpy(path, __crt0_argv[0]); + *get_filename(path) = 0; + put_backslash(path); + if (try_patch_location(path, dir, file)) + return TRUE; + + /* try the ALLEGRO environment variable */ + s = getenv("ALLEGRO"); + if (s) { + strcpy(path, s); + put_backslash(path); + if (try_patch_location(path, dir, file)) + return TRUE; + } + + /* try the ULTRASND environment variable */ + s = getenv("ULTRASND"); + if (s) { + strcpy(path, s); + put_backslash(path); + if (try_patch_location(path, dir, file)) + return TRUE; + } + + return FALSE; +} + + + +/* parse_string: + * Splits a string into component parts, storing them in the argv pointers. + * Returns the number of components. + */ +static int parse_string(char *buf, char *argv[]) +{ + int c = 0; + + while ((*buf) && (c<16)) { + while ((*buf == ' ') || (*buf == '\t') || (*buf == '=')) + buf++; + + if (*buf == '#') + return c; + + if (*buf) + argv[c++] = buf; + + while ((*buf) && (*buf != ' ') && (*buf != '\t') && (*buf != '=')) + buf++; + + if (*buf) { + *buf = 0; + buf++; + } + } + + return c; +} + + + +/* digmid_load_patches: + * Reads the patches that are required by a particular song. + */ +static int digmid_load_patches(char *patches, char *drums) +{ + PACKFILE *f; + char dir[256], file[256], buf[256], filename[256]; + char todo[256][16]; + char *argv[16]; + int argc; + int patchnum, flag_num; + int drum_mode = FALSE; + int override_mode = FALSE; + int drum_start = 0; +#if 0 + int type, size; +#endif + int i, j; + + if (!_digmid_find_patches(dir, file)) + return -1; + + for (i=0; i<256; i++) + todo[i][0] = 0; + + strcpy(buf, dir); + strcat(buf, file); + f = pack_fopen(buf, F_READ); + if (!f) + return -1; + + while (pack_fgets(buf, 255, f) != 0) { + argc = parse_string(buf, argv); + + if (argc > 0) { + /* is first word all digits? */ + flag_num = TRUE; + for (i=0; i<(int)strlen(argv[0]); i++) { + if ((!isdigit(argv[0][i])) && (argv[0][i] != '-')) { + flag_num = FALSE; + break; + } + } + + if ((flag_num) && (argc >= 2)) { + if (stricmp(argv[1], "begin_multipatch") == 0) { + /* start the block of percussion instruments */ + drum_start = atoi(argv[0])-1; + drum_mode = TRUE; + } + else if (stricmp(argv[1], "override_patch") == 0) { + /* ignore patch overrides */ + override_mode = TRUE; + } + else if (!override_mode) { + /* must be a patch number */ + patchnum = atoi(argv[0]); + + if (!drum_mode) + patchnum--; + + if ((patchnum >= 0) && (patchnum < 128) && + (((drum_mode) && (drums[patchnum])) || + ((!drum_mode) && (patches[patchnum])))) { + + if (drum_mode) + patchnum += drum_start; + + if (!patch[patchnum]) { + /* need to load this sample */ + strncpy(todo[patchnum], argv[1], 15); + todo[patchnum][15] = 0; + } + } + } + } + else { + /* handle other keywords */ + if (stricmp(argv[0], "end_multipatch") == 0) { + drum_mode = FALSE; + override_mode = FALSE; + } + } + } + } + + pack_fclose(f); + +#if 0 + if ((dir[0]) && (dir[strlen(dir)-1] == '#')) { + /* read from a datafile */ + dir[strlen(dir)-1] = 0; + f = pack_fopen(dir, F_READ_PACKED); + if (!f) + return -1; + + type = pack_mgetl(f); + if (type != DAT_MAGIC) { + pack_fclose(f); + return -1; + } + + pack_mgetl(f); + + filename[0] = 0; + + /* scan through the file */ + while (!pack_feof(f)) { + type = pack_mgetl(f); + + if (type == DAT_PROPERTY) { + type = pack_mgetl(f); + size = pack_mgetl(f); + if (type == DAT_ID('N','A','M','E')) { + /* store name property */ + pack_fread(filename, size, f); + filename[size] = 0; + } + else { + /* skip other properties */ + pack_fseek(f, size); + } + } + else if (type == DAT_PATCH) { + /* do we want this patch? */ + for (i=0; i<256; i++) + if ((todo[i][0]) && (stricmp(filename, todo[i]) == 0)) + break; + + if (i < 256) { + /* load this patch */ + f = pack_fopen_chunk(f, FALSE); + patch[i] = load_patch(f, (i >= 128)); + f = pack_fclose_chunk(f); + for (j=i+1; j<256; j++) { + /* share multiple copies of the instrument */ + if (stricmp(todo[i], todo[j]) == 0) { + patch[j] = patch[i]; + todo[j][0] = 0; + } + } + todo[i][0] = 0; + } + else { + /* skip unwanted patch */ + size = pack_mgetl(f); + pack_fseek(f, size+4); + } + } + else { + /* skip unwanted object */ + size = pack_mgetl(f); + pack_fseek(f, size+4); + } + } + } + else +#endif + { + /* read from regular disk files */ + for (i=0; i<256; i++) { + if (todo[i][0]) { + strcpy(filename, dir); + strcat(filename, todo[i]); + if (*get_extension(filename) == 0) + strcat(filename, ".pat"); + f = pack_fopen(filename, F_READ); + if (f) { + patch[i] = load_patch(f, (i >= 128)); + pack_fclose(f); + } + errno = 0; + for (j=i+1; j<256; j++) { + /* share multiple copies of the instrument */ + if (stricmp(todo[i], todo[j]) == 0) { + patch[j] = patch[i]; + todo[j][0] = 0; + } + } + } + } + } + + return 0; +} + + + +/* digmid_freq: + * Helper for converting note numbers to sample frequencies. + */ +static inline int digmid_freq(int inst, SAMPLE *s, PATCH_EXTRA *e, int note, int bend) +{ + float freq, f1, f2; + float sfreq = s->freq; + float base_note = e->base_note; + + if (inst > 127) { + /* drums use a fixed frequency */ + freq = ftbl[inst-128] * sfreq / base_note; + } + else { + /* calculate frequency */ + f1 = ftbl[note] * sfreq / base_note; + f2 = ftbl[note+1] * sfreq / base_note; + + /* quick pitch bend method - ~.035% error - acceptable? */ + freq = ((f1*(float)(4096-bend)) + (f2*(float)bend)) / 4096.0; + } + + /* frequency scaling */ + if (e->scale_factor != 1024) { + f1 = sfreq * e->scale_freq / 60; + freq -= f1; + freq = (freq * e->scale_factor) / 1024; + freq += f1; + } + + /* lower by an octave if we are going to overflow */ + while (freq >= (1<<19)-1) + freq /= 2; + + return (int)(freq+0.5); +} + + + +/* digmid_trigger: + * Helper for activating a specific sample layer. + */ +static inline void digmid_trigger(int inst, int snum, int note, int bend, int vol, int pan) +{ + int freq, voice; + DIGMID_VOICE *info; + PATCH_EXTRA *e; + SAMPLE *s; + + voice = _midi_allocate_voice(-1, -1); + if (voice < 0) + return; + + s = patch[inst]->sample[snum]; + e = patch[inst]->extra[snum]; + + freq = digmid_freq(inst, s, e, note, bend); + + if (inst > 127) + pan = e->pan; + + /* store note information for later use */ + info = &digmid_voice[voice - midi_digmid.basevoice]; + info->s = s; + info->e = e; + info->inst = inst; + info->vol = vol; + + /* play the note */ + reallocate_voice(voice, s); + voice_set_playmode(voice, e->play_mode); + voice_set_volume(voice, vol); + voice_set_frequency(voice, freq); + voice_set_pan(voice, pan); + + if (e->sustain_level < 255) + voice_ramp_volume(voice, e->decay_time, e->sustain_level*vol/255); + + voice_start(voice); +} + + + +/* digmid_key_on: + * Triggers the specified voice. The instrument is specified as a GM + * patch number, pitch as a midi note number, and volume from 0-127. + * The bend parameter is _not_ expressed as a midi pitch bend value. + * It ranges from 0 (no pitch change) to 0xFFF (almost a semitone sharp). + * Drum sounds are indicated by passing an instrument number greater than + * 128, in which case the sound is GM percussion key #(inst-128). + */ +static void digmid_key_on(int inst, int note, int bend, int vol, int pan) +{ + PATCH_EXTRA *e; + float freq; + int best, best_diff; + int diff; + int i, c; + + /* quit if instrument is not available */ + if ((!patch[inst]) || (patch[inst]->samples < 1)) + return; + + /* adjust volume and pan ranges */ + vol *= 2; + pan *= 2; + + if (patch[inst]->samples == 1) { + /* only one sample to choose from */ + digmid_trigger(inst, 0, note, bend, vol, pan); + } + else { + /* find the sample(s) with best frequency range */ + best = -1; + best_diff = INT_MAX; + c = 0; + + for (i=0; isamples; i++) { + freq = ftbl[note]; + e = patch[inst]->extra[i]; + + if ((freq >= e->low_note) && (freq <= e->high_note)) { + digmid_trigger(inst, i, note, bend, vol, pan); + c++; + if (c > 4) + break; + } + else { + diff = MIN(ABS(freq - e->low_note), ABS(freq - e->high_note)); + if (diff < best_diff) { + best_diff = diff; + best = i; + } + } + } + + if ((c <= 0) && (best >= 0)) + digmid_trigger(inst, best, note, bend, vol, pan); + } +} + +static END_OF_FUNCTION(digmid_key_on); + + + +/* digmid_key_off: + * Hey, guess what this does :-) + */ +static void digmid_key_off(int voice) +{ + DIGMID_VOICE *info = &digmid_voice[voice - midi_digmid.basevoice]; + + if (info->inst > 127) + return; + + if (info->e->release_time > 0) + voice_ramp_volume(voice, info->e->release_time, 0); + else + voice_stop(voice); +} + +static END_OF_FUNCTION(digmid_key_off); + + + +/* digmid_set_volume: + * Sets the volume of the specified voice (vol range 0-127). + */ +static void digmid_set_volume(int voice, int vol) +{ + DIGMID_VOICE *info = &digmid_voice[voice - midi_digmid.basevoice]; + int v; + + if (info->inst > 127) + return; + + vol *= 2; + + if (info->e->sustain_level < 255) { + /* adjust for volume ramping */ + int current = voice_get_volume(voice); + int target = info->e->sustain_level*info->vol/255; + int start = info->vol; + + if (ABS(current - target) < 8) { + /* ramp has finished */ + voice_set_volume(voice, vol*info->e->sustain_level/255); + } + else { + /* in the middle of a ramp */ + int mu; + + if (start > target) + mu = MID(0, (current-target) * 256 / (start-target), 256); + else + mu = 0; + + v = mu+info->e->sustain_level*(256-mu)/256; + v = MID(0, vol*v/255, 255); + + voice_set_volume(voice, v); + voice_ramp_volume(voice, info->e->decay_time*mu/256, info->e->sustain_level*vol/255); + } + } + else { + /* no ramp */ + voice_set_volume(voice, vol); + } + + info->vol = vol; +} + +static END_OF_FUNCTION(digmid_set_volume); + + + +/* digmid_set_pitch: + * Sets the pitch of the specified voice. + */ +static void digmid_set_pitch(int voice, int note, int bend) +{ + DIGMID_VOICE *info = &digmid_voice[voice - midi_digmid.basevoice]; + int freq; + + if (info->inst > 127) + return; + + freq = digmid_freq(info->inst, info->s, info->e, note, bend); + + voice_set_frequency(voice, freq); +} + +static END_OF_FUNCTION(digmid_set_pitch); + + + +/* digmid_detect: + * Have we got a sensible looking patch set? + */ +static int digmid_detect() +{ + char dir[256], file[256]; + + if (!_digmid_find_patches(dir, file)) { + strcpy(allegro_error, "DIGMID patch set not found"); + return FALSE; + } + + return TRUE; +} + + + +/* digmid_init: + * Setup the digmid driver. + */ +static int digmid_init(int voices) +{ + int i; + + for (i=0; i<256; i++) + patch[i] = NULL; + + midi_digmid.voices = voices; + + /* create frequency table */ + ftbl[129] = 14080000; /* A10 = 14080.000 hz */ + for (i=128; i>=0; i--) + ftbl[i] = ftbl[i+1] / pow(2.0, 1.0/12.0); + + LOCK_VARIABLE(midi_digmid); + LOCK_VARIABLE(patch); + LOCK_VARIABLE(ftbl); + LOCK_VARIABLE(digmid_voice); + LOCK_FUNCTION(digmid_key_on); + LOCK_FUNCTION(digmid_key_off); + LOCK_FUNCTION(digmid_set_volume); + LOCK_FUNCTION(digmid_set_pitch); + + return 0; +} + + + +/* digmid_exit: + * Cleanup when we are finished. + */ +static void digmid_exit() +{ + int i, j; + + for (i=0; i<256; i++) { + if (patch[i]) { + for (j=i+1; j<256; j++) { + if (patch[j] == patch[i]) + patch[j] = NULL; + } + destroy_patch(patch[i]); + patch[i] = NULL; + } + } +} + + diff --git a/arch/dos/allg_snd/sound/drv/adlib.c b/arch/dos/allg_snd/sound/drv/adlib.c new file mode 100644 index 00000000..e8ff8d30 --- /dev/null +++ b/arch/dos/allg_snd/sound/drv/adlib.c @@ -0,0 +1,872 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * By Shawn Hargreaves, + * 1 Salisbury Road, + * Market Drayton, + * Shropshire, + * England, TF9 1AJ. + * + * Adlib/FM driver for the MIDI player. + * + * See readme.txt for copyright information. + */ + + +#ifndef DJGPP +#error This file should only be used by the djgpp version of Allegro +#endif + +#include +#include +#include + +#include "allegro.h" +#include "internal.h" + + +/* external interface to the Adlib driver */ +static int fm_detect(); +static int fm_init(int voices); +static void fm_exit(); +static int fm_mixer_volume(int volume); +static int fm_load_patches(char *patches, char *drums); +static void fm_key_on(int inst, int note, int bend, int vol, int pan); +static void fm_key_off(int voice); +static void fm_set_volume(int voice, int vol); +static void fm_set_pitch(int voice, int note, int bend); + +static char adlib_desc[80] = "not initialised"; + + +MIDI_DRIVER midi_adlib = +{ + "Adlib", + adlib_desc, + 0, 0, 0, 0, -1, -1, + fm_detect, + fm_init, + fm_exit, + fm_mixer_volume, + NULL, + fm_load_patches, + _dummy_adjust_patches, + fm_key_on, + fm_key_off, + fm_set_volume, + fm_set_pitch, + _dummy_noop2, + _dummy_noop2 +}; + + +typedef struct FM_INSTRUMENT +{ + unsigned char characteristic1; + unsigned char characteristic2; + unsigned char level1; + unsigned char level2; + unsigned char attackdecay1; + unsigned char attackdecay2; + unsigned char sustainrelease1; + unsigned char sustainrelease2; + unsigned char wave1; + unsigned char wave2; + unsigned char feedback; + unsigned char freq; + unsigned char key; + unsigned char type; +} FM_INSTRUMENT; + + +#define FM_HH 1 +#define FM_CY 2 +#define FM_TT 4 +#define FM_SD 8 +#define FM_BD 16 + + +/* include the GM patch set (static data) */ +#include "fm_instr.h" + + +/* is the OPL in percussion mode? */ +static int fm_drum_mode = FALSE; + +/* delays when writing to OPL registers */ +static int fm_delay_1 = 6; +static int fm_delay_2 = 35; + +/* register offsets for each voice */ +static int fm_offset[18] = { + 0x000, 0x001, 0x002, 0x008, 0x009, 0x00A, 0x010, 0x011, 0x012, + 0x100, 0x101, 0x102, 0x108, 0x109, 0x10A, 0x110, 0x111, 0x112 +}; + +/* for converting midi note numbers to FM frequencies */ +static int fm_freq[13] = { + 0x157, 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, + 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287, 0x2AE +}; + +/* logarithmic relationship between midi and FM volumes */ +static int fm_vol_table[128] = { + 0, 11, 16, 19, 22, 25, 27, 29, 32, 33, 35, 37, 39, 40, 42, 43, + 45, 46, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 64, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, + 78, 79, 80, 80, 81, 82, 83, 83, 84, 85, 86, 86, 87, 88, 89, 89, + 90, 91, 91, 92, 93, 93, 94, 95, 96, 96, 97, 97, 98, 99, 99, 100, + 101, 101, 102, 103, 103, 104, 104, 105, 106, 106, 107, 107, 108, + 109, 109, 110, 110, 111, 112, 112, 113, 113, 114, 114, 115, 115, + 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, + 123, 123, 124, 124, 125, 125, 126, 126, 127 +}; + +/* drum channel tables: BD SD TT CY HH */ +static int fm_drum_channel[] = { 6, 7, 8, 8, 7 }; +static int fm_drum_op1[] = { TRUE, FALSE, TRUE, FALSE, TRUE }; +static int fm_drum_op2[] = { TRUE, TRUE, FALSE, TRUE, FALSE }; +static int fm_drum_pitch[] = { TRUE, TRUE, TRUE, FALSE, FALSE }; + +/* cached information about the state of the drum channels */ +static FM_INSTRUMENT *fm_drum_cached_inst1[5]; +static FM_INSTRUMENT *fm_drum_cached_inst2[5]; +static int fm_drum_cached_vol1[5]; +static int fm_drum_cached_vol2[5]; +static long fm_drum_cached_time[5]; + +/* various bits of information about the current state of the FM chip */ +static unsigned char fm_drum_mask; +static unsigned char fm_key[18]; +static unsigned char fm_keyscale[18]; +static unsigned char fm_feedback[18]; +static int fm_level[18]; +static int fm_patch[18]; + +#define VOICE_OFFSET(x) ((x < 9) ? x : 0x100+x-9) + + + +/* fm_write: + * Writes a byte to the specified register on the FM chip. + */ +static void fm_write(int reg, unsigned char data) +{ + int i; + int port = (reg & 0x100) ? _fm_port+2 : _fm_port; + + outportb(port, reg & 0xFF); /* write the register */ + + for (i=0; i0; i--) + fm_write(i, 0); + + if (midi_card == MIDI_OPL3) { /* if we have an OPL3... */ + fm_delay_1 = 1; + fm_delay_2 = 2; + + fm_write(0x105, 1); /* enable OPL3 mode */ + + for (i=0x1F5; i>0x105; i--) + fm_write(i, 0); + + for (i=0x104; i>0x100; i--) + fm_write(i, 0); + + if (!enable) + fm_write(0x105, 0); /* turn OPL3 mode off again */ + } + else { + fm_delay_1 = 6; + fm_delay_2 = 35; + + if (midi_card == MIDI_2XOPL2) { /* if we have a second OPL2... */ + for (i=0x1F5; i>0x100; i--) + fm_write(i, 0); + + fm_write(0x101, 0x20); + fm_write(0x1BD, 0xC0); + } + } + + for (i=0; ilevel2 & 0xC0; + fm_level[voice] = 63 - (inst->level2 & 63); + fm_feedback[voice] = inst->feedback; + + /* write the new data */ + fm_write(0x20+fm_offset[voice], inst->characteristic1); + fm_write(0x23+fm_offset[voice], inst->characteristic2); + fm_write(0x60+fm_offset[voice], inst->attackdecay1); + fm_write(0x63+fm_offset[voice], inst->attackdecay2); + fm_write(0x80+fm_offset[voice], inst->sustainrelease1); + fm_write(0x83+fm_offset[voice], inst->sustainrelease2); + fm_write(0xE0+fm_offset[voice], inst->wave1); + fm_write(0xE3+fm_offset[voice], inst->wave2); + + /* don't set operator1 level for additive synthesis sounds */ + if (!(inst->feedback & 1)) + fm_write(0x40+fm_offset[voice], inst->level1); + + /* on OPL3, 0xC0 contains pan info, so don't set it until fm_key_on() */ + if (midi_card != MIDI_OPL3) + fm_write(0xC0+VOICE_OFFSET(voice), inst->feedback); +} + + + +/* fm_set_drum_op1: + * Sets the sound for operator #1 of a drum channel. + */ +static inline void fm_set_drum_op1(int voice, FM_INSTRUMENT *inst) +{ + fm_write(0x20+fm_offset[voice], inst->characteristic1); + fm_write(0x60+fm_offset[voice], inst->attackdecay1); + fm_write(0x80+fm_offset[voice], inst->sustainrelease1); + fm_write(0xE0+fm_offset[voice], inst->wave1); +} + + + +/* fm_set_drum_op2: + * Sets the sound for operator #2 of a drum channel. + */ +static inline void fm_set_drum_op2(int voice, FM_INSTRUMENT *inst) +{ + fm_write(0x23+fm_offset[voice], inst->characteristic2); + fm_write(0x63+fm_offset[voice], inst->attackdecay2); + fm_write(0x83+fm_offset[voice], inst->sustainrelease2); + fm_write(0xE3+fm_offset[voice], inst->wave2); +} + + + +/* fm_set_drum_vol_op1: + * Sets the volume for operator #1 of a drum channel. + */ +static inline void fm_set_drum_vol_op1(int voice, int vol) +{ + vol = 63 * fm_vol_table[vol] / 128; + fm_write(0x40+fm_offset[voice], (63-vol)); +} + + + +/* fm_set_drum_vol_op2: + * Sets the volume for operator #2 of a drum channel. + */ +static inline void fm_set_drum_vol_op2(int voice, int vol) +{ + vol = 63 * fm_vol_table[vol] / 128; + fm_write(0x43+fm_offset[voice], (63-vol)); +} + + + +/* fm_set_drum_pitch: + * Sets the pitch of a drum channel. + */ +static inline void fm_set_drum_pitch(int voice, FM_INSTRUMENT *drum) +{ + fm_write(0xA0+VOICE_OFFSET(voice), drum->freq); + fm_write(0xB0+VOICE_OFFSET(voice), drum->key & 0x1F); +} + + + +/* fm_trigger_drum: + * Triggers a note on a drum channel. + */ +static inline void fm_trigger_drum(int inst, int vol) +{ + FM_INSTRUMENT *drum = fm_drum+inst; + int d; + + if (!fm_drum_mode) + fm_set_drum_mode(TRUE); + + if (drum->type == FM_BD) + d = 0; + else if (drum->type == FM_SD) + d = 1; + else if (drum->type == FM_TT) + d = 2; + else if (drum->type == FM_CY) + d = 3; + else + d = 4; + + /* don't let drum sounds come too close together */ + if (fm_drum_cached_time[d] == _midi_tick) + return; + + fm_drum_cached_time[d] = _midi_tick; + + fm_drum_mask &= (~drum->type); + fm_write(0xBD, fm_drum_mask); + + vol = vol*3/4; + + if (fm_drum_op1[d]) { + if (fm_drum_cached_inst1[d] != drum) { + fm_drum_cached_inst1[d] = drum; + fm_set_drum_op1(fm_drum_channel[d], drum); + } + + if (fm_drum_cached_vol1[d] != vol) { + fm_drum_cached_vol1[d] = vol; + fm_set_drum_vol_op1(fm_drum_channel[d], vol); + } + } + + if (fm_drum_op2[d]) { + if (fm_drum_cached_inst2[d] != drum) { + fm_drum_cached_inst2[d] = drum; + fm_set_drum_op2(fm_drum_channel[d], drum); + } + + if (fm_drum_cached_vol2[d] != vol) { + fm_drum_cached_vol2[d] = vol; + fm_set_drum_vol_op2(fm_drum_channel[d], vol); + } + } + + fm_set_drum_pitch(fm_drum_channel[d], drum); + + fm_drum_mask |= drum->type; + fm_write(0xBD, fm_drum_mask); +} + + + +/* fm_key_on: + * Triggers the specified voice. The instrument is specified as a GM + * patch number, pitch as a midi note number, and volume from 0-127. + * The bend parameter is _not_ expressed as a midi pitch bend value. + * It ranges from 0 (no pitch change) to 0xFFF (almost a semitone sharp). + * Drum sounds are indicated by passing an instrument number greater than + * 128, in which case the sound is GM percussion key #(inst-128). + */ +static void fm_key_on(int inst, int note, int bend, int vol, int pan) +{ + int voice; + + if (inst > 127) { /* drum sound? */ + inst -= 163; + if (inst < 0) + inst = 0; + else if (inst > 46) + inst = 46; + + fm_trigger_drum(inst, vol); + } + else { /* regular instrument */ + if (midi_card == MIDI_2XOPL2) { + /* the SB Pro-1 has fixed pan positions per voice... */ + if (pan < 64) + voice = _midi_allocate_voice(0, 5); + else + voice = _midi_allocate_voice(9, midi_driver->voices-1); + } + else + /* on other cards we can use any voices */ + voice = _midi_allocate_voice(-1, -1); + + if (voice < 0) + return; + + /* make sure the voice isn't sounding */ + fm_write(0x43+fm_offset[voice], 63); + if (fm_feedback[voice] & 1) + fm_write(0x40+fm_offset[voice], 63); + + /* make sure the voice is set up with the right sound */ + if (inst != fm_patch[voice]) { + fm_set_voice(voice, fm_instrument+inst); + fm_patch[voice] = inst; + } + + /* set pan position */ + if (midi_card == MIDI_OPL3) { + if (pan < 48) + pan = 0x10; + else if (pan >= 80) + pan = 0x20; + else + pan = 0x30; + + fm_write(0xC0+VOICE_OFFSET(voice), pan | fm_feedback[voice]); + } + + /* and play the note */ + fm_set_pitch(voice, note, bend); + fm_set_volume(voice, vol); + } +} + +static END_OF_FUNCTION(fm_key_on); + + + +/* fm_key_off: + * Hey, guess what this does :-) + */ +static void fm_key_off(int voice) +{ + fm_write(0xB0+VOICE_OFFSET(voice), fm_key[voice] & 0xDF); +} + +static END_OF_FUNCTION(fm_key_off); + + + +/* fm_set_volume: + * Sets the volume of the specified voice (vol range 0-127). + */ +static void fm_set_volume(int voice, int vol) +{ + vol = fm_level[voice] * fm_vol_table[vol] / 128; + fm_write(0x43+fm_offset[voice], (63-vol) | fm_keyscale[voice]); + if (fm_feedback[voice] & 1) + fm_write(0x40+fm_offset[voice], (63-vol) | fm_keyscale[voice]); +} + +static END_OF_FUNCTION(fm_set_volume); + + + +/* fm_set_pitch: + * Sets the pitch of the specified voice. + */ +static void fm_set_pitch(int voice, int note, int bend) +{ + int oct = 1; + int freq; + + note -= 24; + while (note >= 12) { + note -= 12; + oct++; + } + + freq = fm_freq[note]; + if (bend) + freq += (fm_freq[note+1] - fm_freq[note]) * bend / 0x1000; + + fm_key[voice] = (oct<<2) | (freq >> 8); + + fm_write(0xA0+VOICE_OFFSET(voice), freq & 0xFF); + fm_write(0xB0+VOICE_OFFSET(voice), fm_key[voice] | 0x20); +} + +static END_OF_FUNCTION(fm_set_pitch); + + + +/* fm_load_patches: + * Called before starting to play a MIDI file, to check if we need to be + * in rhythm mode or not. + */ +static int fm_load_patches(char *patches, char *drums) +{ + int i; + int usedrums = FALSE; + + for (i=6; i<9; i++) { + fm_key[i] = 0; + fm_keyscale[i] = 0; + fm_feedback[i] = 0; + fm_level[i] = 0; + fm_patch[i] = -1; + fm_write(0x40+fm_offset[i], 63); + fm_write(0x43+fm_offset[i], 63); + } + + for (i=0; i<5; i++) { + fm_drum_cached_inst1[i] = NULL; + fm_drum_cached_inst2[i] = NULL; + fm_drum_cached_vol1[i] = -1; + fm_drum_cached_vol2[i] = -1; + fm_drum_cached_time[i] = 0; + } + + for (i=0; i<128; i++) { + if (drums[i]) { + usedrums = TRUE; + break; + } + } + + fm_set_drum_mode(usedrums); + + return 0; +} + +static END_OF_FUNCTION(fm_load_patches); + + + +/* fm_mixer_volume: + * For SB-Pro cards, sets the mixer volume for FM output. + */ +static int fm_mixer_volume(int volume) +{ + return _sb_set_mixer(-1, volume); +} + + + +/* fm_is_there: + * Checks for the presence of an OPL synth at the current port. + */ +static int fm_is_there() +{ + fm_write(1, 0); /* init test register */ + + fm_write(4, 0x60); /* reset both timers */ + fm_write(4, 0x80); /* enable interrupts */ + + if (inportb(_fm_port) & 0xE0) + return FALSE; + + fm_write(2, 0xFF); /* write 0xFF to timer 1 */ + fm_write(4, 0x21); /* start timer 1 */ + + rest(100); + + if ((inportb(_fm_port) & 0xE0) != 0xC0) + return FALSE; + + fm_write(4, 0x60); /* reset both timers */ + fm_write(4, 0x80); /* enable interrupts */ + + return TRUE; +} + + + +/* fm_detect: + * Adlib detection routine. + */ +static int fm_detect() +{ + static int ports[] = + { 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x388, 0 }; + int i; + char *s; + int opl_type; + + if (_fm_port < 0) { + if (midi_card == MIDI_OPL2) { + _fm_port = 0x388; + if (fm_is_there()) + goto found_it; + } + + for (i=0; ports[i]; i++) { /* find the card */ + _fm_port = ports[i]; + if (fm_is_there()) + goto found_it; + } + } + + if (!fm_is_there()) { + strcpy(allegro_error, "OPL synth not found"); + return FALSE; + } + + found_it: + + if ((inportb(_fm_port) & 6) == 0) { /* check for OPL3 */ + opl_type = MIDI_OPL3; + _sb_read_dsp_version(); + } + else { /* check for second OPL2 */ + if (_sb_read_dsp_version() >= 0x300) + opl_type = MIDI_2XOPL2; + else + opl_type = MIDI_OPL2; + } + + if (midi_card == MIDI_OPL3) { + if (opl_type != MIDI_OPL3) { + strcpy(allegro_error, "OPL3 synth not found"); + return FALSE; + } + } + else if (midi_card == MIDI_2XOPL2) { + if (opl_type != MIDI_2XOPL2) { + strcpy(allegro_error, "Second OPL2 synth not found"); + return FALSE; + } + } + else if (midi_card != MIDI_OPL2) + midi_card = opl_type; + + if (midi_card == MIDI_OPL2) + s = "OPL2 synth"; + else if (midi_card == MIDI_2XOPL2) + s = "Dual OPL2 synths"; + else + s = "OPL3 synth"; + + sprintf(adlib_desc, "%s on port %X", s, _fm_port); + + midi_adlib.voices = (midi_card == MIDI_OPL2) ? 9 : 18; + midi_adlib.def_voices = midi_adlib.max_voices = midi_adlib.voices; + + return TRUE; +} + + + +/* load_ibk: + * Reads in a .IBK patch set file, for use by the Adlib driver. + */ +int load_ibk(char *filename, int drums) +{ + char sig[4]; + FM_INSTRUMENT *inst; + int c, note, oct, skip, count; + + PACKFILE *f = pack_fopen(filename, F_READ); + if (!f) + return -1; + + pack_fread(sig, 4, f); + if (memcmp(sig, "IBK\x1A", 4) != 0) { + pack_fclose(f); + return -1; + } + + if (drums) { + inst = fm_drum; + skip = 35; + count = 47; + } + else { + inst = fm_instrument; + skip = 0; + count = 128; + } + + for (c=0; ccharacteristic1 = pack_getc(f); + inst->characteristic2 = pack_getc(f); + inst->level1 = pack_getc(f); + inst->level2 = pack_getc(f); + inst->attackdecay1 = pack_getc(f); + inst->attackdecay2 = pack_getc(f); + inst->sustainrelease1 = pack_getc(f); + inst->sustainrelease2 = pack_getc(f); + inst->wave1 = pack_getc(f); + inst->wave2 = pack_getc(f); + inst->feedback = pack_getc(f); + + if (drums) { + switch (pack_getc(f)) { + case 6: inst->type = FM_BD; break; + case 7: inst->type = FM_HH; break; + case 8: inst->type = FM_TT; break; + case 9: inst->type = FM_SD; break; + case 10: inst->type = FM_CY; break; + default: inst->type = 0; break; + } + + pack_getc(f); + + note = pack_getc(f) - 24; + oct = 1; + + while (note >= 12) { + note -= 12; + oct++; + } + + inst->freq = fm_freq[note]; + inst->key = (oct<<2) | (fm_freq[note] >> 8); + } + else { + inst->type = 0; + inst->freq = 0; + inst->key = 0; + + pack_getc(f); + pack_getc(f); + pack_getc(f); + } + + pack_getc(f); + pack_getc(f); + + inst++; + } + + pack_fclose(f); + return 0; +} + + + +/* fm_init: + * Setup the adlib driver. + */ +static int fm_init(int voices) +{ + char *s; + int i; + + fm_reset(1); + + for (i=0; i<2; i++) { + s = get_config_string("sound", ((i == 0) ? "ibk_file" : "ibk_drum_file"), NULL); + if ((s) && (s[0])) { + if (load_ibk(s, (i > 0)) != 0) { + sprintf(allegro_error, "Error reading .IBK file '%s'", s); + return -1; + } + } + } + + LOCK_VARIABLE(midi_adlib); + LOCK_VARIABLE(fm_instrument); + LOCK_VARIABLE(fm_drum); + LOCK_VARIABLE(_fm_port); + LOCK_VARIABLE(fm_offset); + LOCK_VARIABLE(fm_freq); + LOCK_VARIABLE(fm_vol_table); + LOCK_VARIABLE(fm_drum_channel); + LOCK_VARIABLE(fm_drum_op1); + LOCK_VARIABLE(fm_drum_op2); + LOCK_VARIABLE(fm_drum_pitch); + LOCK_VARIABLE(fm_drum_cached_inst1); + LOCK_VARIABLE(fm_drum_cached_inst2); + LOCK_VARIABLE(fm_drum_cached_vol1); + LOCK_VARIABLE(fm_drum_cached_vol2); + LOCK_VARIABLE(fm_drum_cached_time); + LOCK_VARIABLE(fm_drum_mask); + LOCK_VARIABLE(fm_drum_mode); + LOCK_VARIABLE(fm_key); + LOCK_VARIABLE(fm_keyscale); + LOCK_VARIABLE(fm_feedback); + LOCK_VARIABLE(fm_level); + LOCK_VARIABLE(fm_patch); + LOCK_VARIABLE(fm_delay_1); + LOCK_VARIABLE(fm_delay_2); + LOCK_FUNCTION(fm_write); + LOCK_FUNCTION(fm_reset); + LOCK_FUNCTION(fm_set_drum_mode); + LOCK_FUNCTION(fm_key_on); + LOCK_FUNCTION(fm_key_off); + LOCK_FUNCTION(fm_set_volume); + LOCK_FUNCTION(fm_set_pitch); + LOCK_FUNCTION(fm_load_patches); + + return 0; +} + + + +/* fm_exit: + * Cleanup when we are finished. + */ +static void fm_exit() +{ + fm_reset(0); +} + diff --git a/arch/dos/allg_snd/sound/drv/awedata.c b/arch/dos/allg_snd/sound/drv/awedata.c new file mode 100644 index 00000000..033e861a --- /dev/null +++ b/arch/dos/allg_snd/sound/drv/awedata.c @@ -0,0 +1,1848 @@ +/*-------------------------------------------------------------------------- + * awedata.c - static SoundFont data + *-------------------------------------------------------------------------- + * This file was created automatically from SoundFont data by use of the + * write_sf_embedded function in readsfnt.c. + */ + +short int _awe_sf_defaults[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 13500, 0, 0, 0, 0, 0, 0, 0, + 109, 0, 0, 0, 0, -12000, -725, -12000, + -15600, -12000, -8800, -12000, -12000, 1000, -12000, 0, + 0, -12000, -12000, -6772, -6772, 1000, -12000, 0, + 0, -1, 0, 32512, 32512, 0, -1, -1, + 0, 0, 0, 0, 0, 0, 0, 0, + 100, 0, -1 +}; + +int _awe_sf_num_presets = 129; + +short int _awe_sf_presets[] = { + 0, 0, 8, + 1, 0, 8, + 2, 0, 6, + 3, 0, 16, + 4, 0, 8, + 5, 0, 2, + 6, 0, 5, + 7, 0, 2, + 8, 0, 3, + 9, 0, 4, + 10, 0, 6, + 11, 0, 3, + 12, 0, 2, + 13, 0, 2, + 14, 0, 1, + 15, 0, 2, + 16, 0, 4, + 17, 0, 3, + 18, 0, 5, + 19, 0, 5, + 20, 0, 5, + 21, 0, 6, + 22, 0, 2, + 23, 0, 5, + 24, 0, 4, + 25, 0, 3, + 26, 0, 4, + 27, 0, 2, + 28, 0, 2, + 29, 0, 6, + 30, 0, 5, + 31, 0, 2, + 32, 0, 3, + 33, 0, 3, + 34, 0, 3, + 35, 0, 3, + 36, 0, 3, + 37, 0, 3, + 38, 0, 5, + 39, 0, 6, + 40, 0, 6, + 41, 0, 6, + 42, 0, 3, + 43, 0, 3, + 44, 0, 4, + 45, 0, 2, + 46, 0, 2, + 47, 0, 8, + 48, 0, 4, + 49, 0, 4, + 50, 0, 2, + 51, 0, 4, + 52, 0, 4, + 53, 0, 4, + 54, 0, 2, + 55, 0, 2, + 56, 0, 6, + 57, 0, 5, + 58, 0, 3, + 59, 0, 3, + 60, 0, 2, + 61, 0, 6, + 62, 0, 2, + 63, 0, 2, + 64, 0, 8, + 65, 0, 8, + 66, 0, 8, + 67, 0, 7, + 68, 0, 4, + 69, 0, 2, + 70, 0, 3, + 71, 0, 3, + 72, 0, 4, + 73, 0, 4, + 74, 0, 2, + 75, 0, 4, + 76, 0, 4, + 77, 0, 2, + 78, 0, 2, + 79, 0, 2, + 80, 0, 4, + 81, 0, 4, + 82, 0, 4, + 83, 0, 4, + 84, 0, 4, + 85, 0, 4, + 86, 0, 4, + 87, 0, 5, + 88, 0, 4, + 89, 0, 2, + 90, 0, 4, + 91, 0, 4, + 92, 0, 4, + 93, 0, 8, + 94, 0, 4, + 95, 0, 2, + 96, 0, 3, + 97, 0, 4, + 98, 0, 4, + 99, 0, 5, + 100, 0, 4, + 101, 0, 4, + 102, 0, 4, + 103, 0, 3, + 104, 0, 2, + 105, 0, 3, + 106, 0, 5, + 107, 0, 2, + 108, 0, 4, + 109, 0, 4, + 110, 0, 6, + 111, 0, 2, + 112, 0, 4, + 113, 0, 4, + 114, 0, 2, + 115, 0, 2, + 116, 0, 3, + 117, 0, 2, + 118, 0, 4, + 119, 0, 2, + 120, 0, 2, + 121, 0, 2, + 122, 0, 4, + 123, 0, 4, + 124, 0, 4, + 125, 0, 4, + 126, 0, 4, + 127, 0, 4, + 0, 128, 68 +}; + +short int _awe_sf_splits[] = { +/* 0 */ + 11, 12, 12, 12, 12, 12, 12, 12, + 18, 19, 19, 19, 19, 19, 19, 19, + 17, 18, 18, 18, 18, 18, + 12, 13, 13, 13, 13, 13, 13, 13, 11, 12, 12, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 14, 11, 11, 11, + 14, 14, + 17, 14, 11, 11, 11, + 17, 14, + +/* 8 */ + 13, 11, 11, + 16, 16, 11, 11, + 17, 17, 17, 16, 16, 16, + 20, 20, 21, + 17, 17, + 8, 9, + 11, + 11, 11, + +/* 16 */ + 13, 13, 13, 13, + 16, 16, 14, + 20, 18, 18, 17, 17, + 13, 13, 16, 16, 16, + 12, 12, 12, 10, 10, + 12, 12, 12, 12, 13, 13, + 14, 12, + 14, 14, 12, 10, 10, + +/* 24 */ + 16, 16, 16, 16, + 16, 16, 16, + 16, 17, 15, 15, + 12, 11, + 12, 12, + 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, + 14, 12, + +/* 32 */ + 10, 10, 10, + 12, 13, 13, + 15, 15, 15, + 15, 15, 15, + 17, 15, 15, + 14, 14, 14, + 15, 15, 15, 15, 15, + 15, 15, 15, 16, 16, 16, + +/* 40 */ + 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 14, + 13, 13, 13, + 13, 13, 13, + 14, 14, 14, 14, + 14, 14, + 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, + +/* 48 */ + 11, 11, 11, 11, + 11, 11, 11, 11, + 10, 10, + 13, 13, 15, 16, + 10, 10, 11, 11, + 14, 14, 11, 11, + 10, 10, + 9, 8, + +/* 56 */ + 17, 17, 17, 17, 17, 17, + 20, 20, 20, 20, 20, + 16, 16, 16, + 20, 20, 20, + 15, 15, + 16, 16, 16, 17, 17, 17, + 16, 17, + 18, 18, + +/* 64 */ + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, + 15, 15, 15, 13, + 15, 12, + 15, 15, 13, + 14, 15, 13, + +/* 72 */ + 14, 14, 14, 12, + 15, 15, 11, 11, + 16, 14, + 11, 11, 13, 11, + 10, 10, 11, 11, + 11, 11, + 13, 13, + 13, 13, + +/* 80 */ + 12, 10, 12, 10, + 14, 14, 14, 14, + 12, 12, 12, 10, + 12, 12, 21, 21, + 10, 10, 13, 13, + 14, 14, 16, 16, + 18, 18, 17, 17, + 19, 19, 19, 19, 19, + +/* 88 */ + 12, 12, 16, 16, + 12, 12, + 15, 15, 19, 19, + 14, 14, 14, 14, + 15, 15, 16, 16, + 16, 16, 16, 18, 18, 18, 18, 18, + 20, 20, 19, 19, + 20, 20, + +/* 96 */ + 15, 15, 16, + 20, 20, 20, 20, + 13, 13, 11, 11, + 17, 17, 17, 15, 15, + 13, 13, 12, 12, + 18, 18, 19, 19, + 17, 17, 19, 19, + 19, 16, 16, + +/* 104 */ + 10, 10, + 11, 11, 11, + 10, 10, 12, 12, 12, + 11, 11, + 11, 11, 9, 9, + 12, 12, 10, 12, + 14, 14, 14, 14, 14, 14, + 15, 15, + +/* 112 */ + 11, 11, 11, 8, + 9, 9, 10, 10, + 11, 11, + 10, 10, + 12, 12, 11, + 12, 12, + 17, 17, 15, 15, + 12, 12, + +/* 120 */ + 11, 11, + 11, 11, + 19, 18, 17, 18, + 17, 10, 19, 19, + 14, 12, 13, 12, + 19, 19, 19, 18, + 13, 12, 13, 12, + 11, 11, 11, 11, + +/* 128 */ + 8, 9, 8, 9, 9, 8, 8, 7, 8, 9, 8, 8, 8, 8, 10, 10, 8, 9, 10, 13, 10, 14, 10, 11, 9, 9, 9, 10, 10, 10, 10, 11, 10, 10, 9, 8, 10, 9, 8, 8, 8, 8, 9, 9, 8, 8, 8, 9, 11, 11, 10, 10, 9, 9, 9, 10, 10, 11, 11, 8, 10, 10, 9, 9, 9, 10, 11, 12 +}; + +short int _awe_sf_gens[] = { + +/* Preset 0 */ + 8,10856, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 43,12800, 48,100, 52,-43, 54,1, 58,75 + , 8,10856, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 43,14643, 48,100, 52,8, 53,1, 54,1, 58,81 + , 8,9617, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 43,16954, 48,100, 52,4, 53,3, 54,1, 58,77 + , 8,10856, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 43,19523, 48,100, 52,2, 53,2, 54,1, 58,83 + , 8,10856, 34,-8800, 35,-799, 36,3417, 38,-148, 40,33, 43,20813, 48,100, 52,2, 53,4, 54,1, 58,89 + , 8,10856, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 43,22610, 48,100, 52,29, 53,5, 54,1, 58,106 + , 8,10856, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 43,23385, 48,100, 52,30, 53,6, 54,1, 58,111 + , 8,10856, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 43,32604, 48,100, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 1 */ + , 8,14400, 9,75, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,0, 43,12800, 48,67, 52,-43, 54,1, 58,75 + , 8,14400, 9,75, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,0, 43,14643, 48,67, 52,8, 53,1, 54,1, 58,81 + , 8,14400, 9,75, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,0, 43,16954, 48,67, 52,4, 53,3, 54,1, 58,77 + , 8,14400, 9,75, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,0, 43,19523, 48,67, 52,2, 53,2, 54,1, 58,83 + , 8,14400, 9,75, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,0, 43,20813, 48,67, 52,2, 53,4, 54,1, 58,89 + , 8,14400, 9,75, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,0, 43,22610, 48,67, 52,29, 53,5, 54,1, 58,106 + , 8,14400, 9,75, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,0, 43,23385, 48,67, 52,30, 53,6, 54,1, 58,111 + , 8,14400, 9,75, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,0, 43,32604, 48,67, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 2 */ + , 8,14400, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,1, 43,14336, 48,100, 52,-43, 54,1, 58,75 + , 8,14400, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,1, 43,16185, 48,100, 52,8, 53,1, 54,1, 58,81 + , 8,14400, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,1, 43,18496, 48,100, 52,4, 53,3, 54,1, 58,77 + , 8,14400, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,1, 43,21065, 48,100, 52,2, 53,2, 54,1, 58,83 + , 8,14400, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,1, 43,24147, 48,100, 52,29, 53,5, 54,1, 58,106 + , 8,14400, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,1, 43,32607, 48,100, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 3 */ + , 17,-287, 34,-8856, 35,-799, 36,4386, 38,-148, 40,33, 41,2, 43,12800, 48,150, 52,-35, 54,1, 58,75 + , 17,-287, 34,-8856, 35,-799, 36,4386, 38,-148, 40,33, 41,2, 43,14643, 48,150, 52,16, 53,1, 54,1, 58,81 + , 17,-287, 34,-8856, 35,-799, 36,4386, 38,-148, 40,33, 41,2, 43,16954, 48,150, 52,11, 53,3, 54,1, 58,77 + , 17,-287, 34,-8856, 35,-799, 36,4386, 38,-148, 40,33, 41,2, 43,19523, 48,150, 52,10, 53,2, 54,1, 58,83 + , 17,-287, 34,-8856, 35,-799, 36,4386, 38,-148, 40,33, 41,2, 43,20813, 48,150, 52,10, 53,4, 54,1, 58,89 + , 17,-287, 34,-8856, 35,-799, 36,4386, 38,-148, 40,33, 41,2, 43,22610, 48,150, 52,36, 53,5, 54,1, 58,106 + , 17,-287, 34,-8856, 35,-799, 36,4386, 38,-148, 40,33, 41,2, 43,23385, 48,150, 52,38, 53,6, 54,1, 58,111 + , 17,-287, 34,-8856, 35,-799, 36,4386, 38,-148, 40,33, 41,2, 43,32604, 48,150, 52,-40, 53,7, 54,1, 58,111 + , 17,146, 35,-799, 36,4386, 38,-148, 40,33, 41,3, 43,12800, 48,150, 52,50, 54,1, 58,76 + , 17,146, 35,-799, 36,4386, 38,-148, 40,33, 41,3, 43,14643, 48,150, 52,2, 53,1, 54,1, 58,81 + , 17,146, 35,-799, 36,4386, 38,-148, 40,33, 41,3, 43,17466, 48,150, 52,-3, 53,3, 54,1, 58,77 + , 17,146, 35,-799, 36,4386, 38,-148, 40,33, 41,3, 43,19525, 48,150, 52,-4, 53,2, 54,1, 58,83 + , 17,146, 35,-799, 36,4386, 38,-148, 40,33, 41,3, 43,20813, 48,150, 52,-4, 53,4, 54,1, 58,89 + , 17,146, 35,-799, 36,4386, 38,-148, 40,33, 41,3, 43,22610, 48,150, 52,22, 53,5, 54,1, 58,106 + , 17,146, 35,-799, 36,4386, 38,-148, 40,33, 41,3, 43,23385, 48,150, 52,24, 53,6, 54,1, 58,111 + , 17,146, 35,-799, 36,4386, 38,-148, 40,33, 41,3, 43,32604, 48,150, 52,46, 53,7, 54,1, 58,112 + +/* Preset 4 */ + , 8,11151, 15,384, 34,-8856, 36,-386, 37,496, 38,-667, 41,4, 43,12288, 48,200, 52,21, 53,138, 54,1, 58,65 + , 8,11151, 15,384, 34,-8856, 36,-261, 37,475, 38,-667, 41,4, 43,15409, 48,200, 52,21, 53,138, 54,1, 58,65 + , 8,11151, 15,384, 34,-8856, 36,1200, 37,496, 38,-667, 41,4, 43,20285, 48,200, 52,21, 53,138, 54,1, 58,65 + , 8,11151, 15,384, 34,-8856, 36,-386, 37,496, 38,-667, 41,4, 43,26449, 48,200, 52,29, 53,8, 54,1, 58,82 + , 8,14400, 9,190, 15,384, 34,-8856, 36,-386, 37,496, 38,-667, 41,4, 43,32616, 48,200, 52,-48, 53,7, 54,1, 58,111 + , 15,419, 34,-8800, 36,3565, 38,-667, 41,5, 43,15360, 48,200, 52,29, 53,149, 54,1, 58,76 + , 15,419, 34,-8800, 36,3565, 38,-667, 41,5, 43,25149, 48,200, 52,-21, 53,127, 54,1, 58,76 + , 15,419, 34,-8800, 36,3565, 38,-667, 41,5, 43,32611, 48,200, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 5 */ + , 8,5074, 11,6412, 29,65, 30,1017, 34,-8800, 36,4301, 38,-949, 41,6, 43,26368, 48,110, 52,29, 53,8, 54,1, 58,82 + , 8,5074, 11,6412, 29,65, 30,1017, 34,-8800, 36,4301, 38,-949, 41,6, 43,32616, 48,110, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 6 */ + , 8,14400, 11,3487, 27,-693, 28,330, 29,412, 34,-8800, 35,-2470, 36,2400, 37,947, 38,91, 41,7, 43,26624, 48,315, 52,-45, 53,10, 54,1, 58,82 + , 8,14400, 11,3487, 27,-693, 28,330, 29,412, 34,-8800, 35,-12000, 36,-12000, 41,7, 43,32617, 48,315, 52,-48, 53,7, 58,111 + , 34,-8800, 35,-2544, 36,1544, 38,-542, 41,178, 43,16896, 48,112, 52,44, 53,71, 54,1, 58,78 + , 34,-8800, 35,-2544, 36,1544, 38,-542, 41,178, 43,27459, 48,112, 52,-31, 53,72, 54,1, 58,85 + , 34,-8800, 35,-2544, 36,1544, 38,-542, 41,178, 43,32620, 48,112, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 7 */ + , 8,8083, 11,3487, 27,-693, 28,330, 29,412, 34,-8800, 35,-2470, 36,3393, 37,937, 38,-3986, 41,8, 43,26368, 48,150, 52,29, 53,9, 54,1, 58,82 + , 8,8083, 11,3487, 27,-693, 28,330, 29,412, 34,-8800, 35,-12000, 36,-12000, 41,8, 43,32616, 48,150, 52,-48, 53,7, 58,111 + +/* Preset 8 */ + , 8,9027, 9,24, 34,-8800, 35,-4372, 36,3049, 38,575, 41,9, 43,24064, 48,100, 52,33, 53,123, 54,1, 58,73 + , 8,9499, 34,-8800, 36,3049, 38,575, 41,10, 43,27136, 48,100, 52,-21, 53,130, 54,1, 58,84 + , 8,9499, 34,-8800, 36,3049, 38,575, 41,10, 43,32619, 48,100, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 9 */ + , 8,5841, 11,3487, 27,-693, 28,330, 29,412, 34,-8800, 35,-2470, 36,413, 37,149, 38,-2050, 41,11, 43,15104, 48,100, 52,11, 53,146, 58,52 + , 8,5841, 11,3487, 27,-693, 28,330, 29,412, 34,-8800, 35,-2470, 36,413, 37,149, 38,-2050, 41,11, 43,18748, 48,100, 52,11, 53,146, 58,52 + , 8,9617, 34,-8800, 36,3049, 38,1591, 41,12, 43,27904, 48,100, 52,32, 53,145, 54,1, 58,88 + , 8,9617, 34,-8800, 36,3049, 38,1591, 41,12, 43,32622, 48,100, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 10 */ + , 9,190, 11,3487, 27,-693, 28,330, 29,412, 34,-7656, 35,-2470, 36,1017, 37,937, 38,1035, 41,13, 43,15360, 48,120, 52,-21, 53,127, 54,1, 58,76 + , 9,190, 11,3487, 27,-693, 28,330, 29,412, 34,-7656, 35,-2470, 36,1017, 37,937, 38,1035, 41,13, 43,25149, 48,120, 52,-21, 53,127, 54,1, 58,76 + , 9,190, 11,3487, 27,-693, 28,330, 29,412, 34,-7656, 35,-2470, 36,1017, 37,937, 38,1035, 41,13, 43,32611, 48,120, 52,-48, 53,7, 54,1, 58,111 + , 8,10325, 9,136, 11,7087, 30,2311, 33,-5572, 34,-5053, 36,813, 37,769, 38,213, 41,14, 43,15360, 48,120, 52,-21, 53,131, 54,1, 58,64 + , 8,10325, 9,136, 11,7087, 30,2311, 33,-5572, 34,-8590, 36,813, 37,769, 38,213, 41,14, 43,22077, 48,120, 52,-21, 53,131, 54,1, 58,64 + , 8,10325, 9,136, 11,7087, 30,2311, 33,-5572, 34,-8856, 36,813, 37,769, 38,213, 41,14, 43,32599, 48,120, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 11 */ + , 8,4779, 11,7087, 13,20, 15,250, 22,-646, 26,-8856, 27,-7972, 28,-386, 29,412, 30,1365, 34,-8856, 36,3049, 38,688, 41,15, 43,24064, 48,120, 52,24, 53,123, 54,1, 58,73 + , 8,4779, 11,7087, 13,20, 15,250, 22,-646, 26,-8856, 27,-7972, 28,-386, 29,412, 30,1365, 34,-8856, 36,1544, 38,688, 41,15, 43,24064, 48,120, 52,24, 53,123, 54,1, 58,73 + , 8,4779, 9,190, 11,7087, 13,20, 15,250, 22,-646, 26,-8856, 27,-7972, 28,-386, 29,412, 30,1365, 34,-8856, 36,4301, 38,688, 41,15, 43,32607, 48,120, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 12 */ + , 11,7087, 15,250, 26,-8856, 27,-7972, 30,1365, 34,-6772, 35,-3986, 36,2013, 37,989, 38,811, 41,16, 43,29440, 48,50, 52,29, 53,125, 54,1, 58,94 + , 11,7087, 15,250, 26,-8856, 27,-7972, 30,1365, 34,-6772, 35,-3986, 36,2013, 37,989, 38,811, 41,16, 43,32628, 48,50, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 13 */ + , 34,-8800, 36,1544, 38,-24, 41,17, 48,67, 52,-45, 53,121, 58,98 + , 34,-8800, 36,1544, 38,-24, 41,17, 43,32633, 48,67, 52,-48, 53,7, 58,111 + +/* Preset 14 */ + , 8,10266, 34,-8856, 35,-1003, 36,4182, 38,1699, 41,18, 48,50, 52,50, 53,130, 54,1, 58,109 + +/* Preset 15 */ + , 34,-8800, 35,-1132, 36,2198, 38,1145, 41,19, 43,29184, 48,150, 52,-32, 53,68, 54,1, 58,92 + , 34,-8800, 35,-1132, 36,2198, 38,1145, 41,19, 43,32627, 48,150, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 16 */ + , 8,9617, 34,-8856, 35,-2968, 36,3784, 37,0, 38,-2786, 41,20, 43,22016, 48,217, 52,-15, 53,134, 54,1, 58,64 + , 8,9617, 34,-8856, 35,-2968, 36,3784, 37,0, 38,-2786, 41,20, 43,32599, 48,217, 52,-48, 53,7, 54,1, 58,111 + , 8,9617, 34,-8856, 35,241, 36,4037, 37,0, 38,-2786, 41,21, 43,28160, 48,217, 52,-15, 53,131, 54,1, 58,88 + , 8,9617, 34,-8856, 35,-2968, 36,3784, 37,0, 38,-2786, 41,21, 43,32623, 48,217, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 17 */ + , 2,-1, 3,-1, 8,7906, 11,7087, 29,811, 34,-8800, 36,-1586, 37,0, 38,-2786, 41,22, 43,19200, 48,90, 52,-37, 53,132, 54,1, 58,91 + , 2,-1, 3,-1, 8,7906, 11,7087, 29,811, 34,-8800, 36,-1586, 37,0, 38,-2786, 41,22, 43,31052, 48,90, 52,30, 53,133, 54,1, 58,100 + , 8,7906, 11,7087, 29,811, 34,-8800, 36,-1586, 37,0, 38,-2786, 41,22, 43,32634, 48,90, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 18 */ + , 2,-1, 3,-1, 6,28, 8,7906, 11,7087, 15,419, 17,75, 24,-1374, 29,811, 34,-8800, 36,-1270, 37,0, 38,-2786, 41,23, 43,19200, 48,187, 52,-35, 53,132, 54,1, 58,91 + , 6,28, 8,7906, 11,7087, 15,419, 17,75, 24,-1374, 29,811, 34,-8800, 36,-1270, 37,0, 38,-2786, 41,23, 43,31052, 48,187, 52,32, 53,133, 54,1, 58,100 + , 6,28, 8,7906, 11,7087, 15,419, 17,75, 24,-1374, 29,811, 34,-8800, 36,-1270, 37,0, 38,-2786, 41,23, 43,32634, 48,187, 52,-48, 53,7, 54,1, 58,111 + , 9,118, 10,450, 13,65, 15,482, 22,-2921, 34,-8800, 35,241, 36,4037, 37,0, 38,-2786, 41,24, 43,29184, 48,250, 52,5, 53,43, 54,1, 58,93 + , 9,118, 10,450, 13,65, 15,482, 22,-2921, 34,-8800, 35,241, 36,4037, 37,0, 38,-2786, 41,24, 43,32627, 48,250, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 19 */ + , 8,14400, 13,-3, 22,-7925, 34,-1603, 37,0, 38,-667, 41,25, 43,28160, 48,77, 52,-20, 53,131, 54,1, 58,88 + , 8,14400, 13,-3, 22,-7925, 34,-1603, 37,0, 38,-667, 41,25, 43,32623, 48,77, 52,-48, 53,7, 54,1, 58,111 + , 7,-8, 8,10325, 9,30, 11,-112, 27,-6772, 30,4400, 34,-6772, 37,0, 38,-667, 41,26, 43,15360, 48,177, 52,-28, 53,24, 54,1, 58,65 + , 7,-8, 8,10325, 9,30, 11,-112, 27,-6772, 30,4400, 34,-6772, 37,0, 38,-667, 41,26, 43,22333, 48,177, 52,-28, 53,24, 54,1, 58,65 + , 7,-8, 8,10325, 9,190, 11,-112, 27,-6772, 30,4400, 34,-2911, 37,0, 38,-667, 41,26, 43,32600, 48,177, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 20 */ + , 2,-1, 3,-1, 34,-6530, 37,0, 38,-3986, 41,27, 43,21504, 48,157, 52,33, 53,46, 54,1, 58,92 + , 2,-1, 3,-1, 34,-6530, 37,0, 38,-3986, 41,27, 43,25173, 48,157, 52,-15, 53,131, 54,1, 58,76 + , 2,-1, 3,-1, 34,-6530, 37,0, 38,-3986, 41,27, 43,32611, 48,157, 52,-48, 53,7, 54,1, 58,111 + , 34,-1382, 37,0, 38,-1224, 41,28, 43,28160, 48,157, 52,-20, 53,134, 54,1, 58,88 + , 34,-1382, 37,0, 38,-1224, 41,28, 43,32623, 48,157, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 21 */ + , 13,16, 22,-194, 34,-8800, 37,0, 38,-1378, 41,29, 43,14080, 48,200, 52,-46, 53,87, 54,1, 58,76 + , 13,16, 22,-194, 34,-8800, 37,0, 38,-1378, 41,29, 43,16952, 48,200, 52,-1, 53,88, 54,1, 58,81 + , 13,16, 22,-194, 34,-8800, 37,0, 38,-1378, 41,29, 43,28483, 48,200, 52,15, 53,89, 54,1, 58,90 + , 13,16, 22,-194, 34,-8800, 37,0, 38,-1378, 41,29, 43,32624, 48,200, 52,-48, 53,7, 54,1, 58,111 + , 6,9, 24,-1297, 34,-955, 37,0, 38,-3986, 41,179, 43,25088, 48,200, 51,12, 52,-18, 53,79, 54,1, 58,76 + , 6,9, 24,-1297, 34,-955, 37,0, 38,-3986, 41,179, 43,32611, 48,200, 51,12, 52,-46, 53,7, 54,1, 58,111 + +/* Preset 22 */ + , 2,-1, 3,-1, 13,16, 22,-498, 34,-8800, 37,0, 38,-3986, 41,30, 43,28928, 48,105, 52,33, 53,46, 54,1, 58,92 + , 13,16, 22,-498, 34,-8800, 37,0, 38,-3986, 41,30, 43,32626, 48,105, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 23 */ + , 2,-1, 3,-1, 13,16, 22,-498, 34,-8800, 37,0, 38,-3986, 41,31, 43,15104, 48,220, 52,-46, 53,87, 54,1, 58,76 + , 2,-1, 3,-1, 13,16, 22,-498, 34,-8800, 37,0, 38,-3986, 41,31, 43,28476, 48,220, 52,15, 53,89, 54,1, 58,90 + , 13,16, 22,-498, 34,-8800, 37,0, 38,-3986, 41,31, 43,32624, 48,220, 52,-48, 53,7, 54,1, 58,111 + , 34,-955, 37,0, 38,-3986, 41,32, 43,25088, 48,220, 52,-20, 53,79, 54,1, 58,76 + , 34,-955, 37,0, 38,-3986, 41,32, 43,32611, 48,220, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 24 */ + , 5,-8, 6,-8, 13,-1, 21,-3670, 22,-698, 24,1701, 34,-8800, 36,4301, 38,-3986, 41,33, 43,14336, 48,100, 52,46, 53,80, 54,1, 58,70 + , 5,-8, 6,-8, 13,-1, 21,-3670, 22,-698, 24,1701, 34,-8800, 36,4301, 38,-3986, 41,33, 43,19769, 48,100, 52,-1, 53,81, 54,1, 58,77 + , 5,-8, 6,-8, 13,-1, 21,-3670, 22,-698, 24,1701, 34,-8800, 36,4301, 38,-3986, 41,33, 43,24910, 48,100, 52,32, 53,75, 54,1, 58,76 + , 5,-8, 6,-8, 13,-1, 21,-3670, 22,-698, 24,1701, 34,-8800, 36,4301, 38,-3986, 41,33, 43,32610, 48,100, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 25 */ + , 5,-8, 6,-8, 13,-1, 21,-3670, 22,-698, 24,1701, 34,-8800, 36,3417, 38,-3986, 41,34, 43,18432, 48,135, 52,47, 53,74, 54,1, 58,74 + , 5,-8, 6,-8, 13,-1, 21,-3670, 22,-698, 24,1701, 34,-8800, 36,3417, 38,-3986, 41,34, 43,24905, 48,135, 52,32, 53,75, 54,1, 58,76 + , 5,-8, 6,-8, 13,-1, 21,-3670, 22,-698, 24,1701, 34,-8800, 36,3417, 38,-3986, 41,34, 43,32610, 48,135, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 26 */ + , 6,-8, 8,9263, 13,-1, 21,-3670, 22,-698, 24,-837, 34,-8800, 36,2854, 37,895, 38,-3986, 41,35, 43,24576, 48,150, 53,76, 54,1, 58,74 + , 6,-8, 8,9263, 13,-1, 21,-3670, 22,-698, 24,-837, 34,-8800, 36,2854, 37,895, 38,-3986, 41,35, 43,32609, 48,150, 52,-48, 53,7, 54,1, 58,111 + , 8,10089, 13,-1, 22,-837, 34,-8800, 35,-1132, 36,3417, 37,601, 38,-3986, 41,36, 43,27904, 48,150, 52,-18, 53,82, 54,1, 58,87 + , 8,10089, 13,-1, 22,-837, 34,-8800, 35,-1132, 36,3417, 37,601, 38,-3986, 41,36, 43,32622, 48,150, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 27 */ + , 15,462, 34,-8800, 35,-3172, 36,2626, 38,-3986, 41,37, 43,24320, 48,180, 52,7, 53,76, 54,1, 58,74 + , 15,462, 34,-8800, 37,0, 38,-3986, 41,37, 43,32608, 48,180, 52,-4, 53,86, 54,1, 58,91 + +/* Preset 28 */ + , 5,9, 8,14400, 22,-753, 34,-8800, 36,2941, 38,-3986, 41,38, 43,25088, 52,-46, 53,77, 54,1, 58,76 + , 5,9, 8,14400, 22,-753, 34,-8800, 36,2941, 38,-3986, 41,38, 43,32611, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 29 */ + , 34,-8800, 36,3667, 37,34, 38,-3986, 41,39, 43,15872, 48,202, 52,-45, 53,84, 54,1, 58,72 + , 34,-8800, 36,3667, 37,34, 38,-3986, 41,39, 43,16959, 48,202, 52,-35, 53,85, 54,1, 58,79 + , 34,-8800, 36,3667, 37,34, 38,-3986, 41,39, 43,26947, 48,202, 52,38, 53,83, 54,1, 58,84 + , 34,-8800, 36,3667, 37,34, 38,-3986, 41,39, 43,32618, 48,202, 52,-48, 53,7, 54,1, 58,111 + , 34,-8800, 35,-1132, 36,3667, 38,-3986, 41,40, 43,27904, 48,202, 52,-18, 53,82, 54,1, 58,87 + , 34,-8800, 35,-1132, 36,3667, 38,-3986, 41,40, 43,32622, 48,202, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 30 */ + , 34,-8800, 36,5151, 37,916, 38,-3986, 41,41, 43,15872, 48,150, 52,-45, 53,84, 54,1, 58,72 + , 34,-8800, 36,5151, 37,916, 38,-3986, 41,41, 43,16959, 48,150, 52,-35, 53,85, 54,1, 58,79 + , 34,-8800, 36,5151, 37,916, 38,-3986, 41,41, 43,18499, 48,150, 52,38, 53,83, 54,1, 58,84 + , 34,-8800, 36,5151, 37,916, 38,-3986, 41,41, 43,29001, 48,150, 52,-4, 53,86, 54,1, 58,91 + , 34,-8800, 36,5151, 37,916, 38,-3986, 41,41, 43,32626, 48,150, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 31 */ + , 2,-1, 3,-1, 34,-8800, 35,-1344, 36,5151, 37,916, 38,-2420, 41,42, 43,29696, 48,50, 52,8, 53,78, 54,1, 58,85 + , 34,-8800, 35,-1344, 36,5151, 37,916, 38,-2420, 41,42, 43,32629, 48,50, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 32 */ + , 34,-8800, 36,2837, 38,-1378, 41,43, 43,22272, 48,100, 52,44, 53,61, 54,1, 58,66 + , 34,-8800, 36,2521, 38,1591, 41,43, 43,28248, 48,100, 52,25, 53,69, 54,1, 58,89 + , 34,-8800, 36,2837, 38,-1378, 41,43, 43,32623, 48,100, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 33 */ + , 8,8024, 11,7087, 28,-2786, 34,-8800, 36,2521, 38,-1378, 41,44, 43,21504, 48,157, 53,62, 54,1, 58,62 + , 8,8024, 11,7087, 28,-2786, 34,-8800, 36,2521, 38,1591, 41,44, 43,28245, 48,157, 52,25, 53,69, 54,1, 58,89 + , 8,8024, 11,7087, 28,-2786, 34,-8800, 36,2521, 38,-1378, 41,44, 43,32623, 48,157, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 34 */ + , 8,7552, 9,18, 11,7087, 28,0, 34,-8800, 36,5254, 37,212, 38,-1224, 41,45, 43,22784, 48,120, 52,-20, 53,67, 54,1, 58,67 + , 8,7552, 9,18, 11,7087, 28,0, 34,-8800, 36,5254, 37,212, 38,-1224, 41,45, 43,28250, 48,120, 52,25, 53,69, 54,1, 58,89 + , 8,7552, 9,18, 11,7087, 28,0, 34,-8800, 36,5254, 37,212, 38,-1224, 41,45, 43,32623, 48,120, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 35 */ + , 8,7434, 9,18, 11,7087, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-667, 41,46, 43,20736, 48,75, 52,33, 53,63, 54,1, 58,60 + , 8,7434, 9,18, 11,7087, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-667, 41,46, 43,28242, 48,75, 52,25, 53,69, 54,1, 58,89 + , 8,7434, 9,18, 11,7087, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-667, 41,46, 43,32623, 48,75, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 36 */ + , 2,-1, 3,-1, 8,8201, 11,7087, 28,-1586, 34,-8800, 35,-3172, 36,6000, 37,979, 38,-3067, 41,47, 43,18432, 48,120, 52,-10, 53,64, 54,1, 58,50 + , 8,7139, 11,4050, 28,-1586, 34,-8800, 35,-3172, 36,6000, 37,979, 38,-3067, 41,47, 43,28233, 48,120, 52,29, 53,9, 54,1, 58,82 + , 8,8201, 11,7087, 28,-1586, 34,-8800, 35,-3172, 36,6000, 37,979, 38,-3067, 41,47, 43,32623, 48,120, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 37 */ + , 8,8791, 11,7087, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-3343, 41,48, 43,22528, 48,152, 52,25, 53,65, 54,1, 58,67 + , 8,8791, 11,7087, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-3343, 41,48, 43,28249, 48,152, 52,25, 53,69, 54,1, 58,89 + , 8,8791, 11,7087, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-3343, 41,48, 43,32623, 48,152, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 38 */ + , 8,4956, 11,6412, 27,-6772, 28,-2786, 34,-8800, 36,6000, 37,979, 38,-2821, 41,49, 43,16640, 48,70, 52,4, 53,66, 54,1, 58,44 + , 8,4956, 11,6412, 27,-6772, 28,-2786, 34,-8800, 36,6000, 37,979, 38,-2821, 41,49, 43,27970, 48,70, 52,-1, 53,128, 54,1, 58,87 + , 8,4956, 11,6412, 27,-6772, 28,-2786, 34,-8800, 36,6000, 37,979, 38,-2821, 41,49, 43,32622, 48,70, 52,-48, 53,7, 54,1, 58,111 + , 8,4956, 11,6412, 27,-6772, 28,-2786, 34,-8800, 36,6000, 37,979, 38,-2821, 41,49, 43,26178, 48,70, 52,2, 53,135, 54,1, 58,81 + , 8,4956, 11,6412, 27,-6772, 28,-2786, 34,-8800, 36,6000, 37,979, 38,-2821, 41,49, 43,32615, 48,70, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 39 */ + , 8,9145, 11,6412, 27,-6772, 28,-884, 34,-8800, 36,6000, 37,979, 38,-802, 41,50, 43,20736, 48,157, 52,35, 53,63, 54,1, 58,60 + , 8,9145, 11,6412, 27,-6772, 28,-884, 34,-8800, 36,6000, 37,979, 38,-802, 41,50, 43,28242, 48,157, 52,25, 53,69, 54,1, 58,89 + , 8,9145, 11,6412, 27,-6772, 28,-884, 34,-8800, 36,6000, 37,979, 38,-802, 41,50, 43,32623, 48,157, 52,-48, 53,7, 54,1, 58,111 + , 8,8024, 9,63, 11,5287, 27,-6772, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-802, 41,51, 43,22784, 48,120, 52,-15, 53,67, 54,1, 58,67 + , 8,8024, 9,63, 11,5287, 27,-6772, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-802, 41,51, 43,28250, 48,120, 52,25, 53,69, 54,1, 58,89 + , 8,8024, 9,63, 11,5287, 27,-6772, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-802, 41,51, 43,32623, 48,120, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 40 */ + , 5,19, 8,10561, 21,-2332, 22,-837, 34,-7972, 36,3975, 37,0, 38,-667, 41,52, 43,17920, 48,120, 52,30, 53,55, 54,1, 58,87 + , 5,19, 8,10561, 21,-2332, 22,-837, 34,-7972, 36,3975, 37,0, 38,-667, 41,52, 43,19015, 48,120, 52,15, 53,56, 54,1, 58,90 + , 5,19, 8,10561, 21,-2332, 22,-837, 34,-7972, 36,3975, 37,0, 38,-667, 41,52, 43,20043, 48,120, 52,-45, 53,57, 54,1, 58,94 + , 5,19, 8,10561, 21,-2332, 22,-837, 34,-7972, 36,3975, 37,0, 38,-667, 41,52, 43,21071, 48,120, 52,24, 53,58, 54,1, 58,98 + , 5,19, 8,10561, 21,-2332, 22,-837, 34,-7972, 36,3975, 37,0, 38,-667, 41,52, 43,31571, 48,120, 52,15, 53,59, 54,1, 58,102 + , 5,19, 8,10561, 21,-2332, 22,-837, 34,-7972, 36,3975, 37,0, 38,-667, 41,52, 43,32636, 48,120, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 41 */ + , 2,-1, 3,-1, 5,19, 21,-2332, 22,-837, 34,-2803, 36,3975, 37,0, 38,-667, 41,53, 43,16640, 48,100, 52,30, 53,55, 54,1, 58,87 + , 2,-1, 3,-1, 5,19, 21,-2332, 22,-837, 34,-6688, 36,3975, 37,0, 38,-667, 41,53, 43,17730, 48,100, 52,15, 53,56, 54,1, 58,90 + , 2,-1, 3,-1, 5,19, 21,-2332, 22,-837, 34,-6688, 36,3975, 37,0, 38,-667, 41,53, 43,18758, 48,100, 52,-45, 53,57, 54,1, 58,94 + , 2,-1, 3,-1, 5,19, 21,-2332, 22,-837, 34,-6688, 36,3975, 37,0, 38,-667, 41,53, 43,19786, 48,100, 52,24, 53,58, 54,1, 58,98 + , 2,-1, 3,-1, 5,19, 21,-2332, 22,-837, 34,-6688, 36,3975, 37,0, 38,-667, 41,53, 43,31566, 48,100, 52,15, 53,59, 54,1, 58,102 + , 5,19, 21,-2332, 22,-837, 34,-6688, 36,3975, 37,0, 38,-667, 41,53, 43,32636, 48,100, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 42 */ + , 5,19, 21,-2332, 22,-837, 34,-2653, 37,0, 38,-542, 41,54, 43,13568, 48,120, 52,32, 53,52, 54,1, 58,76 + , 5,19, 21,-2332, 22,-837, 34,-2653, 37,0, 38,-542, 41,54, 43,26934, 48,120, 52,38, 53,53, 54,1, 58,84 + , 5,19, 21,-2332, 22,-837, 34,-2653, 37,0, 38,-542, 41,54, 43,32618, 48,120, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 43 */ + , 5,19, 21,-2332, 22,-837, 34,-8800, 37,0, 38,-667, 41,55, 43,21760, 48,140, 52,32, 53,54, 54,1, 58,64 + , 5,19, 21,-2332, 22,-837, 34,-5447, 37,0, 38,-667, 41,55, 43,26966, 48,140, 52,38, 53,53, 54,1, 58,84 + , 5,19, 21,-2332, 22,-837, 34,-8800, 37,0, 38,-667, 41,55, 43,32618, 48,140, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 44 */ + , 5,19, 13,30, 21,-2332, 22,460, 34,-8800, 37,0, 38,-405, 41,56, 43,15104, 48,67, 52,33, 53,48, 54,1, 58,74 + , 5,19, 13,30, 21,-2332, 22,460, 34,-8800, 37,0, 38,-405, 41,56, 43,18492, 48,67, 52,50, 53,49, 54,1, 58,88 + , 5,19, 13,30, 21,-2332, 22,460, 34,-8800, 37,0, 38,-405, 41,56, 43,29513, 48,67, 52,36, 53,50, 54,1, 58,94 + , 5,19, 13,30, 21,-2332, 22,460, 34,-8800, 37,0, 38,-405, 41,56, 43,32628, 48,67, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 45 */ + , 5,-8, 13,-1, 21,-2332, 22,-837, 34,-8800, 36,1092, 38,213, 41,57, 43,29440, 48,80, 52,3, 53,60, 54,1, 58,91 + , 5,-8, 13,-1, 21,-2332, 22,-837, 34,-8800, 36,1092, 38,213, 41,57, 43,32628, 48,80, 52,-41, 53,7, 54,1, 58,111 + +/* Preset 46 */ + , 34,-8800, 36,2521, 38,1591, 41,58, 43,28160, 48,80, 52,25, 53,69, 54,1, 58,89 + , 34,-8800, 36,2521, 38,1591, 41,58, 43,32623, 48,80, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 47 */ + , 34,-8856, 35,-1066, 36,2288, 38,1482, 41,59, 43,12032, 48,127, 52,50, 53,112, 54,1, 58,80 + , 34,-8856, 35,-1066, 36,2265, 38,1017, 41,59, 43,12336, 48,127, 52,50, 53,112, 54,1, 58,80 + , 34,-8856, 35,-1066, 36,2217, 38,-148, 41,59, 43,13105, 48,127, 52,50, 53,112, 54,1, 58,80 + , 34,-8856, 35,-1066, 36,2013, 38,813, 41,59, 43,14132, 48,127, 52,50, 53,112, 54,1, 58,80 + , 34,-8856, 35,-1066, 36,2118, 38,701, 41,59, 43,15160, 48,127, 52,50, 53,112, 54,1, 58,80 + , 34,-8856, 35,-1066, 36,2013, 38,582, 41,59, 43,18236, 48,127, 52,50, 53,112, 54,1, 58,80 + , 34,-8856, 35,-1066, 36,1654, 38,-148, 41,59, 43,25928, 48,127, 52,50, 53,112, 54,1, 58,80 + , 34,-8856, 35,-1066, 36,2118, 38,-148, 41,59, 43,32614, 48,127, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 48 */ + , 8,9853, 34,-8800, 37,0, 38,-24, 41,60, 43,15104, 48,90, 52,29, 53,48, 54,1, 58,74 + , 8,11033, 34,-8800, 37,0, 38,-24, 41,60, 43,18492, 48,90, 52,50, 53,49, 54,1, 58,88 + , 8,11033, 34,-8800, 37,0, 38,-24, 41,60, 43,29513, 48,90, 52,36, 53,50, 54,1, 58,94 + , 8,11033, 34,-8800, 37,0, 38,-24, 41,60, 43,32628, 48,90, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 49 */ + , 8,11682, 34,-1500, 37,0, 38,1035, 41,61, 43,15104, 48,100, 52,29, 53,48, 54,1, 58,74 + , 8,11682, 34,-1500, 37,0, 38,1035, 41,61, 43,18492, 48,100, 52,50, 53,49, 54,1, 58,88 + , 8,11682, 34,-1500, 37,0, 38,1035, 41,61, 43,29513, 48,100, 52,36, 53,50, 54,1, 58,94 + , 8,11682, 34,-1500, 37,0, 38,1035, 41,61, 43,32628, 48,100, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 50 */ + , 34,-5152, 37,0, 38,338, 41,62, 43,29440, 48,75, 52,4, 53,51, 54,1, 58,94 + , 34,-5152, 37,0, 38,338, 41,62, 43,32628, 48,75, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 51 */ + , 7,-130, 11,112, 30,2013, 34,-2266, 37,0, 38,1591, 41,63, 43,29440, 48,45, 52,8, 53,51, 54,1, 58,94 + , 7,-130, 11,112, 30,2013, 34,-2266, 37,0, 38,1591, 41,63, 43,32628, 48,45, 52,-48, 53,7, 54,1, 58,111 + , 8,7670, 9,100, 11,7087, 28,0, 29,811, 30,1782, 34,-2266, 37,0, 38,1591, 41,64, 43,29696, 48,52, 53,51, 54,1, 58,94 + , 8,7670, 9,100, 11,7087, 28,0, 29,811, 30,1782, 34,-2266, 37,0, 38,1591, 41,64, 43,32629, 48,52, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 52 */ + , 34,-1684, 37,0, 38,213, 41,65, 43,30464, 48,40, 52,10, 53,142, 54,1, 58,98 + , 34,-1684, 37,0, 38,213, 41,65, 43,32632, 48,40, 52,-48, 53,7, 54,1, 58,111 + , 9,69, 34,-1684, 37,0, 38,213, 41,66, 43,27392, 48,40, 52,-28, 53,143, 54,1, 58,85 + , 9,69, 34,-1684, 37,0, 38,213, 41,66, 43,32620, 48,40, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 53 */ + , 8,11505, 9,42, 34,-2968, 36,3462, 37,97, 38,-1079, 41,67, 43,23552, 48,100, 51,1, 52,-15, 53,43, 54,1, 58,70 + , 8,11505, 9,42, 34,-2968, 36,3462, 37,97, 38,-1079, 41,67, 43,32605, 48,100, 51,1, 52,-48, 53,7, 54,1, 58,111 + , 34,-8800, 36,3462, 37,191, 38,-1079, 41,68, 43,25856, 48,100, 52,-28, 53,147, 54,1, 58,79 + , 34,-8800, 36,3462, 37,191, 38,-1079, 41,68, 43,32614, 48,100, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 54 */ + , 34,-11958, 37,34, 38,338, 41,69, 43,27392, 48,40, 52,-25, 53,143, 54,1, 58,85 + , 34,-11958, 37,34, 38,338, 41,69, 43,32620, 48,40, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 55 */ + , 34,-8800, 36,-3986, 37,0, 38,1482, 41,70, 43,30464, 52,35, 53,124, 58,98 + , 34,-8800, 37,0, 38,1482, 41,70, 43,32632, 52,-48, 53,7, 58,111 + +/* Preset 56 */ + , 5,9, 9,42, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,23, 38,-1079, 41,71, 43,16384, 48,52, 52,-43, 53,33, 54,1, 58,84 + , 5,9, 9,42, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,23, 38,-1079, 41,71, 43,17729, 48,52, 52,-20, 53,29, 54,1, 58,88 + , 5,9, 9,42, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,23, 38,-1079, 41,71, 43,19014, 48,52, 52,-1, 53,30, 54,1, 58,93 + , 5,9, 9,42, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,23, 38,-1079, 41,71, 43,20299, 48,52, 52,24, 53,31, 54,1, 58,98 + , 5,9, 9,42, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,23, 38,-1079, 41,71, 43,32080, 48,52, 52,-4, 53,32, 54,1, 58,103 + , 5,9, 9,42, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,23, 38,-1079, 41,71, 43,32638, 48,52, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 57 */ + , 5,9, 8,5251, 11,7087, 21,-2332, 22,-837, 26,-8856, 28,3841, 29,496, 30,3488, 34,-8856, 36,4301, 37,23, 38,-1079, 41,72, 43,13312, 48,50, 52,-7, 53,34, 54,1, 58,70 + , 5,9, 8,5251, 11,7087, 21,-2332, 22,-837, 26,-8856, 28,3841, 29,496, 30,3488, 34,-8856, 36,4301, 37,23, 38,-1079, 41,72, 43,15157, 48,50, 52,33, 53,35, 54,1, 58,80 + , 5,9, 8,5251, 11,7087, 21,-2332, 22,-837, 26,-8856, 28,3841, 29,496, 30,3488, 34,-8856, 36,4301, 37,23, 38,-1079, 41,72, 43,16444, 48,50, 52,-3, 53,36, 54,1, 58,84 + , 5,9, 8,5251, 11,7087, 21,-2332, 22,-837, 26,-8856, 28,3841, 29,496, 30,3488, 34,-8856, 36,4301, 37,23, 38,-1079, 41,72, 43,28481, 48,50, 52,16, 53,37, 54,1, 58,90 + , 5,9, 8,5251, 11,7087, 21,-2332, 22,-837, 26,-8856, 28,3841, 29,496, 30,3488, 34,-8856, 36,4301, 37,23, 38,-1079, 41,72, 43,32624, 48,50, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 58 */ + , 5,9, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,55, 38,-1224, 41,73, 43,22016, 48,50, 52,38, 53,38, 54,1, 58,65 + , 5,9, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,55, 38,-1224, 41,73, 43,28503, 48,50, 52,16, 53,37, 54,1, 58,90 + , 5,9, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,55, 38,-1224, 41,73, 43,32624, 48,50, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 59 */ + , 5,9, 8,5251, 11,6862, 21,-2332, 22,-837, 26,-8856, 28,4054, 29,496, 30,3488, 34,-8856, 36,4301, 37,55, 38,-1224, 41,74, 43,16640, 48,82, 52,44, 53,39, 54,1, 58,78 + , 5,9, 8,5251, 11,6862, 21,-2332, 22,-837, 26,-8856, 28,4054, 29,496, 30,3488, 34,-8856, 36,4301, 37,55, 38,-1224, 41,74, 43,28738, 48,82, 52,-40, 53,40, 54,1, 58,90 + , 5,9, 8,5251, 11,6862, 21,-2332, 22,-837, 26,-8856, 28,4054, 29,496, 30,3488, 34,-8856, 36,4301, 37,55, 38,-1224, 41,74, 43,32625, 48,82, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 60 */ + , 2,1, 3,1, 11,6862, 28,4054, 34,-8590, 36,4301, 37,149, 38,-24, 41,75, 43,28416, 48,30, 52,15, 53,22, 54,1, 58,90 + , 2,1, 3,1, 11,6862, 28,4054, 34,-8590, 36,4301, 37,149, 38,-24, 41,75, 43,32624, 48,30, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 61 */ + , 5,9, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,55, 38,-949, 41,76, 43,18176, 48,120, 52,-35, 53,27, 54,1, 58,77 + , 5,9, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,55, 38,-949, 41,76, 43,29768, 48,120, 52,47, 53,28, 54,1, 58,95 + , 5,9, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,55, 38,-949, 41,76, 43,32629, 48,120, 52,-48, 53,7, 54,1, 58,111 + , 5,9, 11,6862, 21,-2400, 22,-926, 28,4054, 33,-6772, 34,-8856, 36,4301, 37,55, 38,-949, 41,77, 43,18176, 48,120, 52,-26, 53,27, 54,1, 58,77 + , 5,9, 11,6862, 21,-2400, 22,-926, 28,4054, 33,-6772, 34,-8856, 36,4301, 37,55, 38,-949, 41,77, 43,29768, 48,120, 52,-43, 53,28, 54,1, 58,94 + , 5,9, 11,6862, 21,-2400, 22,-926, 28,4054, 33,-6772, 34,-8856, 36,4301, 37,55, 38,-949, 41,77, 43,32629, 48,120, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 62 */ + , 8,9971, 9,66, 11,7087, 27,-4372, 28,4054, 30,2919, 34,-8856, 36,4301, 37,55, 38,-1224, 41,78, 43,27904, 48,30, 53,128, 54,1, 58,87 + , 8,9971, 9,66, 11,7087, 27,-4372, 28,4054, 30,2919, 34,-8856, 36,4301, 37,55, 38,-1224, 41,78, 43,32622, 48,30, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 63 */ + , 8,6195, 9,21, 11,7087, 27,-7972, 28,4054, 29,989, 30,2641, 34,-8856, 36,4301, 37,0, 38,-1079, 41,79, 43,27648, 48,30, 52,2, 53,128, 54,1, 58,87 + , 8,6195, 9,21, 11,7087, 27,-7972, 28,4054, 29,989, 30,2641, 34,-8856, 36,4301, 37,0, 38,-1079, 41,79, 43,32621, 48,30, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 64 */ + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,86, 38,-3986, 41,80, 43,14336, 48,30, 52,36, 53,11, 54,1, 58,71 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,86, 38,-3986, 41,80, 43,14905, 48,30, 52,-45, 53,12, 54,1, 58,74 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,86, 38,-3986, 41,80, 43,16699, 48,30, 52,5, 53,13, 54,1, 58,76 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,86, 38,-3986, 41,80, 43,18498, 48,30, 52,29, 53,14, 54,1, 58,82 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,86, 38,-3986, 41,80, 43,19529, 48,30, 52,-3, 53,15, 54,1, 58,84 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,86, 38,-3986, 41,80, 43,22093, 48,30, 52,-4, 53,16, 54,1, 58,91 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,86, 38,-3986, 41,80, 43,29527, 48,30, 52,29, 53,17, 54,1, 58,94 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,86, 38,-3986, 41,80, 43,32628, 48,30, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 65 */ + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,81, 43,13568, 48,70, 52,36, 53,11, 54,1, 58,71 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,81, 43,14646, 48,70, 52,-45, 53,12, 54,1, 58,74 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,81, 43,15930, 48,70, 52,5, 53,13, 54,1, 58,76 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,81, 43,17727, 48,70, 52,29, 53,14, 54,1, 58,82 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,81, 43,18758, 48,70, 52,-3, 53,15, 54,1, 58,84 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,81, 43,20810, 48,70, 52,-4, 53,16, 54,1, 58,91 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,81, 43,29522, 48,70, 52,29, 53,17, 54,1, 58,94 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,81, 43,32628, 48,70, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 66 */ + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,82, 43,13056, 48,79, 52,36, 53,11, 54,1, 58,71 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,82, 43,13876, 48,79, 52,-45, 53,12, 54,1, 58,74 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,82, 43,14903, 48,79, 52,5, 53,13, 54,1, 58,76 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,82, 43,16443, 48,79, 52,29, 53,14, 54,1, 58,82 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,82, 43,17473, 48,79, 52,-3, 53,15, 54,1, 58,84 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,82, 43,19013, 48,79, 52,-4, 53,16, 54,1, 58,91 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,82, 43,29515, 48,79, 52,29, 53,17, 54,1, 58,94 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,82, 43,32628, 48,79, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 67 */ + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,55, 38,-3986, 41,83, 43,13056, 48,50, 52,-45, 53,12, 54,1, 58,74 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,55, 38,-3986, 41,83, 43,14388, 48,50, 52,5, 53,13, 54,1, 58,76 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,55, 38,-3986, 41,83, 43,15161, 48,50, 52,29, 53,14, 54,1, 58,82 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,55, 38,-3986, 41,83, 43,16444, 48,50, 52,-3, 53,15, 54,1, 58,84 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,55, 38,-3986, 41,83, 43,17473, 48,50, 52,-4, 53,16, 54,1, 58,91 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,55, 38,-3986, 41,83, 43,29509, 48,50, 52,29, 53,17, 54,1, 58,94 + , 5,9, 21,-2332, 22,-837, 34,-8856, 37,55, 38,-3986, 41,83, 43,32628, 48,50, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 68 */ + , 2,-1, 3,-1, 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,84, 43,16128, 48,75, 52,33, 53,18, 54,1, 58,80 + , 2,-1, 3,-1, 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,84, 43,17472, 48,75, 52,38, 53,19, 54,1, 58,84 + , 2,-1, 3,-1, 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,84, 43,27973, 48,75, 52,32, 53,20, 54,1, 58,88 + , 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,84, 43,32622, 48,75, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 69 */ + , 2,-1, 3,-1, 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,85, 43,25856, 48,62, 52,-35, 53,21, 54,1, 58,79 + , 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,85, 43,32614, 48,62, 52,-48, 53,7, 58,111 + +/* Preset 70 */ + , 2,-1, 3,-1, 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,86, 43,22528, 48,62, 52,41, 53,23, 54,1, 58,67 + , 2,-1, 3,-1, 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,86, 43,25945, 48,62, 52,-35, 53,21, 54,1, 58,79 + , 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,86, 43,32614, 48,62, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 71 */ + , 2,-1, 3,-1, 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,87, 43,17664, 48,62, 53,25, 54,1, 58,74 + , 2,-1, 3,-1, 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,87, 43,25926, 48,62, 52,49, 53,26, 54,1, 58,80 + , 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,87, 43,32614, 48,62, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 72 */ + , 5,9, 21,-2332, 22,-837, 34,-8800, 36,2941, 37,86, 38,-3986, 41,88, 43,28416, 48,90, 52,-28, 53,24, 54,1, 58,89 + , 5,9, 21,-2332, 22,-837, 34,-8800, 36,2941, 37,86, 38,-3986, 41,88, 43,32624, 48,90, 52,-48, 53,7, 54,1, 58,111 + , 2,-3, 3,-3, 8,9853, 34,-3151, 36,4280, 37,86, 38,-3986, 41,89, 43,28928, 48,90, 52,33, 53,41, 54,1, 58,92 + , 8,9853, 34,-3151, 36,4280, 37,86, 38,-3986, 41,89, 43,32626, 48,90, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 73 */ + , 5,9, 9,106, 21,-2332, 22,-837, 34,-4899, 35,-3172, 36,3049, 37,34, 38,-3986, 41,90, 43,28416, 52,-28, 53,24, 54,1, 58,89 + , 5,9, 9,106, 21,-2332, 22,-837, 34,-4899, 35,-3172, 36,3049, 37,34, 38,-3986, 41,90, 43,32624, 52,-48, 53,7, 54,1, 58,111 + , 9,97, 34,-8800, 37,34, 38,-3986, 41,91, 43,26368, 48,240, 52,-1, 53,43, 54,1, 58,81 + , 9,97, 34,-8800, 37,34, 38,-3986, 41,91, 43,32616, 48,240, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 74 */ + , 2,-3, 3,-3, 5,9, 21,-2332, 22,-837, 34,-8856, 36,4280, 37,34, 38,-3986, 41,92, 43,28928, 48,52, 52,33, 53,41, 54,1, 58,92 + , 5,9, 21,-2332, 22,-837, 34,-8856, 36,4280, 37,34, 38,-3986, 41,92, 43,32626, 48,52, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 75 */ + , 34,-8856, 36,4077, 37,34, 38,-3986, 41,93, 43,26368, 48,142, 52,-1, 53,43, 54,1, 58,81 + , 34,-8856, 36,4077, 37,34, 38,-3986, 41,93, 43,32616, 48,142, 52,-48, 53,7, 54,1, 58,111 + , 2,-3, 3,-3, 34,-8856, 36,3462, 37,34, 38,-3986, 41,94, 43,28928, 48,142, 52,40, 53,41, 54,1, 58,92 + , 34,-8856, 36,3462, 37,34, 38,-3986, 41,94, 43,32626, 48,142, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 76 */ + , 34,-8800, 36,1317, 37,0, 38,-3986, 41,95, 43,23296, 48,180, 52,38, 53,42, 58,70 + , 34,-8800, 36,1317, 37,0, 38,-3986, 41,95, 43,32604, 48,180, 52,-48, 53,7, 58,111 + , 34,-8856, 36,4077, 37,0, 38,-3986, 41,96, 43,26368, 48,180, 52,-7, 53,43, 54,1, 58,81 + , 34,-8856, 36,4077, 37,0, 38,-3986, 41,96, 43,32616, 48,180, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 77 */ + , 34,-8800, 36,2521, 37,13, 38,-3986, 41,97, 43,26368, 48,180, 52,-7, 53,43, 54,1, 58,81 + , 34,-8800, 36,2521, 37,13, 38,-3986, 41,97, 43,32616, 48,180, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 78 */ + , 5,9, 21,-2203, 22,-1019, 34,-4870, 37,13, 38,-3986, 41,98, 43,27392, 48,67, 52,24, 53,44, 54,1, 58,86 + , 5,9, 21,-2203, 22,-1019, 34,-4870, 37,13, 38,-3986, 41,98, 43,32620, 48,67, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 79 */ + , 5,9, 21,-2203, 22,-1019, 34,-8800, 37,23, 38,-3986, 41,99, 43,27392, 48,52, 52,24, 53,44, 54,1, 58,86 + , 5,9, 21,-2203, 22,-1019, 34,-8800, 37,23, 38,-3986, 41,99, 43,32620, 48,52, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 80 */ + , 2,-3, 3,-3, 34,-11958, 37,23, 38,-3986, 41,101, 43,25856, 48,180, 52,-32, 53,129, 54,1, 58,79 + , 34,-11958, 37,23, 38,-3986, 41,101, 43,32614, 48,180, 52,-48, 53,7, 54,1, 58,111 + , 2,-3, 3,-3, 34,-11958, 37,23, 38,-3986, 41,102, 43,25856, 48,180, 52,-39, 53,129, 54,1, 58,79 + , 34,-11958, 37,23, 38,-3986, 41,102, 43,32614, 48,180, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 81 */ + , 8,10325, 9,81, 11,7087, 28,-1586, 34,-11958, 37,23, 38,-3986, 41,103, 43,27904, 48,60, 52,-1, 53,128, 54,1, 58,87 + , 8,10325, 9,81, 11,7087, 28,-1586, 34,-11958, 37,23, 38,-3986, 41,103, 43,32622, 48,60, 52,-48, 53,7, 54,1, 58,111 + , 8,10915, 9,81, 11,7087, 28,-1586, 34,-11958, 37,23, 38,-3986, 41,104, 43,26112, 48,120, 52,2, 53,135, 54,1, 58,81 + , 8,10915, 9,81, 11,7087, 28,-1586, 34,-11958, 37,23, 38,-3986, 41,104, 43,32615, 48,120, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 82 */ + , 15,466, 30,813, 34,-11958, 36,1317, 37,23, 38,-3986, 41,180, 43,23296, 48,50, 52,38, 53,42, 58,70 + , 15,466, 30,813, 34,-11958, 36,1317, 37,23, 38,-3986, 41,180, 43,32604, 48,50, 52,-48, 53,7, 58,111 + , 2,-3, 3,-3, 34,-8856, 37,23, 38,-3986, 41,106, 43,25856, 48,135, 52,-32, 53,129, 54,1, 58,79 + , 34,-8856, 37,23, 38,-3986, 41,106, 43,32614, 48,135, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 83 */ + , 15,466, 30,813, 34,-11958, 36,1317, 37,23, 38,-3986, 41,105, 43,23296, 48,180, 52,38, 53,42, 58,70 + , 15,466, 30,813, 34,-11958, 36,1317, 37,23, 38,-3986, 41,105, 43,32604, 48,180, 52,-48, 53,7, 58,111 + , 7,919, 8,4602, 9,33, 11,4612, 15,497, 26,-5407, 27,413, 28,6000, 29,0, 30,2013, 34,-8856, 37,23, 38,-3986, 41,107, 43,26112, 48,82, 51,-9, 52,2, 53,135, 54,1, 58,81 + , 7,919, 8,4602, 9,33, 11,4612, 15,497, 26,-5407, 27,413, 28,6000, 29,0, 30,2013, 34,-8856, 37,23, 38,-3986, 41,107, 43,32615, 48,82, 51,-9, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 84 */ + , 34,-8800, 37,23, 38,-3986, 41,108, 43,27648, 48,135, 52,10, 53,128, 54,1, 58,87 + , 34,-8800, 37,23, 38,-3986, 41,108, 43,32621, 48,135, 52,-48, 53,7, 54,1, 58,111 + , 7,-149, 29,580, 34,-8800, 37,23, 38,-3986, 41,109, 43,26112, 48,277, 51,-1, 52,-15, 53,9, 54,1, 58,80 + , 7,-149, 29,580, 34,-8800, 37,23, 38,-3986, 41,109, 43,32615, 48,277, 51,-1, 52,-24, 53,7, 54,1, 58,111 + +/* Preset 85 */ + , 5,47, 15,497, 22,-78, 34,-6772, 36,4077, 37,23, 38,-3986, 41,110, 43,26368, 48,82, 52,-1, 53,43, 54,1, 58,81 + , 5,47, 15,497, 22,-78, 34,-6772, 36,4077, 37,23, 38,-3986, 41,110, 43,32616, 48,82, 52,-48, 53,7, 54,1, 58,111 + , 5,-8, 6,9, 9,33, 15,497, 22,-42, 24,29, 34,-8800, 37,23, 38,-3986, 41,111, 43,30464, 48,82, 52,5, 53,142, 54,1, 58,98 + , 5,-8, 6,9, 9,33, 15,497, 22,-42, 24,29, 34,-8800, 37,23, 38,-3986, 41,111, 43,32632, 48,82, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 86 */ + , 8,4484, 9,150, 11,7087, 15,435, 28,1365, 29,727, 30,4400, 34,-6772, 36,3770, 37,23, 38,-3986, 41,112, 43,27904, 48,30, 52,-1, 53,128, 54,1, 58,87 + , 8,4484, 9,150, 11,7087, 15,435, 28,1365, 29,727, 30,4400, 34,-6772, 36,3770, 37,23, 38,-3986, 41,112, 43,32622, 48,30, 52,-48, 53,7, 54,1, 58,111 + , 8,4602, 9,190, 11,7087, 15,497, 28,1515, 29,706, 30,4400, 34,-8800, 37,23, 38,-3986, 41,113, 43,27392, 48,30, 52,2, 53,135, 54,1, 58,86 + , 8,4602, 9,190, 11,7087, 15,497, 28,1515, 29,706, 30,4400, 34,-8800, 37,23, 38,-3986, 41,113, 43,32620, 48,30, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 87 */ + , 8,4956, 9,36, 11,5175, 15,497, 21,-2084, 22,-780, 28,0, 29,601, 30,1365, 34,-8856, 37,23, 38,-3986, 41,114, 43,16640, 48,50, 52,8, 53,66, 54,1, 58,44 + , 8,4956, 9,36, 11,5175, 15,497, 21,-2084, 22,-780, 28,0, 29,601, 30,1365, 34,-8856, 37,23, 38,-3986, 41,114, 43,27970, 48,50, 52,-1, 53,128, 54,1, 58,87 + , 8,4956, 9,36, 11,5175, 15,497, 21,-2084, 22,-780, 28,0, 29,601, 30,1365, 34,-8856, 37,23, 38,-3986, 41,114, 43,32622, 48,50, 52,-48, 53,7, 54,1, 58,111 + , 8,4956, 9,36, 11,5175, 15,497, 21,-2084, 22,-780, 28,0, 29,601, 30,1365, 34,-8856, 37,23, 38,-3986, 41,114, 43,26178, 48,50, 52,2, 53,135, 54,1, 58,81 + , 8,4956, 9,36, 11,5175, 15,497, 21,-2084, 22,-780, 28,0, 29,601, 30,1365, 34,-8856, 37,23, 38,-3986, 41,114, 43,32615, 48,50, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 88 */ + , 8,11328, 15,466, 34,-2653, 37,23, 38,688, 41,115, 43,29440, 48,60, 52,13, 53,51, 54,1, 58,94 + , 8,11328, 15,466, 34,-2653, 37,23, 38,688, 41,115, 43,32628, 48,60, 52,-48, 53,7, 54,1, 58,111 + , 8,9263, 9,15, 11,2362, 15,482, 28,1654, 30,2484, 34,-8800, 36,3153, 38,688, 41,116, 43,26368, 48,82, 52,29, 53,8, 54,1, 58,82 + , 8,9263, 9,15, 11,2362, 15,482, 28,1654, 30,2484, 34,-8800, 36,3153, 38,688, 41,116, 43,32616, 48,82, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 89 */ + , 8,8555, 15,466, 34,-500, 37,23, 38,1482, 41,117, 43,29440, 48,60, 52,10, 53,51, 54,1, 58,94 + , 8,8555, 15,466, 34,-500, 37,23, 38,1482, 41,117, 43,32628, 48,60, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 90 */ + , 7,-243, 8,11505, 9,9, 15,466, 26,-6772, 34,-8800, 37,23, 38,338, 41,118, 43,27648, 48,140, 52,2, 53,128, 54,1, 58,87 + , 7,-243, 8,11505, 9,9, 15,466, 26,-6772, 34,-8800, 37,23, 38,338, 41,118, 43,32621, 48,140, 52,-48, 53,7, 54,1, 58,111 + , 7,-8, 8,11387, 9,97, 11,-4275, 15,482, 25,-12421, 26,413, 28,315, 30,3621, 34,-8800, 37,23, 38,338, 41,119, 43,26112, 48,140, 52,11, 53,135, 54,1, 58,81 + , 7,-8, 8,11387, 9,97, 11,-4275, 15,482, 25,-12421, 26,413, 28,315, 30,3621, 34,-8800, 37,23, 38,338, 41,119, 43,32615, 48,140, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 91 */ + , 5,28, 9,24, 15,466, 22,-42, 34,-8856, 37,23, 38,1262, 41,120, 43,25088, 48,150, 52,-20, 53,136, 54,1, 58,76 + , 5,28, 9,24, 15,466, 22,-42, 34,-8856, 37,23, 38,1262, 41,120, 43,32611, 48,150, 52,-48, 53,7, 54,1, 58,111 + , 5,19, 9,24, 15,482, 22,180, 34,-8590, 37,23, 38,1262, 41,121, 43,30464, 48,150, 52,5, 53,142, 54,1, 58,98 + , 5,19, 9,24, 15,482, 22,180, 34,-8590, 37,23, 38,1262, 41,121, 43,32632, 48,150, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 92 */ + , 8,7552, 15,466, 25,-7592, 29,0, 34,-6530, 35,133, 36,4400, 38,1591, 41,122, 43,24832, 48,180, 52,36, 53,149, 54,1, 58,76 + , 8,7552, 15,466, 25,-7592, 29,0, 34,-6530, 35,133, 36,4400, 38,1591, 41,122, 43,32610, 48,180, 52,-48, 53,7, 54,1, 58,111 + , 8,10561, 15,482, 25,-7972, 27,-3172, 28,2715, 34,-5958, 36,2837, 37,139, 38,1916, 41,123, 43,25088, 48,180, 52,-20, 53,137, 54,1, 58,76 + , 8,10561, 15,482, 25,-7972, 27,-3172, 28,2715, 34,-5958, 36,2837, 37,139, 38,1916, 41,123, 43,32611, 48,180, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 93 */ + , 8,6018, 9,81, 11,5062, 15,466, 28,3158, 30,4400, 34,-6013, 36,4400, 38,1699, 41,124, 43,21760, 48,180, 52,32, 53,54, 54,1, 58,64 + , 8,6018, 9,81, 11,5062, 15,466, 28,3158, 30,4400, 34,-6013, 36,4400, 38,1699, 41,124, 43,24918, 48,180, 52,36, 53,149, 54,1, 58,76 + , 8,6018, 9,81, 11,5062, 15,466, 28,3158, 30,4400, 34,-6013, 36,4400, 38,1699, 41,124, 43,32610, 48,180, 52,-48, 53,7, 54,1, 58,111 + , 8,5782, 9,78, 11,5287, 15,482, 28,3043, 30,4400, 34,652, 35,-4372, 36,2837, 37,811, 38,1699, 41,125, 43,16384, 48,180, 52,32, 53,75, 54,1, 58,64 + , 8,5782, 9,78, 11,5287, 15,482, 28,3043, 30,4400, 34,652, 35,-4372, 36,3049, 37,811, 38,1699, 41,125, 43,19521, 48,180, 52,32, 53,75, 54,1, 58,64 + , 8,5782, 9,78, 11,5287, 15,482, 28,3043, 30,4400, 34,652, 35,-4372, 36,2837, 37,811, 38,1699, 41,125, 43,21837, 48,180, 52,32, 53,75, 54,1, 58,64 + , 8,5782, 9,78, 11,5287, 15,482, 28,3043, 30,4400, 34,652, 35,-4372, 36,5817, 37,811, 38,1699, 41,125, 43,25174, 48,180, 52,-20, 53,137, 54,1, 58,76 + , 8,5782, 9,78, 11,5287, 15,482, 28,3043, 30,4400, 34,652, 35,-4372, 36,5817, 37,811, 38,1699, 41,125, 43,32611, 48,180, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 94 */ + , 5,9, 8,7788, 9,129, 10,168, 11,7087, 22,-3357, 27,-7972, 28,1365, 30,2679, 34,-1857, 36,6000, 37,76, 38,1035, 41,126, 43,27904, 48,150, 52,-4, 53,128, 54,1, 58,87 + , 5,9, 8,7788, 9,129, 10,168, 11,7087, 22,-3357, 27,-7972, 28,1365, 30,2679, 34,-1857, 36,6000, 37,76, 38,1035, 41,126, 43,32622, 48,150, 52,-48, 53,7, 54,1, 58,111 + , 5,9, 8,7552, 9,24, 10,168, 11,4387, 22,-3357, 28,1365, 30,2715, 34,-5958, 36,6000, 37,76, 38,1035, 41,127, 43,27904, 48,150, 52,-4, 53,128, 54,1, 58,87 + , 5,9, 8,7552, 9,24, 10,168, 11,4387, 22,-3357, 28,1365, 30,2715, 34,-5958, 36,6000, 37,76, 38,1035, 41,127, 43,32622, 48,150, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 95 */ + , 8,4484, 9,100, 11,7087, 15,466, 25,-3403, 26,4272, 28,2311, 29,506, 30,4400, 34,-2010, 36,4258, 37,0, 38,1916, 41,128, 43,27648, 48,200, 52,7, 53,128, 54,1, 58,87 + , 8,4484, 9,100, 11,7087, 15,466, 25,-3403, 26,4272, 28,2311, 29,506, 30,4400, 34,-2010, 36,4258, 37,0, 38,1916, 41,128, 43,32621, 48,200, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 96 */ + , 8,6726, 9,9, 11,3937, 28,2217, 30,3043, 34,-6772, 36,4800, 38,2025, 41,129, 43,27904, 48,157, 52,-4, 53,128, 54,1, 58,87 + , 8,6726, 9,9, 11,3937, 28,2217, 30,3043, 34,-6772, 36,4800, 38,2025, 41,129, 43,32622, 48,157, 52,-48, 53,7, 54,1, 58,111 + , 7,1144, 9,109, 26,-8856, 28,813, 30,4400, 34,-3151, 36,4800, 38,2240, 41,130, 48,157, 51,-16, 52,-24, 53,122, 54,1, 56,50, 58,82 + +/* Preset 97 */ + , 8,7080, 9,72, 11,3712, 15,466, 26,-2621, 28,315, 29,811, 30,4197, 34,-217, 36,4756, 37,86, 38,2025, 41,131, 43,28672, 48,142, 51,3, 52,-14, 53,128, 54,1, 58,90 + , 8,7080, 9,72, 11,3712, 15,466, 26,-2621, 28,315, 29,811, 30,4197, 34,-217, 36,4756, 37,86, 38,2025, 41,131, 43,32625, 48,142, 51,1, 52,-48, 53,7, 54,1, 58,111 + , 8,7316, 9,60, 11,4162, 15,482, 26,-2084, 28,315, 29,769, 30,4103, 34,-217, 36,4756, 37,86, 38,2025, 41,132, 43,26880, 48,142, 51,3, 52,-14, 53,128, 54,1, 58,83 + , 8,7316, 9,60, 11,4162, 15,482, 26,-2084, 28,315, 29,769, 30,4103, 34,-217, 36,4756, 37,86, 38,2025, 41,132, 43,32618, 48,142, 51,1, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 98 */ + , 8,10443, 15,466, 34,-8800, 35,-4372, 36,3049, 38,1482, 41,133, 43,24064, 48,187, 52,29, 53,123, 54,1, 58,73 + , 8,10443, 15,466, 34,-8800, 35,-4372, 36,3049, 38,1482, 41,133, 43,32607, 48,187, 52,-48, 53,7, 54,1, 58,111 + , 15,482, 34,-8800, 36,3049, 38,1811, 41,134, 43,30208, 48,187, 52,-45, 53,130, 54,1, 58,96 + , 15,482, 34,-8800, 36,3049, 38,1811, 41,134, 43,32631, 48,187, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 99 */ + , 8,7906, 9,15, 11,7087, 15,466, 28,1200, 30,1200, 34,-8800, 36,1980, 37,86, 38,-281, 41,135, 43,18432, 48,130, 52,47, 53,74, 54,1, 58,74 + , 8,7906, 9,15, 11,7087, 15,466, 28,1200, 30,1200, 34,-8800, 36,1980, 37,86, 38,-281, 41,135, 43,24905, 48,130, 52,32, 53,75, 54,1, 58,76 + , 8,7906, 9,15, 11,7087, 15,466, 28,1200, 30,1200, 34,-8800, 36,1980, 37,86, 38,-281, 41,135, 43,32610, 48,130, 52,-48, 53,7, 54,1, 58,111 + , 6,28, 15,482, 21,-3670, 22,-866, 34,-8800, 36,3667, 37,86, 38,1591, 41,136, 43,29440, 48,130, 52,4, 53,51, 54,1, 58,94 + , 6,28, 15,482, 21,-3670, 22,-866, 34,-8800, 36,3667, 37,86, 38,1591, 41,136, 43,32628, 48,130, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 100 */ + , 5,66, 15,466, 22,460, 34,-11958, 36,2733, 38,1699, 41,137, 43,27392, 48,130, 52,-32, 53,143, 54,1, 58,85 + , 5,66, 15,466, 22,460, 34,-11958, 36,2733, 38,1699, 41,137, 43,32620, 48,130, 52,-48, 53,7, 54,1, 58,111 + , 8,14400, 15,482, 34,-11958, 36,2733, 38,1699, 41,138, 43,29440, 48,130, 52,4, 53,51, 54,1, 58,94 + , 8,14400, 15,482, 34,-11958, 36,2733, 38,1699, 41,138, 43,32628, 48,130, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 101 */ + , 8,4602, 9,54, 11,6075, 15,466, 26,4284, 27,-4870, 28,813, 30,3488, 34,2382, 37,0, 38,2345, 41,139, 43,27392, 48,200, 52,-32, 53,143, 54,1, 58,85 + , 8,4602, 9,54, 11,6075, 15,466, 26,4284, 27,-4870, 28,813, 30,3488, 34,2382, 37,0, 38,2345, 41,139, 43,32620, 48,200, 52,-48, 53,7, 54,1, 58,111 + , 8,4602, 9,94, 11,5737, 15,466, 26,4284, 27,-2203, 28,3343, 30,3578, 34,2382, 37,0, 38,2345, 41,140, 43,27392, 48,200, 51,32, 52,-32, 53,143, 54,1, 58,85 + , 8,4602, 9,94, 11,5737, 15,466, 26,4284, 27,-2203, 28,3343, 30,3578, 34,2382, 37,0, 38,2345, 41,140, 43,32620, 48,200, 51,32, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 102 */ + , 8,5310, 9,103, 11,7087, 15,466, 28,-884, 29,727, 30,2982, 34,-7972, 37,0, 38,1372, 41,141, 43,30464, 48,60, 52,5, 53,142, 54,1, 58,98 + , 8,5310, 9,103, 11,7087, 15,466, 28,-884, 29,727, 30,2982, 34,-7972, 37,0, 38,1372, 41,141, 43,32632, 48,60, 52,-48, 53,7, 54,1, 58,111 + , 5,28, 8,4602, 9,75, 11,6412, 15,482, 22,460, 26,-116, 28,1782, 30,-2786, 34,-81, 36,3358, 38,1372, 41,142, 43,27392, 48,60, 52,-32, 53,143, 54,1, 58,85 + , 5,28, 8,4602, 9,75, 11,6412, 15,482, 22,460, 26,-116, 28,1782, 30,-2786, 34,-81, 36,3358, 38,1372, 41,142, 43,32620, 48,60, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 103 */ + , 5,19, 8,6490, 9,24, 11,6637, 15,466, 22,-753, 28,-1586, 30,2484, 34,-5186, 35,-3172, 36,3462, 38,1591, 41,143, 43,24320, 48,210, 52,5, 53,76, 54,1, 58,74 + , 8,7906, 9,18, 11,3487, 15,482, 28,0, 30,3186, 34,-5186, 37,0, 38,1591, 41,144, 43,27904, 48,210, 52,-4, 53,128, 54,1, 58,87 + , 8,7906, 9,18, 11,3487, 15,482, 28,0, 30,3186, 34,-5186, 37,0, 38,1591, 41,144, 43,32622, 48,210, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 104 */ + , 34,-8800, 36,5003, 38,1035, 41,145, 43,27648, 48,60, 52,30, 53,73, 54,1, 58,87 + , 34,-8800, 36,5003, 38,1035, 41,145, 43,32621, 48,60, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 105 */ + , 34,-8800, 35,-2544, 36,1544, 38,-542, 41,146, 43,16896, 48,60, 52,44, 53,71, 54,1, 58,78 + , 34,-8800, 35,-2544, 36,1544, 38,-542, 41,146, 43,27459, 48,60, 52,-31, 53,72, 54,1, 58,85 + , 34,-8800, 35,-2544, 36,1544, 38,-542, 41,146, 43,32620, 48,60, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 106 */ + , 8,10561, 34,-8800, 37,0, 38,-281, 41,147, 43,28416, 48,30, 52,-28, 53,113, 58,89 + , 8,10561, 34,-8800, 37,0, 38,-281, 41,147, 43,32624, 48,30, 52,-48, 53,7, 58,111 + , 8,6726, 34,-5053, 35,-2544, 36,1544, 38,-281, 41,148, 43,16640, 48,30, 52,44, 53,71, 54,1, 58,78 + , 8,6726, 34,-5053, 35,-2544, 36,1544, 38,-281, 41,148, 43,27458, 48,30, 52,-31, 53,72, 54,1, 58,85 + , 8,6726, 34,-5053, 35,-2544, 36,1544, 38,-281, 41,148, 43,32620, 48,30, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 107 */ + , 34,-8800, 35,-3172, 36,2412, 38,213, 41,149, 43,27392, 48,60, 52,24, 53,70, 54,1, 58,86 + , 34,-8800, 35,-3172, 36,2412, 38,213, 41,149, 43,32620, 48,60, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 108 */ + , 9,96, 34,-8800, 36,256, 38,688, 41,150, 43,25088, 48,37, 52,-20, 53,127, 54,1, 58,76 + , 9,96, 34,-8800, 36,256, 38,688, 41,150, 43,32611, 48,37, 52,-48, 53,7, 54,1, 58,111 + , 34,-8800, 37,0, 38,811, 41,151, 43,30720, 48,37, 52,-39, 53,113, 58,98 + , 34,-8800, 37,0, 38,811, 41,151, 43,32633, 48,37, 52,-48, 53,7, 58,111 + +/* Preset 109 */ + , 2,-3, 3,-3, 34,-11958, 37,23, 38,-667, 41,152, 43,14592, 48,50, 52,-14, 53,45, 54,1, 58,62 + , 2,-3, 3,-3, 34,-11958, 37,23, 38,-667, 41,152, 43,29498, 48,50, 52,32, 53,47, 54,1, 58,94 + , 34,-11958, 37,23, 38,-667, 41,152, 43,32628, 48,50, 52,-48, 53,7, 54,1, 58,111 + , 2,-3, 3,-3, 34,-11958, 37,23, 38,-667, 41,153, 43,14592, 48,50, 52,-6, 53,45, 54,1, 58,62 + +/* Preset 110 */ + , 5,9, 21,-1675, 22,-780, 34,-8800, 36,3975, 37,13, 38,-667, 41,154, 43,17920, 48,100, 52,30, 53,55, 54,1, 58,87 + , 5,9, 21,-1675, 22,-780, 34,-8800, 36,3975, 37,13, 38,-667, 41,154, 43,19015, 48,100, 52,15, 53,56, 54,1, 58,90 + , 5,9, 21,-1675, 22,-780, 34,-8800, 36,3975, 37,13, 38,-667, 41,154, 43,20043, 48,100, 52,-45, 53,57, 54,1, 58,94 + , 5,9, 21,-1675, 22,-780, 34,-8800, 36,3975, 37,13, 38,-667, 41,154, 43,21071, 48,100, 52,24, 53,58, 54,1, 58,98 + , 5,9, 21,-1675, 22,-780, 34,-8800, 36,3975, 37,13, 38,-667, 41,154, 43,31571, 48,100, 52,15, 53,59, 54,1, 58,102 + , 5,9, 21,-1675, 22,-780, 34,-8800, 36,3975, 37,13, 38,-667, 41,154, 43,32636, 48,100, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 111 */ + , 5,9, 21,-1675, 22,-780, 34,-8856, 35,-7972, 36,3684, 37,76, 38,-802, 41,155, 43,29440, 48,50, 52,29, 53,47, 54,1, 58,94 + , 5,9, 21,-1675, 22,-780, 34,-8856, 35,-7972, 36,3684, 37,76, 38,-802, 41,155, 43,32628, 48,50, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 112 */ + , 34,-8800, 36,968, 37,412, 38,1035, 41,156, 43,19456, 48,60, 52,29, 53,138, 54,1, 58,84 + , 34,-8800, 36,968, 37,412, 38,1035, 41,156, 43,28237, 48,60, 52,7, 53,139, 54,1, 58,89 + , 34,-8800, 36,968, 37,412, 38,1035, 41,156, 43,32623, 48,60, 52,-48, 53,7, 54,1, 58,111 + , 34,-8800, 36,-125, 38,-148, 41,157, 48,60, 52,19, 53,114, 58,107 + +/* Preset 113 */ + , 34,-8800, 36,372, 38,-148, 41,158, 43,29696, 48,120, 52,50, 53,114, 58,95 + , 34,-8800, 36,372, 38,-148, 41,158, 43,32629, 48,120, 52,-48, 53,7, 58,111 + , 34,-8800, 36,372, 38,-148, 41,159, 43,22016, 48,120, 52,-23, 53,127, 54,1, 58,64 + , 34,-8800, 36,372, 38,-148, 41,159, 43,32599, 48,120, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 114 */ + , 34,-8800, 35,-2400, 36,1035, 38,1035, 41,160, 43,27904, 48,60, 52,32, 53,109, 54,1, 58,88 + , 34,-8800, 35,-2400, 36,1035, 38,1035, 41,160, 43,32622, 48,60, 52,-48, 53,7, 54,1, 58,111 + +/* Preset 115 */ + , 34,-11958, 36,-386, 38,-1378, 41,161, 43,31744, 51,-16, 52,-10, 53,113, 56,50, 58,102 + , 34,-11958, 36,-386, 38,-1378, 41,161, 43,32637, 51,-16, 52,-11, 53,7, 56,50, 58,111 + +/* Preset 116 */ + , 34,-8800, 36,1365, 38,-148, 41,162, 43,29952, 48,130, 51,-5, 52,-12, 53,95, 54,1, 56,50, 58,95 + , 34,-8800, 36,1365, 38,-148, 41,162, 43,32630, 48,130, 51,-5, 52,-24, 53,7, 54,1, 56,50, 58,111 + , 34,-8800, 36,1365, 38,338, 41,163, 48,130, 51,-11, 52,25, 53,112, 54,1, 56,50, 58,107 + +/* Preset 117 */ + , 34,-8800, 36,2837, 38,918, 41,164, 43,26624, 48,105, 51,-4, 52,-12, 53,95, 54,1, 56,50, 58,83 + , 34,-8800, 36,2837, 38,918, 41,164, 43,32617, 48,105, 51,-4, 52,-24, 53,7, 54,1, 56,50, 58,112 + +/* Preset 118 */ + , 7,516, 28,-386, 29,874, 30,4400, 34,-8800, 35,-4372, 36,372, 38,-949, 41,165, 43,26368, 48,120, 51,-12, 52,-12, 53,95, 54,1, 56,50, 58,81 + , 7,516, 28,-386, 29,874, 30,4400, 34,-8800, 35,-4372, 36,372, 38,-949, 41,165, 43,32616, 48,120, 51,-12, 52,-24, 53,7, 54,1, 56,50, 58,111 + , 7,591, 28,-2786, 30,-1586, 34,-8800, 36,736, 38,-949, 41,166, 43,28416, 48,120, 51,-12, 52,-14, 53,127, 54,1, 56,50, 58,89 + , 7,591, 28,-2786, 30,-1586, 34,-8800, 36,736, 38,-949, 41,166, 43,32624, 48,120, 51,-12, 52,-24, 53,7, 54,1, 56,50, 58,111 + +/* Preset 119 */ + , 34,915, 36,-2143, 38,-7053, 41,167, 43,28672, 48,7, 51,-6, 52,23, 53,115, 54,1, 56,50, 58,91 + , 34,915, 36,-2143, 38,-7053, 41,167, 43,32625, 48,7, 51,-6, 52,-24, 53,7, 54,1, 56,50, 58,111 + +/* Preset 120 */ + , 9,190, 34,-8800, 37,0, 38,-2197, 41,168, 43,26368, 51,-12, 52,-3, 53,148, 56,50, 58,81 + , 9,190, 34,-8800, 37,0, 38,-2197, 41,168, 43,32616, 51,-12, 52,-24, 53,7, 56,50, 58,111 + +/* Preset 121 */ + , 34,-8800, 36,2626, 38,-949, 41,169, 43,23296, 48,282, 51,-5, 52,19, 53,42, 56,50, 58,70 + , 34,-8800, 36,2626, 38,-949, 41,169, 43,32604, 48,282, 51,-5, 52,-24, 53,7, 56,50, 58,111 + +/* Preset 122 */ + , 0,500, 8,4602, 9,57, 11,3937, 26,2866, 27,-2332, 28,2484, 30,3533, 34,1776, 35,998, 36,2412, 38,1699, 41,170, 43,27904, 52,9, 53,140, 54,1, 56,50, 58,88 + , 8,4602, 9,57, 11,3937, 26,2866, 27,-2332, 28,2484, 30,3533, 34,1776, 35,998, 36,2412, 38,1699, 41,170, 43,32622, 52,-24, 53,7, 54,1, 56,50, 58,111 + , 8,5310, 9,57, 11,2587, 26,2866, 27,-2332, 28,3043, 30,3578, 34,-3986, 36,3358, 38,1699, 41,170, 43,30720, 52,9, 53,140, 54,1, 56,50, 58,99 + , 8,4602, 9,57, 11,3937, 26,2866, 27,-2332, 28,2484, 30,3533, 34,1776, 35,998, 36,2412, 38,1699, 41,170, 43,32633, 52,-24, 53,7, 54,1, 56,50, 58,111 + +/* Preset 123 */ + , 5,-55, 7,-599, 9,160, 21,-544, 22,460, 26,-2902, 30,3823, 34,-1382, 36,1092, 38,-386, 41,171, 43,32639, 48,50, 53,127, 54,1, 56,50, 58,51 + , 34,-8800, 35,-12000, 36,-12000, 41,171, 43,32612, 48,50, 52,-24, 53,7, 56,50, 58,111 + , 5,-599, 7,-599, 9,160, 21,-544, 22,460, 26,-1702, 28,-1586, 34,-1382, 35,-2701, 36,-884, 37,916, 38,315, 41,171, 43,32639, 48,50, 53,127, 54,1, 56,50, 58,35 + , 5,-599, 7,-599, 9,160, 21,-3172, 22,460, 26,-1702, 28,-1586, 34,-8856, 35,-2701, 36,5382, 37,916, 38,1958, 41,171, 43,21248, 48,50, 53,127, 54,1, 56,50, 58,35 + +/* Preset 124 */ + , 2,-30, 3,32, 9,103, 37,0, 38,-1079, 41,172, 43,27392, 48,105, 51,-3, 52,17, 53,141, 54,1, 56,50, 58,86 + , 9,103, 37,0, 38,-1079, 41,172, 43,32620, 48,105, 51,-3, 52,-24, 53,7, 54,1, 56,50, 58,111 + , 2,-30, 3,32, 9,112, 37,0, 38,-1079, 41,173, 43,27392, 48,105, 52,16, 53,141, 54,3, 56,50, 58,85 + , 9,103, 37,0, 38,-1079, 41,173, 43,32620, 48,105, 51,-3, 52,-24, 53,7, 54,1, 56,50, 58,111 + +/* Preset 125 */ + , 5,591, 8,4838, 9,9, 10,3543, 13,118, 22,258, 34,542, 36,3565, 37,0, 38,-148, 41,174, 43,15104, 48,172, 51,-12, 52,9, 53,140, 54,1, 56,50, 58,85 + , 5,591, 8,4838, 9,9, 10,3543, 13,118, 22,258, 34,542, 36,3565, 37,0, 38,-148, 41,174, 43,27196, 48,172, 51,-12, 52,9, 53,140, 54,1, 56,50, 58,85 + , 5,591, 8,4838, 9,9, 10,3543, 13,118, 22,258, 34,542, 36,3565, 37,0, 38,-148, 41,174, 43,32619, 48,172, 51,-12, 52,-24, 53,7, 54,1, 56,50, 58,111 + , 5,47, 8,4838, 9,9, 10,3543, 13,118, 22,258, 34,542, 36,3565, 37,0, 38,-148, 41,174, 48,172, 51,-24, 52,2, 53,142, 54,1, 56,50, 58,127 + +/* Preset 126 */ + , 17,217, 34,1587, 37,0, 38,-148, 41,175, 43,28416, 48,45, 51,-8, 52,23, 53,117, 54,1, 56,50, 58,98 + , 34,1587, 37,0, 38,-148, 41,175, 43,32624, 48,45, 51,-8, 52,-24, 53,7, 54,1, 56,50, 58,111 + , 17,-287, 34,1587, 37,0, 38,-148, 41,175, 43,31744, 48,45, 51,-8, 52,23, 53,117, 54,1, 56,50, 58,103 + , 34,1587, 37,0, 38,-148, 41,175, 43,32637, 48,45, 51,-8, 52,-24, 53,7, 54,1, 56,50, 58,111 + +/* Preset 127 */ + , 17,-216, 34,-11958, 37,0, 38,-148, 41,176, 43,29184, 51,-12, 52,17, 53,93, 56,50, 58,93 + , 17,-216, 34,-11958, 37,0, 38,-148, 41,176, 43,32627, 51,-12, 52,-24, 53,7, 56,50, 58,111 + , 17,288, 34,-11958, 37,0, 38,-148, 41,176, 43,29952, 51,-12, 52,17, 53,93, 56,50, 58,96 + , 17,288, 34,-11958, 37,0, 38,-148, 41,176, 43,32630, 51,-12, 52,-24, 53,7, 56,50, 58,111 + +/* Preset 128 */ + , 36,-3986, 38,-148, 41,177, 43,6939, 48,142, 52,-31, 53,90, 58,45 + , 36,-125, 38,-542, 41,177, 43,7196, 48,142, 52,19, 53,140, 54,1, 58,51 + , 36,-2332, 38,-148, 41,177, 43,7196, 48,142, 52,-48, 53,94, 58,54 + , 37,0, 38,-148, 41,177, 43,7453, 48,112, 52,-48, 53,96, 57,7, 58,57 + , 37,0, 38,-148, 41,177, 43,7710, 48,112, 52,-12, 53,148, 57,7, 58,42 + , 37,0, 38,-2197, 41,177, 43,7967, 48,37, 52,4, 53,111, 58,42 + , 35,-1461, 37,0, 38,-2197, 41,177, 43,8224, 48,127, 53,146, 58,31 + , 36,-5572, 38,-5853, 41,177, 43,8481, 52,-48, 53,94, 58,51 + , 36,-1919, 38,-2197, 41,177, 43,8738, 48,127, 52,-48, 53,94, 58,51 + , 36,1872, 38,-2197, 41,177, 43,8738, 48,127, 52,-34, 53,139, 54,1, 58,44 + , 36,1763, 38,-2050, 41,177, 43,8995, 48,30, 52,2, 53,92, 58,50 + , 37,0, 38,-1867, 41,177, 43,9252, 48,7, 52,24, 53,92, 58,48 + , 36,-1586, 38,-1378, 41,177, 43,9509, 48,135, 52,-48, 53,94, 58,56 + , 36,736, 38,811, 41,177, 43,9766, 48,45, 52,-43, 53,144, 58,56 + , 17,-216, 36,-521, 38,-802, 41,177, 43,10023, 48,90, 52,-21, 53,117, 54,1, 58,46 + , 17,-216, 36,-261, 38,-542, 41,177, 43,10023, 48,90, 52,47, 53,117, 54,1, 58,79 + , 36,372, 38,213, 41,177, 43,10280, 48,112, 52,8, 53,144, 58,52 + , 36,-386, 38,-1079, 41,177, 43,10280, 48,112, 52,-48, 53,95, 54,1, 58,51 + , 17,-216, 36,1872, 38,1591, 41,177, 43,10537, 48,112, 52,18, 53,95, 54,1, 58,69 + , 17,146, 35,-7972, 36,-1586, 37,989, 38,-1079, 41,177, 43,10794, 48,100, 52,-37, 53,150, 54,1, 57,1, 58,50 + , 17,-74, 36,1654, 38,1372, 41,177, 43,11051, 48,67, 52,-25, 53,95, 54,1, 58,68 + , 17,146, 34,-7390, 35,-7972, 36,-12000, 37,989, 38,-3067, 41,177, 43,11308, 48,67, 52,-46, 53,150, 54,1, 57,1, 58,52 + , 17,-74, 36,1426, 38,1145, 41,177, 43,11565, 48,67, 52,-25, 53,95, 54,1, 58,67 + , 17,75, 36,2198, 38,1145, 41,177, 43,11822, 48,45, 52,-17, 53,150, 54,1, 57,1, 58,54 + , 36,1317, 38,1035, 41,177, 43,12079, 48,52, 52,-4, 53,95, 54,1, 58,66 + , 36,1200, 38,1145, 41,177, 43,12336, 48,67, 52,40, 53,95, 54,1, 58,63 + , 17,146, 36,1980, 38,1699, 41,177, 43,12593, 52,47, 53,115, 54,1, 58,68 + , 17,288, 36,856, 38,575, 41,177, 43,12850, 48,90, 52,-25, 53,95, 54,1, 58,61 + , 17,-216, 36,1763, 38,1482, 41,177, 43,13107, 48,142, 52,-7, 53,151, 54,1, 58,59 + , 17,-145, 36,1980, 38,1262, 41,177, 43,13364, 48,75, 52,47, 53,119, 54,1, 58,74 + , 17,-216, 36,1426, 38,1035, 41,177, 43,13621, 48,90, 52,8, 53,118, 54,1, 58,71 + , 17,146, 35,-4372, 36,1200, 38,2345, 41,177, 43,13878, 48,52, 52,35, 53,97, 54,3, 58,70 + , 17,-74, 36,1654, 38,1372, 41,177, 43,14135, 48,90, 52,47, 53,115, 54,1, 58,65 + , 17,146, 35,-4372, 36,619, 38,2345, 41,177, 43,14392, 48,202, 52,-14, 53,98, 58,72 + , 17,-216, 36,1654, 38,1372, 41,177, 43,14649, 52,47, 53,115, 54,1, 58,74 + , 17,-429, 36,1654, 38,811, 41,177, 43,14906, 53,99, 54,1, 58,82 + , 17,-287, 36,1763, 38,1482, 41,177, 43,15163, 48,165, 52,18, 53,151, 54,1, 58,66 + , 17,358, 35,-3670, 36,0, 38,-1702, 41,177, 43,15420, 52,21, 53,100, 58,78 + , 17,217, 36,0, 38,-1079, 41,177, 43,15677, 52,-18, 53,101, 58,77 + , 17,-287, 36,0, 38,-667, 41,177, 43,15934, 52,43, 53,102, 58,82 + , 17,-429, 36,-261, 38,-1702, 41,177, 43,16191, 52,-46, 53,103, 58,85 + , 17,-429, 36,-125, 38,-1224, 41,177, 43,16448, 52,21, 53,104, 58,83 + , 17,217, 36,619, 38,-24, 41,177, 43,16705, 52,50, 53,112, 54,1, 58,89 + , 17,288, 36,619, 38,-24, 41,177, 43,16962, 52,50, 53,112, 54,1, 58,95 + , 17,-287, 36,-261, 38,-2050, 41,177, 43,17219, 52,50, 53,114, 58,85 + , 17,-287, 36,-261, 38,-667, 41,177, 43,17476, 52,50, 53,114, 58,91 + , 17,-358, 36,0, 38,-1224, 41,177, 43,17733, 52,-14, 53,105, 58,85 + , 17,-358, 36,813, 38,-7053, 41,177, 43,17990, 48,90, 52,27, 53,106, 58,83 + , 17,217, 35,-2701, 38,-7053, 41,177, 43,18247, 48,210, 52,36, 53,107, 54,1, 57,2, 58,87 + , 17,217, 35,-1034, 38,-7053, 41,177, 43,18504, 48,157, 52,36, 53,107, 54,1, 57,2, 58,91 + , 17,288, 36,1200, 38,-2050, 41,177, 43,18761, 48,180, 52,-25, 53,108, 57,3, 58,90 + , 17,358, 36,1317, 38,-1224, 41,177, 43,19018, 48,90, 52,-46, 53,110, 57,3, 58,102 + , 17,288, 36,-386, 38,-949, 41,177, 43,19275, 48,45, 52,40, 53,116, 58,100 + , 17,358, 36,-3986, 38,-7053, 41,177, 43,19532, 48,37, 52,-45, 53,113, 58,104 + , 17,288, 36,-2544, 38,-7053, 41,177, 43,19789, 48,37, 52,-45, 53,113, 58,111 + , 17,-216, 36,0, 38,-2197, 41,177, 43,20046, 48,150, 52,35, 53,120, 57,4, 58,87 + , 17,-216, 36,0, 38,-2821, 41,177, 43,20303, 48,67, 52,35, 53,120, 57,4, 58,105 + , 17,-429, 36,-667, 38,-4653, 41,177, 43,20560, 48,277, 52,-32, 53,126, 54,1, 57,5, 58,88 + , 17,-358, 36,968, 38,455, 41,177, 43,20817, 48,217, 52,-42, 53,126, 54,1, 57,5, 58,89 + , 17,288, 36,-386, 38,-2420, 41,177, 43,21074, 52,-14, 53,105, 58,95 + , 17,358, 34,-2514, 36,619, 38,338, 41,177, 43,21331, 52,4, 53,97, 54,3, 58,104 + , 17,358, 34,-6688, 36,619, 38,-148, 41,177, 43,21331, 52,47, 53,119, 54,1, 58,73 + , 17,288, 36,1200, 38,-148, 41,177, 43,21588, 52,-12, 53,91, 54,1, 58,105 + , 17,-429, 36,-1586, 38,-949, 41,177, 43,21845, 48,285, 52,21, 53,100, 58,89 + , 17,-429, 36,-1586, 37,0, 38,-949, 41,177, 43,21845, 48,285, 53,146, 58,71 + , 17,-358, 36,813, 38,-667, 41,177, 43,22102, 48,202, 52,-18, 53,101, 57,6, 58,104 + , 17,-429, 36,1872, 38,1035, 41,177, 43,22359, 48,165, 52,-25, 53,95, 54,1, 57,6, 58,113 + , 17,-429, 36,-1586, 37,380, 38,1035, 41,177, 43,22359, 48,165, 52,50, 53,112, 54,1, 57,6, 58,125 + +}; + +int _awe_sf_sample_data[] = { + 494, 11149, 17721, 17725, + 17771, 35408, 39898, 39901, + 65209, 86715, 86778, 86782, + 39947, 55375, 65159, 65163, + 86828, 93676, 93802, 93807, + 93853, 99946, 99994, 99998, + 100044, 104192, 104246, 104507, + 104553, 107516, 109947, 109951 + , + 494, 11149, 17721, 17725, + 17771, 35408, 39898, 39901, + 65209, 86715, 86778, 86782, + 39947, 55375, 65159, 65163, + 86828, 93676, 93802, 93807, + 93853, 99946, 99994, 99998, + 100044, 104192, 104246, 104507, + 104553, 107516, 109947, 109951 + , + 494, 11149, 17721, 17725, + 17771, 35408, 39898, 39901, + 65209, 86715, 86778, 86782, + 39947, 55375, 65159, 65163, + 93853, 99946, 99994, 99998, + 104553, 107516, 109947, 109951 + , + 494, 11149, 17721, 17725, + 17771, 35408, 39898, 39901, + 65209, 86715, 86778, 86782, + 39947, 55375, 65159, 65163, + 86828, 93676, 93802, 93807, + 93853, 99946, 99994, 99998, + 100044, 104192, 104246, 104507, + 104553, 107516, 109947, 109951, + 494, 11149, 17721, 17725, + 17771, 35408, 39898, 39901, + 65209, 86715, 86778, 86782, + 39947, 55375, 65159, 65163, + 86828, 93676, 93802, 93807, + 93853, 99946, 99994, 99998, + 100044, 104192, 104246, 104507, + 104553, 107516, 109947, 109951 + , + 458744, 458761, 458809, 458813, + 458744, 458761, 458809, 458813, + 458744, 458761, 458809, 458813, + 109997, 111117, 111165, 111169, + 104553, 107516, 109947, 109951, + 497937, 497944, 498216, 498220, + 430271, 430340, 430406, 430410, + 104553, 107516, 109947, 109951 + , + 109997, 111117, 111165, 111169, + 104553, 107516, 109947, 109951 + , + 114245, 115539, 115631, 115635, + 104553, 107516, 109947, 109951, + 259435, 262219, 262280, 262284, + 262330, 265870, 265909, 265912, + 104553, 107516, 109947, 109951 + , + 111215, 114051, 114195, 114199, + 104553, 107516, 109947, 109951 + , + 421857, 422553, 422634, 422638, + 446722, 451551, 452134, 452138, + 104553, 107516, 109947, 109951 + , + 491098, 491105, 491166, 491170, + 491098, 491105, 491166, 491170, + 490837, 490844, 491048, 491052, + 104553, 107516, 109947, 109951 + , + 430271, 430340, 430406, 430410, + 430271, 430340, 430406, 430410, + 104553, 107516, 109947, 109951, + 452184, 452253, 452319, 452323, + 452184, 452253, 452319, 452323, + 104553, 107516, 109947, 109951 + , + 421857, 422553, 422634, 422638, + 421857, 422553, 422634, 422638, + 104553, 107516, 109947, 109951 + , + 427295, 428083, 428107, 428111, + 104553, 107516, 109947, 109951 + , + 419807, 419814, 420783, 420786, + 104553, 107516, 109947, 109951 + , + 446722, 451551, 452134, 452138 + , + 246278, 250056, 250108, 250112, + 104553, 107516, 109947, 109951 + , + 458074, 458143, 458209, 458213, + 104553, 107516, 109947, 109951, + 452184, 452253, 452319, 452323, + 104553, 107516, 109947, 109951 + , + 452369, 454984, 455039, 455043, + 455089, 457990, 458024, 458028, + 104553, 107516, 109947, 109951 + , + 452369, 454984, 455039, 455043, + 455089, 457990, 458024, 458028, + 104553, 107516, 109947, 109951, + 170819, 172904, 178282, 178286, + 104553, 107516, 109947, 109951 + , + 452184, 452253, 452319, 452323, + 104553, 107516, 109947, 109951, + 131469, 132834, 132896, 132900, + 131469, 132834, 132896, 132900, + 104553, 107516, 109947, 109951 + , + 181530, 182445, 182499, 182503, + 452184, 452253, 452319, 452323, + 104553, 107516, 109947, 109951, + 458074, 458143, 458209, 458213, + 104553, 107516, 109947, 109951 + , + 298212, 299191, 299256, 299260, + 299306, 299872, 299922, 299925, + 299971, 300795, 300825, 300828, + 104553, 107516, 109947, 109951, + 282298, 282367, 282433, 282437, + 104553, 107516, 109947, 109951 + , + 181530, 182445, 182499, 182503, + 104553, 107516, 109947, 109951 + , + 298212, 299191, 299256, 299260, + 299971, 300795, 300825, 300828, + 104553, 107516, 109947, 109951, + 282298, 282367, 282433, 282437, + 104553, 107516, 109947, 109951 + , + 282483, 286210, 286307, 286311, + 286357, 291482, 291545, 291549, + 273246, 279414, 279482, 279486, + 104553, 107516, 109947, 109951 + , + 268319, 273119, 273196, 273200, + 273246, 279414, 279482, 279486, + 104553, 107516, 109947, 109951 + , + 279532, 280933, 281008, 281012, + 104553, 107516, 109947, 109951, + 291595, 291604, 291709, 291713, + 104553, 107516, 109947, 109951 + , + 279532, 280933, 281008, 281012, + 296401, 297994, 298162, 298166 + , + 281058, 281824, 281889, 281893, + 104553, 107516, 109947, 109951 + , + 293047, 294792, 294874, 294878, + 294924, 296296, 296351, 296355, + 291759, 292954, 292997, 293001, + 104553, 107516, 109947, 109951, + 291595, 291604, 291709, 291713, + 104553, 107516, 109947, 109951 + , + 293047, 294792, 294874, 294878, + 294924, 296296, 296351, 296355, + 291759, 292954, 292997, 293001, + 296401, 297994, 298162, 298166, + 104553, 107516, 109947, 109951 + , + 281939, 282238, 282248, 282252, + 104553, 107516, 109947, 109951 + , + 236031, 237439, 237561, 237565, + 250158, 253567, 253631, 253635, + 104553, 107516, 109947, 109951 + , + 237611, 238361, 238511, 238515, + 250158, 253567, 253631, 253635, + 104553, 107516, 109947, 109951 + , + 246108, 246117, 246228, 246232, + 250158, 253567, 253631, 253635, + 104553, 107516, 109947, 109951 + , + 238561, 240726, 240897, 240901, + 250158, 253567, 253631, 253635, + 104553, 107516, 109947, 109951 + , + 240947, 242765, 243063, 243067, + 111215, 114051, 114195, 114199, + 104553, 107516, 109947, 109951 + , + 243113, 245458, 245572, 245576, + 250158, 253567, 253631, 253635, + 104553, 107516, 109947, 109951 + , + 245622, 245631, 246058, 246062, + 430456, 430745, 444201, 444204, + 104553, 107516, 109947, 109951, + 458259, 458274, 458324, 458328, + 104553, 107516, 109947, 109951 + , + 238561, 240726, 240897, 240901, + 250158, 253567, 253631, 253635, + 104553, 107516, 109947, 109951, + 246108, 246117, 246228, 246232, + 250158, 253567, 253631, 253635, + 104553, 107516, 109947, 109951 + , + 226907, 228598, 228634, 228638, + 228684, 230386, 230446, 230450, + 230496, 231531, 231577, 231581, + 231627, 232659, 232697, 232701, + 232747, 234316, 234376, 234380, + 104553, 107516, 109947, 109951 + , + 226907, 228598, 228634, 228638, + 228684, 230386, 230446, 230450, + 230496, 231531, 231577, 231581, + 231627, 232659, 232697, 232701, + 232747, 234316, 234376, 234380, + 104553, 107516, 109947, 109951 + , + 223282, 224409, 224477, 224481, + 224527, 225326, 225369, 225373, + 104553, 107516, 109947, 109951 + , + 225419, 226721, 226857, 226861, + 224527, 225326, 225369, 225373, + 104553, 107516, 109947, 109951 + , + 184452, 187061, 193756, 193760, + 193806, 197221, 202448, 202452, + 202498, 205596, 213220, 213224, + 104553, 107516, 109947, 109951 + , + 234426, 235953, 235981, 235985, + 104553, 107516, 109947, 109951 + , + 250158, 253567, 253631, 253635, + 104553, 107516, 109947, 109951 + , + 365242, 372321, 372937, 372940, + 365242, 372321, 372937, 372940, + 365242, 372321, 372937, 372940, + 365242, 372321, 372937, 372940, + 365242, 372321, 372937, 372940, + 365242, 372321, 372937, 372940, + 365242, 372321, 372937, 372940, + 104553, 107516, 109947, 109951 + , + 184452, 187061, 193756, 193760, + 193806, 197221, 202448, 202452, + 202498, 205596, 213220, 213224, + 104553, 107516, 109947, 109951 + , + 184452, 187061, 193756, 193760, + 193806, 197221, 202448, 202452, + 202498, 205596, 213220, 213224, + 104553, 107516, 109947, 109951 + , + 213270, 214542, 223232, 223236, + 104553, 107516, 109947, 109951 + , + 213270, 214542, 223232, 223236, + 104553, 107516, 109947, 109951, + 213270, 214542, 223232, 223236, + 104553, 107516, 109947, 109951 + , + 468964, 469302, 477719, 477722, + 104553, 107516, 109947, 109951, + 477768, 477803, 486865, 486869, + 104553, 107516, 109947, 109951 + , + 170819, 172904, 178282, 178286, + 104553, 107516, 109947, 109951, + 491216, 494215, 494270, 494274, + 104553, 107516, 109947, 109951 + , + 477768, 477803, 486865, 486869, + 104553, 107516, 109947, 109951 + , + 422684, 422691, 427246, 427249, + 104553, 107516, 109947, 109951 + , + 152314, 153942, 153983, 153987, + 145685, 147283, 147316, 147320, + 147366, 148964, 149014, 149018, + 149064, 150518, 150556, 150560, + 150606, 152208, 152264, 152268, + 104553, 107516, 109947, 109951 + , + 154033, 155265, 155359, 155363, + 155409, 156684, 156738, 156742, + 156788, 157862, 157904, 157908, + 157954, 159458, 159518, 159522, + 104553, 107516, 109947, 109951 + , + 159568, 161399, 161528, 161531, + 157954, 159458, 159518, 159522, + 104553, 107516, 109947, 109951 + , + 161577, 162997, 163058, 163061, + 163107, 163947, 164005, 164009, + 104553, 107516, 109947, 109951 + , + 128835, 130255, 130315, 130319, + 104553, 107516, 109947, 109951 + , + 134414, 139947, 140009, 140013, + 140059, 145048, 145094, 145639, + 104553, 107516, 109947, 109951, + 134414, 139947, 140009, 140013, + 140059, 145048, 145094, 145639, + 104553, 107516, 109947, 109951 + , + 430456, 430745, 444201, 444204, + 104553, 107516, 109947, 109951 + , + 430456, 430745, 444201, 444204, + 104553, 107516, 109947, 109951 + , + 115681, 116735, 116826, 116830, + 116876, 118026, 118099, 118103, + 118149, 119716, 119783, 119787, + 119833, 120476, 120524, 120528, + 120574, 121437, 121479, 121483, + 121529, 122659, 122715, 122719, + 122765, 123901, 123949, 123953, + 104553, 107516, 109947, 109951 + , + 115681, 116735, 116826, 116830, + 116876, 118026, 118099, 118103, + 118149, 119716, 119783, 119787, + 119833, 120476, 120524, 120528, + 120574, 121437, 121479, 121483, + 121529, 122659, 122715, 122719, + 122765, 123901, 123949, 123953, + 104553, 107516, 109947, 109951 + , + 115681, 116735, 116826, 116830, + 116876, 118026, 118099, 118103, + 118149, 119716, 119783, 119787, + 119833, 120476, 120524, 120528, + 120574, 121437, 121479, 121483, + 121529, 122659, 122715, 122719, + 122765, 123901, 123949, 123953, + 104553, 107516, 109947, 109951 + , + 116876, 118026, 118099, 118103, + 118149, 119716, 119783, 119787, + 119833, 120476, 120524, 120528, + 120574, 121437, 121479, 121483, + 121529, 122659, 122715, 122719, + 122765, 123901, 123949, 123953, + 104553, 107516, 109947, 109951 + , + 123999, 124832, 124886, 124890, + 124936, 126114, 126157, 126161, + 126207, 127166, 127200, 127204, + 104553, 107516, 109947, 109951 + , + 127250, 128730, 128785, 128789, + 104553, 107516, 109947, 109951 + , + 130365, 131304, 131419, 131423, + 127250, 128730, 128785, 128789, + 104553, 107516, 109947, 109951 + , + 132946, 133543, 133618, 133622, + 133668, 134255, 134364, 134368, + 104553, 107516, 109947, 109951 + , + 131469, 132834, 132896, 132900, + 104553, 107516, 109947, 109951, + 164055, 165356, 165410, 165414, + 104553, 107516, 109947, 109951 + , + 131469, 132834, 132896, 132900, + 104553, 107516, 109947, 109951, + 170819, 172904, 178282, 178286, + 104553, 107516, 109947, 109951 + , + 164055, 165356, 165410, 165414, + 104553, 107516, 109947, 109951 + , + 170819, 172904, 178282, 178286, + 104553, 107516, 109947, 109951, + 164055, 165356, 165410, 165414, + 104553, 107516, 109947, 109951 + , + 165460, 165467, 170770, 170773, + 104553, 107516, 109947, 109951, + 170819, 172904, 178282, 178286, + 104553, 107516, 109947, 109951 + , + 170819, 172904, 178282, 178286, + 104553, 107516, 109947, 109951 + , + 178332, 179476, 179514, 179518, + 104553, 107516, 109947, 109951 + , + 178332, 179476, 179514, 179518, + 104553, 107516, 109947, 109951 + , + 444250, 446618, 446673, 446676, + 104553, 107516, 109947, 109951, + 444250, 446618, 446673, 446676, + 104553, 107516, 109947, 109951 + , + 430456, 430745, 444201, 444204, + 104553, 107516, 109947, 109951, + 458259, 458274, 458324, 458328, + 104553, 107516, 109947, 109951 + , + 165460, 165467, 170770, 170773, + 104553, 107516, 109947, 109951, + 444250, 446618, 446673, 446676, + 104553, 107516, 109947, 109951 + , + 165460, 165467, 170770, 170773, + 104553, 107516, 109947, 109951, + 458259, 458274, 458324, 458328, + 104553, 107516, 109947, 109951 + , + 430456, 430745, 444201, 444204, + 104553, 107516, 109947, 109951, + 111215, 114051, 114195, 114199, + 104553, 107516, 109947, 109951 + , + 170819, 172904, 178282, 178286, + 104553, 107516, 109947, 109951, + 468964, 469302, 477719, 477722, + 104553, 107516, 109947, 109951 + , + 430456, 430745, 444201, 444204, + 104553, 107516, 109947, 109951, + 458259, 458274, 458324, 458328, + 104553, 107516, 109947, 109951 + , + 245622, 245631, 246058, 246062, + 430456, 430745, 444201, 444204, + 104553, 107516, 109947, 109951, + 458259, 458274, 458324, 458328, + 104553, 107516, 109947, 109951 + , + 213270, 214542, 223232, 223236, + 104553, 107516, 109947, 109951, + 109997, 111117, 111165, 111169, + 104553, 107516, 109947, 109951 + , + 213270, 214542, 223232, 223236, + 104553, 107516, 109947, 109951 + , + 430456, 430745, 444201, 444204, + 104553, 107516, 109947, 109951, + 458259, 458274, 458324, 458328, + 104553, 107516, 109947, 109951 + , + 458374, 458443, 458509, 458513, + 104553, 107516, 109947, 109951, + 468964, 469302, 477719, 477722, + 104553, 107516, 109947, 109951 + , + 497937, 497944, 498216, 498220, + 104553, 107516, 109947, 109951, + 458559, 458628, 458694, 458698, + 104553, 107516, 109947, 109951 + , + 225419, 226721, 226857, 226861, + 497937, 497944, 498216, 498220, + 104553, 107516, 109947, 109951, + 273246, 279414, 279482, 279486, + 273246, 279414, 279482, 279486, + 273246, 279414, 279482, 279486, + 458559, 458628, 458694, 458698, + 104553, 107516, 109947, 109951 + , + 430456, 430745, 444201, 444204, + 104553, 107516, 109947, 109951, + 430456, 430745, 444201, 444204, + 104553, 107516, 109947, 109951 + , + 430456, 430745, 444201, 444204, + 104553, 107516, 109947, 109951 + , + 430456, 430745, 444201, 444204, + 104553, 107516, 109947, 109951, + 420832, 420839, 421808, 421811 + , + 430456, 430745, 444201, 444204, + 104553, 107516, 109947, 109951, + 430456, 430745, 444201, 444204, + 104553, 107516, 109947, 109951 + , + 421857, 422553, 422634, 422638, + 104553, 107516, 109947, 109951, + 446722, 451551, 452134, 452138, + 104553, 107516, 109947, 109951 + , + 268319, 273119, 273196, 273200, + 273246, 279414, 279482, 279486, + 104553, 107516, 109947, 109951, + 213270, 214542, 223232, 223236, + 104553, 107516, 109947, 109951 + , + 477768, 477803, 486865, 486869, + 104553, 107516, 109947, 109951, + 213270, 214542, 223232, 223236, + 104553, 107516, 109947, 109951 + , + 477768, 477803, 486865, 486869, + 104553, 107516, 109947, 109951, + 477768, 477803, 486865, 486869, + 104553, 107516, 109947, 109951 + , + 468964, 469302, 477719, 477722, + 104553, 107516, 109947, 109951, + 477768, 477803, 486865, 486869, + 104553, 107516, 109947, 109951 + , + 279532, 280933, 281008, 281012, + 430456, 430745, 444201, 444204, + 104553, 107516, 109947, 109951 + , + 265958, 268233, 268269, 268273, + 104553, 107516, 109947, 109951 + , + 259435, 262219, 262280, 262284, + 262330, 265870, 265909, 265912, + 104553, 107516, 109947, 109951 + , + 372986, 372993, 374146, 374149, + 104553, 107516, 109947, 109951, + 259435, 262219, 262280, 262284, + 262330, 265870, 265909, 265912, + 104553, 107516, 109947, 109951 + , + 253681, 259347, 259385, 259389, + 104553, 107516, 109947, 109951 + , + 430271, 430340, 430406, 430410, + 104553, 107516, 109947, 109951, + 372986, 372993, 374146, 374149, + 104553, 107516, 109947, 109951 + , + 179564, 181331, 181480, 181484, + 182549, 184354, 184402, 184406, + 104553, 107516, 109947, 109951, + 179564, 181331, 181480, 181484 + , + 226907, 228598, 228634, 228638, + 228684, 230386, 230446, 230450, + 230496, 231531, 231577, 231581, + 231627, 232659, 232697, 232701, + 232747, 234316, 234376, 234380, + 104553, 107516, 109947, 109951 + , + 182549, 184354, 184402, 184406, + 104553, 107516, 109947, 109951 + , + 458744, 458761, 458809, 458813, + 458859, 458874, 458945, 458949, + 104553, 107516, 109947, 109951, + 374195, 374202, 378658, 378661 + , + 374195, 374202, 378658, 378661, + 104553, 107516, 109947, 109951, + 430271, 430340, 430406, 430410, + 104553, 107516, 109947, 109951 + , + 359039, 361896, 361930, 361936, + 104553, 107516, 109947, 109951 + , + 372986, 372993, 374146, 374149, + 104553, 107516, 109947, 109951 + , + 317192, 322428, 324359, 324363, + 104553, 107516, 109947, 109951, + 365242, 372321, 372937, 372940 + , + 317192, 322428, 324359, 324363, + 104553, 107516, 109947, 109951 + , + 317192, 322428, 324359, 324363, + 104553, 107516, 109947, 109951, + 430271, 430340, 430406, 430410, + 104553, 107516, 109947, 109951 + , + 378707, 386731, 392236, 392240, + 104553, 107516, 109947, 109951 + , + 494320, 494327, 497887, 497891, + 104553, 107516, 109947, 109951 + , + 165460, 165467, 170770, 170773, + 104553, 107516, 109947, 109951 + , + 458995, 459002, 467284, 467288, + 104553, 107516, 109947, 109951, + 458995, 459002, 467284, 467288, + 104553, 107516, 109947, 109951 + , + 430271, 430340, 430406, 430410, + 104553, 107516, 109947, 109951, + 430271, 430340, 430406, 430410, + 430271, 430340, 430406, 430410 + , + 467334, 467341, 468914, 468918, + 104553, 107516, 109947, 109951, + 467334, 467341, 468914, 468918, + 104553, 107516, 109947, 109951 + , + 458995, 459002, 467284, 467288, + 458995, 459002, 467284, 467288, + 104553, 107516, 109947, 109951, + 468964, 469302, 477719, 477722 + , + 394105, 394112, 402261, 402265, + 104553, 107516, 109947, 109951, + 394105, 394112, 402261, 402265, + 104553, 107516, 109947, 109951 + , + 310498, 310505, 315890, 315893, + 104553, 107516, 109947, 109951, + 310498, 310505, 315890, 315893, + 104553, 107516, 109947, 109951 + , + 300874, 300881, 301290, 301293, + 458995, 459002, 467284, 467288, + 315939, 315946, 317143, 317146, + 324409, 324416, 326066, 326069, + 494320, 494327, 497887, 497891, + 364827, 364834, 365193, 365196, + 491098, 491105, 491166, 491170, + 315939, 315946, 317143, 317146, + 315939, 315946, 317143, 317146, + 458859, 458874, 458945, 458949, + 308850, 308857, 310449, 310452, + 308850, 308857, 310449, 310452, + 315939, 315946, 317143, 317146, + 486915, 486922, 490788, 490791, + 394105, 394112, 402261, 402265, + 394105, 394112, 402261, 402265, + 486915, 486922, 490788, 490791, + 317192, 322428, 324359, 324363, + 317192, 322428, 324359, 324363, + 498266, 504094, 509971, 509975, + 317192, 322428, 324359, 324363, + 498266, 504094, 509971, 509975, + 317192, 322428, 324359, 324363, + 498266, 504094, 509971, 509975, + 317192, 322428, 324359, 324363, + 317192, 322428, 324359, 324363, + 378707, 386731, 392236, 392240, + 317192, 322428, 324359, 324363, + 510021, 517480, 523309, 523313, + 408390, 414552, 418085, 418089, + 402311, 405925, 408340, 408344, + 326115, 328272, 329700, 329718, + 378707, 386731, 392236, 392240, + 329764, 329771, 331520, 331523, + 378707, 386731, 392236, 392240, + 331569, 331578, 332352, 332356, + 510021, 517480, 523309, 523313, + 332402, 332409, 335602, 335605, + 335651, 335658, 338371, 338374, + 338420, 338427, 341339, 341342, + 341388, 341395, 344475, 344478, + 344524, 344531, 348542, 348545, + 365242, 372321, 372937, 372940, + 365242, 372321, 372937, 372940, + 374195, 374202, 378658, 378661, + 374195, 374202, 378658, 378661, + 348591, 348598, 351266, 351269, + 351315, 351322, 354565, 354568, + 354614, 355735, 356287, 356300, + 354614, 355735, 356287, 356300, + 356346, 356353, 358990, 358993, + 362018, 362025, 364777, 364781, + 392286, 392293, 394056, 394059, + 372986, 372993, 374146, 374149, + 372986, 372993, 374146, 374149, + 418135, 418142, 419758, 419761, + 418135, 418142, 419758, 419761, + 428157, 428493, 430221, 430225, + 428157, 428493, 430221, 430225, + 348591, 348598, 351266, 351269, + 326115, 328272, 329700, 329718, + 408390, 414552, 418085, 418089, + 301339, 307602, 308800, 308804, + 332402, 332409, 335602, 335605, + 491098, 491105, 491166, 491170, + 335651, 335658, 338371, 338374, + 317192, 322428, 324359, 324363, + 365242, 372321, 372937, 372940 +}; + diff --git a/arch/dos/allg_snd/sound/drv/dma.c b/arch/dos/allg_snd/sound/drv/dma.c new file mode 100644 index 00000000..1fa73e54 --- /dev/null +++ b/arch/dos/allg_snd/sound/drv/dma.c @@ -0,0 +1,269 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * By Shawn Hargreaves, + * 1 Salisbury Road, + * Market Drayton, + * Shropshire, + * England, TF9 1AJ. + * + * DMA routines for the sound code. I used to feel slightly guilty + * because I pinched this code from MikMod, but then I looked at + * the GUS SDK and realised that Jean Paul Mikkers took it from + * there, so I think that justifies me in using it. + * + * See readme.txt for copyright information. + */ + + +#ifndef DJGPP +#error This file should only be used by the djgpp version of Allegro +#endif + +#include +#include +#include +#include + +#include "allegro.h" +#include "internal.h" + + +/* DMA Controler #1 (8-bit controller) */ +#define DMA1_STAT 0x08 /* read status register */ +#define DMA1_WCMD 0x08 /* write command register */ +#define DMA1_WREQ 0x09 /* write request register */ +#define DMA1_SNGL 0x0A /* write single bit register */ +#define DMA1_MODE 0x0B /* write mode register */ +#define DMA1_CLRFF 0x0C /* clear byte ptr flip/flop */ +#define DMA1_MCLR 0x0D /* master clear register */ +#define DMA1_CLRM 0x0E /* clear mask register */ +#define DMA1_WRTALL 0x0F /* write all mask register */ + +/* DMA Controler #2 (16-bit controller) */ +#define DMA2_STAT 0xD0 /* read status register */ +#define DMA2_WCMD 0xD0 /* write command register */ +#define DMA2_WREQ 0xD2 /* write request register */ +#define DMA2_SNGL 0xD4 /* write single bit register */ +#define DMA2_MODE 0xD6 /* write mode register */ +#define DMA2_CLRFF 0xD8 /* clear byte ptr flip/flop */ +#define DMA2_MCLR 0xDA /* master clear register */ +#define DMA2_CLRM 0xDC /* clear mask register */ +#define DMA2_WRTALL 0xDE /* write all mask register */ + +/* stuff for each DMA channel */ +#define DMA0_ADDR 0x00 /* chan 0 base adddress */ +#define DMA0_CNT 0x01 /* chan 0 base count */ +#define DMA1_ADDR 0x02 /* chan 1 base adddress */ +#define DMA1_CNT 0x03 /* chan 1 base count */ +#define DMA2_ADDR 0x04 /* chan 2 base adddress */ +#define DMA2_CNT 0x05 /* chan 2 base count */ +#define DMA3_ADDR 0x06 /* chan 3 base adddress */ +#define DMA3_CNT 0x07 /* chan 3 base count */ +#define DMA4_ADDR 0xC0 /* chan 4 base adddress */ +#define DMA4_CNT 0xC2 /* chan 4 base count */ +#define DMA5_ADDR 0xC4 /* chan 5 base adddress */ +#define DMA5_CNT 0xC6 /* chan 5 base count */ +#define DMA6_ADDR 0xC8 /* chan 6 base adddress */ +#define DMA6_CNT 0xCA /* chan 6 base count */ +#define DMA7_ADDR 0xCC /* chan 7 base adddress */ +#define DMA7_CNT 0xCE /* chan 7 base count */ + +#define DMA0_PAGE 0x87 /* chan 0 page register (refresh) */ +#define DMA1_PAGE 0x83 /* chan 1 page register */ +#define DMA2_PAGE 0x81 /* chan 2 page register */ +#define DMA3_PAGE 0x82 /* chan 3 page register */ +#define DMA4_PAGE 0x8F /* chan 4 page register (unuseable) */ +#define DMA5_PAGE 0x8B /* chan 5 page register */ +#define DMA6_PAGE 0x89 /* chan 6 page register */ +#define DMA7_PAGE 0x8A /* chan 7 page register */ + + +typedef struct { + unsigned char dma_disable; /* bits to disable dma channel */ + unsigned char dma_enable; /* bits to enable dma channel */ + unsigned short page; /* page port location */ + unsigned short addr; /* addr port location */ + unsigned short count; /* count port location */ + unsigned short single; /* single mode port location */ + unsigned short mode; /* mode port location */ + unsigned short clear_ff; /* clear flip-flop port location */ + unsigned char write; /* bits for write transfer */ + unsigned char read; /* bits for read transfer */ +} DMA_ENTRY; + + + +static DMA_ENTRY mydma[] = +{ + /* channel 0 */ + { 0x04, 0x00, DMA0_PAGE, DMA0_ADDR, DMA0_CNT, + DMA1_SNGL, DMA1_MODE, DMA1_CLRFF, 0x48, 0x44 }, + + /* channel 1 */ + { 0x05, 0x01, DMA1_PAGE, DMA1_ADDR, DMA1_CNT, + DMA1_SNGL,DMA1_MODE,DMA1_CLRFF,0x49,0x45 }, + + /* channel 2 */ + { 0x06, 0x02, DMA2_PAGE, DMA2_ADDR, DMA2_CNT, + DMA1_SNGL, DMA1_MODE, DMA1_CLRFF, 0x4A, 0x46 }, + + /* channel 3 */ + { 0x07, 0x03, DMA3_PAGE, DMA3_ADDR, DMA3_CNT, + DMA1_SNGL, DMA1_MODE, DMA1_CLRFF, 0x4B, 0x47 }, + + /* channel 4 */ + { 0x04, 0x00, DMA4_PAGE, DMA4_ADDR, DMA4_CNT, + DMA2_SNGL, DMA2_MODE, DMA2_CLRFF, 0x48, 0x44 }, + + /* channel 5 */ + { 0x05, 0x01, DMA5_PAGE, DMA5_ADDR, DMA5_CNT, + DMA2_SNGL, DMA2_MODE, DMA2_CLRFF, 0x49, 0x45 }, + + /* channel 6 */ + { 0x06, 0x02, DMA6_PAGE, DMA6_ADDR, DMA6_CNT, + DMA2_SNGL, DMA2_MODE, DMA2_CLRFF, 0x4A, 0x46 }, + + /* channel 7 */ + { 0x07, 0x03, DMA7_PAGE, DMA7_ADDR, DMA7_CNT, + DMA2_SNGL, DMA2_MODE, DMA2_CLRFF, 0x4B, 0x47 } +}; + + + +/* _dma_allocate_mem: + * Allocates the specified amount of conventional memory, ensuring that + * the returned block doesn't cross a page boundary. Sel will be set to + * the protected mode segment that should be used to free the block, and + * phys to the linear address of the block. On error, returns non-zero + * and sets sel and phys to 0. + */ +int _dma_allocate_mem(int bytes, int *sel, unsigned long *phys) +{ + int seg; + + /* allocate twice as much memory as we really need */ + seg = __dpmi_allocate_dos_memory((bytes*2 + 15) >> 4, sel); + + if (seg < 0) { + *sel = 0; + *phys = 0; + return -1; + } + + *phys = seg << 4; + + /* if it crosses a page boundary, use the second half of the block */ + if ((*phys>>16) != ((*phys+bytes)>>16)) + *phys += bytes; + + return 0; +} + +END_OF_FUNCTION(_dma_allocate_mem); + + + +/* dma_start: + * Starts the DMA controller for the specified channel, transferring + * size bytes from addr (the block must not cross a page boundary). + * If auto_init is set, it will use the endless repeat DMA mode. + */ +void _dma_start(int channel, unsigned long addr, int size, int auto_init) +{ + DMA_ENTRY *tdma; + unsigned long page, offset; + int mode; + + tdma = &mydma[channel]; + page = addr >> 16; + + if (channel >= 4) { /* 16 bit data is halved */ + addr >>= 1; + size >>= 1; + } + + offset = addr & 0xFFFF; + size--; + + mode = tdma->write; + if (auto_init) + mode |= 0x10; + + outportb(tdma->single, tdma->dma_disable); /* disable channel */ + outportb(tdma->mode, mode); /* set mode */ + outportb(tdma->clear_ff, 0); /* clear flip-flop */ + outportb(tdma->addr, offset & 0xFF); /* address LSB */ + outportb(tdma->addr, offset >> 8); /* address MSB */ + outportb(tdma->page, page); /* page number */ + outportb(tdma->clear_ff, 0); /* clear flip-flop */ + outportb(tdma->count, size & 0xFF); /* count LSB */ + outportb(tdma->count, size >> 8); /* count MSB */ + outportb(tdma->single, tdma->dma_enable); /* enable channel */ +} + +END_OF_FUNCTION(_dma_start); + + + +/* dma_stop: + * Disables the specified DMA channel. + */ +void _dma_stop(int channel) +{ + DMA_ENTRY *tdma = &mydma[channel]; + outportb(tdma->single, tdma->dma_disable); +} + +END_OF_FUNCTION(_dma_stop); + + + +/* dma_todo: + * Returns the current position in a dma transfer. Interrupts should be + * disabled before calling this function. + */ +unsigned long _dma_todo(int channel) +{ + int val1, val2; + DMA_ENTRY *tdma = &mydma[channel]; + + outportb(tdma->clear_ff, 0xff); + + do { + val1 = inportb(tdma->count); + val1 |= inportb(tdma->count) << 8; + val2 = inportb(tdma->count); + val2 |= inportb(tdma->count) << 8; + + val1 -= val2; + } while (val1 > 0x40); + + if (channel > 3) + val2 <<= 1; + + return val2; +} + +END_OF_FUNCTION(_dma_todo); + + + +/* _dma_lock_mem: + * Locks the memory used by the dma routines. + */ +void _dma_lock_mem() +{ + LOCK_VARIABLE(mydma); + LOCK_FUNCTION(_dma_allocate_mem); + LOCK_FUNCTION(_dma_start); + LOCK_FUNCTION(_dma_stop); + LOCK_FUNCTION(_dma_todo); +} + diff --git a/arch/dos/allg_snd/sound/drv/emu8k.c b/arch/dos/allg_snd/sound/drv/emu8k.c new file mode 100644 index 00000000..28640c66 --- /dev/null +++ b/arch/dos/allg_snd/sound/drv/emu8k.c @@ -0,0 +1,651 @@ +/*---------------------------------------------------------------------------- + * emu8k.c - low-level functions for AWE32 driver + *---------------------------------------------------------------------------- + * + * (c) George Foot April-September 1997 + * + * Information taken primarily from "AWE32/EMU8000 Programmer's Guide" (AEPG) + * by Dave Rossum. The AEPG is part of the AWE32 Developers' Information Pack + * (ADIP) from Creative Labs. + * + * I/O port verification technique taken from "The Un-official Sound + * Blaster AWE32 Programming Guide" by Vince Vu a.k.a. Judge Dredd + * + * Miscellaneous guidance taken from Takashi Iwai's Linux AWE32 driver + * + */ + + + +#ifndef DJGPP +#error This file should only be used by the djgpp version of Allegro +#endif + +#include /* for `pow' in the conversion routines */ +#include /* for I/O port access */ +#include /* for getenv("BLASTER") during detection */ +#include /* for strtol to parse the address in BLASTER */ +#include /* for error messaging */ + +#include "internal.h" /* for `rest' in emu8k_init */ +#include "emu8k.h" /* structs and prototypes */ + + + +/****************************************************************************\ +* * +* EMU8000.H : EMU8000 init arrays ( for hardware level programming only ) * +* * +* (C) Copyright Creative Technology Ltd. 1992-96. All rights reserved * +* worldwide. * +* * +* 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 MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR * +* PURPOSE. * +* * +\****************************************************************************/ + +static unsigned short init1_1[32] = { 0x03ff, 0x0030, 0x07ff, 0x0130, 0x0bff, 0x0230, 0x0fff, 0x0330, 0x13ff, 0x0430, 0x17ff, 0x0530, 0x1bff, 0x0630, 0x1fff, 0x0730, 0x23ff, 0x0830, 0x27ff, 0x0930, 0x2bff, 0x0a30, 0x2fff, 0x0b30, 0x33ff, 0x0c30, 0x37ff, 0x0d30, 0x3bff, 0x0e30, 0x3fff, 0x0f30 }; +static unsigned short init1_2[32] = { 0x43ff, 0x0030, 0x47ff, 0x0130, 0x4bff, 0x0230, 0x4fff, 0x0330, 0x53ff, 0x0430, 0x57ff, 0x0530, 0x5bff, 0x0630, 0x5fff, 0x0730, 0x63ff, 0x0830, 0x67ff, 0x0930, 0x6bff, 0x0a30, 0x6fff, 0x0b30, 0x73ff, 0x0c30, 0x77ff, 0x0d30, 0x7bff, 0x0e30, 0x7fff, 0x0f30 }; +static unsigned short init1_3[32] = { 0x83ff, 0x0030, 0x87ff, 0x0130, 0x8bff, 0x0230, 0x8fff, 0x0330, 0x93ff, 0x0430, 0x97ff, 0x0530, 0x9bff, 0x0630, 0x9fff, 0x0730, 0xa3ff, 0x0830, 0xa7ff, 0x0930, 0xabff, 0x0a30, 0xafff, 0x0b30, 0xb3ff, 0x0c30, 0xb7ff, 0x0d30, 0xbbff, 0x0e30, 0xbfff, 0x0f30 }; +static unsigned short init1_4[32] = { 0xc3ff, 0x0030, 0xc7ff, 0x0130, 0xcbff, 0x0230, 0xcfff, 0x0330, 0xd3ff, 0x0430, 0xd7ff, 0x0530, 0xdbff, 0x0630, 0xdfff, 0x0730, 0xe3ff, 0x0830, 0xe7ff, 0x0930, 0xebff, 0x0a30, 0xefff, 0x0b30, 0xf3ff, 0x0c30, 0xf7ff, 0x0d30, 0xfbff, 0x0e30, 0xffff, 0x0f30 }; + +static unsigned short init2_1[32] = { 0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330, 0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730, 0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30, 0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30 }; +static unsigned short init2_2[32] = { 0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330, 0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730, 0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30, 0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30 }; +static unsigned short init2_3[32] = { 0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330, 0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730, 0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30, 0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30 }; +static unsigned short init2_4[32] = { 0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330, 0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730, 0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30, 0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30 }; + +static unsigned short init3_1[32] = { 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5, 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254, 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234, 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224 }; +static unsigned short init3_2[32] = { 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254, 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264, 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294, 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3 }; +static unsigned short init3_3[32] = { 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287, 0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7, 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386, 0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55 }; +static unsigned short init3_4[32] = { 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308, 0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F, 0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319, 0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570 }; + +static unsigned short init4_1[32] = { 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5, 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254, 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234, 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224 }; +static unsigned short init4_2[32] = { 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254, 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264, 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294, 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3 }; +static unsigned short init4_3[32] = { 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287, 0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7, 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386, 0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55 }; +static unsigned short init4_4[32] = { 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308, 0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F, 0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319, 0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570 }; + +/*** (end of init arrays) ***/ + + + +#define MIN_LOOP_LEN 2 + +int _emu8k_baseport=0; +int _emu8k_numchannels=32; + + + +/* Functions to deal with the AWE32's I/O ports + */ +static inline void write_word(int reg,int channel,int port,int data) { + int out_port=_emu8k_baseport; + switch(port) { + case 0: out_port+=0x0000; break; + case 1: out_port+=0x0400; break; + case 2: out_port+=0x0402; break; + case 3: out_port+=0x0800; break; + default: return; + } + outportw(_emu8k_baseport+0x802,(reg<<5)+(channel&0x1f)); + outportw(out_port,data); +} + +static inline unsigned int read_word(int reg,int channel,int port) { + int in_port=_emu8k_baseport; + switch(port) { + case 0: in_port+=0x0000; break; + case 1: in_port+=0x0400; break; + case 2: in_port+=0x0402; break; + case 3: in_port+=0x0800; break; + default: return 0; + } + outportw(_emu8k_baseport+0x802,(reg<<5)+(channel&0x1f)); + return inportw(in_port); +} + +static inline void write_dword(int reg,int channel,int port,unsigned int data) { + int out_port=_emu8k_baseport; + switch(port) { + case 0: out_port+=0x0000; break; + case 1: out_port+=0x0400; break; + case 2: out_port+=0x0402; break; + case 3: out_port+=0x0800; break; + default: return; + } + outportw(_emu8k_baseport+0x802,(reg<<5)+(channel&0x1f)); + outportw(out_port,data&0xffff); + outportw(out_port+2,(data>>16)&0xffff); +} + +static inline unsigned int read_dword(int reg,int channel,int port) { + int in_port,a,b; + in_port=_emu8k_baseport; + switch(port) { + case 0: in_port+=0x0000; break; + case 1: in_port+=0x0400; break; + case 2: in_port+=0x0402; break; + case 3: in_port+=0x0800; break; + default: return 0; + } + outportw(_emu8k_baseport+0x802,(reg<<5)+(channel&0x1f)); + a=inportw(in_port); + b=inportw(in_port+2); + return ((b<<16)+a); +} + + + +/* write_*: + * Functions to write information to the AWE32's registers + * (abbreviated as in the EPG). + */ +static inline void write_CPF(int channel,int i) { write_dword(0,channel,0,i); } +static inline void write_PTRX(int channel,int i) { write_dword(1,channel,0,i); } +static inline void write_CVCF(int channel,int i) { write_dword(2,channel,0,i); } +static inline void write_VTFT(int channel,int i) { write_dword(3,channel,0,i); } +static inline void write_PSST(int channel,int i) { write_dword(6,channel,0,i); } +static inline void write_CSL(int channel,int i) { write_dword(7,channel,0,i); } +static inline void write_CCCA(int channel,int i) { write_dword(0,channel,1,i); } +static inline void write_HWCF4(int i) { write_dword(1, 9,1,i); } +static inline void write_HWCF5(int i) { write_dword(1, 10,1,i); } +static inline void write_HWCF6(int i) { write_dword(1, 13,1,i); } +static inline void write_SMALR(int i) { write_dword(1, 20,1,i); } +static inline void write_SMARR(int i) { write_dword(1, 21,1,i); } +static inline void write_SMALW(int i) { write_dword(1, 22,1,i); } +static inline void write_SMARW(int i) { write_dword(1, 23,1,i); } +static inline void write_SMLD(int i) { write_word (1, 26,1,i); } +static inline void write_SMRD(int i) { write_word (1, 26,2,i); } +static inline void write_WC(int i) { write_word (1, 27,2,i); } +static inline void write_HWCF1(int i) { write_word (1, 29,1,i); } +static inline void write_HWCF2(int i) { write_word (1, 30,1,i); } +static inline void write_HWCF3(int i) { write_word (1, 31,1,i); } +static inline void write_INIT1(int channel,int i) { write_word (2,channel,1,i); } /* `channel' is really `element' here */ +static inline void write_INIT2(int channel,int i) { write_word (2,channel,2,i); } +static inline void write_INIT3(int channel,int i) { write_word (3,channel,1,i); } +static inline void write_INIT4(int channel,int i) { write_word (3,channel,2,i); } +static inline void write_ENVVOL(int channel,int i) { write_word (4,channel,1,i); } +static inline void write_DCYSUSV(int channel,int i) { write_word (5,channel,1,i); } +static inline void write_ENVVAL(int channel,int i) { write_word (6,channel,1,i); } +static inline void write_DCYSUS(int channel,int i) { write_word (7,channel,1,i); } +static inline void write_ATKHLDV(int channel,int i) { write_word (4,channel,2,i); } +static inline void write_LFO1VAL(int channel,int i) { write_word (5,channel,2,i); } +static inline void write_ATKHLD(int channel,int i) { write_word (6,channel,2,i); } +static inline void write_LFO2VAL(int channel,int i) { write_word (7,channel,2,i); } +static inline void write_IP(int channel,int i) { write_word (0,channel,3,i); } +static inline void write_IFATN(int channel,int i) { write_word (1,channel,3,i); } +static inline void write_PEFE(int channel,int i) { write_word (2,channel,3,i); } +static inline void write_FMMOD(int channel,int i) { write_word (3,channel,3,i); } +static inline void write_TREMFRQ(int channel,int i) { write_word (4,channel,3,i); } +static inline void write_FM2FRQ2(int channel,int i) { write_word (5,channel,3,i); } + + + +/* read_*: + * Functions to read information from the AWE32's registers + * (abbreviated as in the AEPG). + */ +static inline int read_CPF(int channel) { return read_dword(0,channel,0); } +static inline int read_PTRX(int channel) { return read_dword(1,channel,0); } +static inline int read_CVCF(int channel) { return read_dword(2,channel,0); } +static inline int read_VTFT(int channel) { return read_dword(3,channel,0); } +static inline int read_PSST(int channel) { return read_dword(6,channel,0); } +static inline int read_CSL(int channel) { return read_dword(7,channel,0); } +static inline int read_CCCA(int channel) { return read_dword(0,channel,1); } +static inline int read_HWCF4() { return read_dword(1, 9,1); } +static inline int read_HWCF5() { return read_dword(1, 10,1); } +static inline int read_HWCF6() { return read_dword(1, 13,1); } +static inline int read_SMALR() { return read_dword(1, 20,1); } +static inline int read_SMARR() { return read_dword(1, 21,1); } +static inline int read_SMALW() { return read_dword(1, 22,1); } +static inline int read_SMARW() { return read_dword(1, 23,1); } +static inline int read_SMLD() { return read_word (1, 26,1); } +static inline int read_SMRD() { return read_word (1, 26,2); } +static inline int read_WC() { return read_word (1, 27,2); } +static inline int read_HWCF1() { return read_word (1, 29,1); } +static inline int read_HWCF2() { return read_word (1, 30,1); } +static inline int read_HWCF3() { return read_word (1, 31,1); } +static inline int read_INIT1() { return read_word (2, 0,1); } +static inline int read_INIT2() { return read_word (2, 0,2); } +static inline int read_INIT3() { return read_word (3, 0,1); } +static inline int read_INIT4() { return read_word (3, 0,2); } +static inline int read_ENVVOL(int channel) { return read_word (4,channel,1); } +static inline int read_DCYSUSV(int channel) { return read_word (5,channel,1); } +static inline int read_ENVVAL(int channel) { return read_word (6,channel,1); } +static inline int read_DCYSUS(int channel) { return read_word (7,channel,1); } +static inline int read_ATKHLDV(int channel) { return read_word (4,channel,2); } +static inline int read_LFO1VAL(int channel) { return read_word (5,channel,2); } +static inline int read_ATKHLD(int channel) { return read_word (6,channel,2); } +static inline int read_LFO2VAL(int channel) { return read_word (7,channel,2); } +static inline int read_IP(int channel) { return read_word (0,channel,3); } +static inline int read_IFATN(int channel) { return read_word (1,channel,3); } +static inline int read_PEFE(int channel) { return read_word (2,channel,3); } +static inline int read_FMMOD(int channel) { return read_word (3,channel,3); } +static inline int read_TREMFRQ(int channel) { return read_word (4,channel,3); } +static inline int read_FM2FRQ2(int channel) { return read_word (5,channel,3); } + + + +/* wait_*: + * Functions to wait for DMA streams to be ready. + */ +static inline void wait_LR() { while (read_SMALR()&0x80000000); } +static inline void wait_LW() { while (read_SMALW()&0x80000000); } +static inline void wait_RR() { while (read_SMARR()&0x80000000); } +static inline void wait_RW() { while (read_SMARW()&0x80000000); } + +/* write_init_arrays: + * Writes the given set of initialisation arrays to the card. + */ +static void write_init_arrays(short int *init1,short int *init2,short int *init3,short int *init4) { + int i; + for (i=0;i<32;i++) write_INIT1(i,init1[i]); + for (i=0;i<32;i++) write_INIT2(i,init2[i]); + for (i=0;i<32;i++) write_INIT3(i,init3[i]); + for (i=0;i<32;i++) write_INIT4(i,init4[i]); +} + + + +/* emu8k_init: + * Initialise the synthesiser. See AEPG chapter 4. + */ +void emu8k_init() { + int channel; + write_HWCF1(0x0059); + write_HWCF2(0x0020); + for (channel=0;channel<_emu8k_numchannels;channel++) write_DCYSUSV(channel,0x0080); + for (channel=0;channel<_emu8k_numchannels;channel++) { + write_ENVVOL(channel,0); + write_ENVVAL(channel,0); + write_DCYSUS(channel,0); + write_ATKHLDV(channel,0); + write_LFO1VAL(channel,0); + write_ATKHLD(channel,0); + write_LFO2VAL(channel,0); + write_IP(channel,0); + write_IFATN(channel,0); + write_PEFE(channel,0); + write_FMMOD(channel,0); + write_TREMFRQ(channel,0); + write_FM2FRQ2(channel,0); + write_PTRX(channel,0); + write_VTFT(channel,0); + write_PSST(channel,0); + write_CSL(channel,0); + write_CCCA(channel,0); + } + for (channel=0;channel<_emu8k_numchannels;channel++) { + write_CPF(channel,0); + write_CVCF(channel,0); + } + write_SMALR(0); + write_SMARR(0); + write_SMALW(0); + write_SMARW(0); + write_init_arrays(init1_1,init1_2,init1_3,init1_4); + rest(25); /* wait 24 msec + 1 for luck */ + write_init_arrays(init2_1,init2_2,init2_3,init2_4); + write_init_arrays(init3_1,init3_2,init3_3,init3_4); + write_HWCF4(0); + write_HWCF5(0x00000083); + write_HWCF6(0x00008000); + write_init_arrays(init4_1,init4_2,init4_3,init4_4); + write_HWCF3(0x0004); +} + + + +/* emu8k_startsound: + * Start a sound on a channel. + */ +void emu8k_startsound(int channel,struct envparms_t *envparms) { + write_DCYSUSV(channel,0x0080); + write_VTFT(channel,0); + write_CVCF(channel,0); + write_PTRX(channel,0); + write_CPF(channel,0); + + write_ENVVOL(channel,envparms->envvol); + write_ENVVAL(channel,envparms->envval); + write_DCYSUS(channel,envparms->dcysus); + write_ATKHLDV(channel,envparms->atkhldv); + write_LFO1VAL(channel,envparms->lfo1val); + write_ATKHLD(channel,envparms->atkhld); + write_LFO2VAL(channel,envparms->lfo2val); + write_IP(channel,envparms->ip); + write_IFATN(channel,envparms->ifatn); + write_PEFE(channel,envparms->pefe); + write_FMMOD(channel,envparms->fmmod); + write_TREMFRQ(channel,envparms->tremfrq); + write_FM2FRQ2(channel,envparms->fm2frq2); + + { + int psst=0,csl=0; + switch (envparms->smpmode&3) { + case 0: /* no looping */ + case 2: /* invalid; should be read as `no looping' */ + psst = (envparms->psst&0xff000000) /* copy pan verbatim; mask out loop start */ + + (envparms->sampend) /* set loop start to near sample end */ + - MIN_LOOP_LEN; + csl = (envparms->csl &0xff000000) /* copy chorus verbatim; mask out loop end */ + + (envparms->sampend) /* set loop end to sample end */ + + MIN_LOOP_LEN; + break; + case 1: /* loop indefinitely */ + case 3: /* loop until key released, then continue */ + psst = envparms->psst; /* leave the loop as it stands */ + csl = envparms->csl; + break; + } + write_PSST(channel,psst); + write_CSL (channel,csl); + } + write_CCCA(channel,envparms->ccca); + + write_VTFT(channel,0x0000FFFF); + write_CVCF(channel,0x0000FFFF); + write_DCYSUSV(channel,envparms->dcysusv); + write_PTRX(channel,envparms->ptrx); + write_CPF(channel,0x40000000); +} +static END_OF_FUNCTION(emu8k_startsound); + + + +/* emu8k_releasesound: + * End a sound on a channel by starting its release phase. + */ +void emu8k_releasesound(int channel,struct envparms_t *envparms) { + if (envparms->smpmode==3) { /* If sound should stop looping and continue, do so */ + write_CSL(channel,(envparms->chorus<<24)+envparms->sampend + MIN_LOOP_LEN); + write_PSST(channel,(envparms->pan<<24)+envparms->sampend - MIN_LOOP_LEN); + } + write_DCYSUSV(channel,0x8000+envparms->volrel); /* Start volume envelope release phase */ + write_DCYSUS (channel,0x8000+envparms->modrel); /* Start modulation envelope release phase */ +} +static END_OF_FUNCTION(emu8k_releasesound); + + +/* emu8k_modulate_*: + * Modulation functions - changing a channel's sound in various ways. + */ +void emu8k_modulate_atten (int channel, int atten) { + int ifatn; + ifatn = read_IFATN (channel); + write_IFATN (channel,(ifatn&0xff00)+(atten&0xff)); +} +static END_OF_FUNCTION(emu8k_modulate_atten); + + +void emu8k_modulate_ip (int channel, int ip) { + write_IP(channel,ip); +} +static END_OF_FUNCTION(emu8k_modulate_ip); + + +void emu8k_modulate_pan (int channel, int pan) { + int psst; + psst = read_PSST(channel); + write_PSST(channel,(pan<<24)+(psst&0x00ffffff)); +} +static END_OF_FUNCTION(emu8k_modulate_pan); + + + +/* emu8k_terminatesound: + * End a sound on a channel immediately (may produce an audible click). + */ +void emu8k_terminatesound(int channel) { + write_DCYSUSV(channel,0x0080); + write_VTFT(channel,0x0000FFFF); + write_CVCF(channel,0x0000FFFF); +} +static END_OF_FUNCTION(emu8k_terminatesound); + + + +/* emu8k_detect: + * Locate the EMU8000. This tries to extract the base port from the E section + * of the BLASTER environment variable, and then does some test reads to check + * that there is an EMU8000 there. + */ +int emu8k_detect() { + char *envvar; + if (!(envvar=getenv("BLASTER"))) { + sprintf(allegro_error,"BLASTER environment variable not set"); + return 0; + } + + _emu8k_baseport=0; + while (*envvar) { + if (*envvar=='E') _emu8k_baseport=strtol(envvar+1,NULL,16); + while ((*envvar!=' ')&&(*envvar!=0)) envvar++; + if (*envvar) envvar++; + } + if (!_emu8k_baseport) { + sprintf(allegro_error,"BLASTER environment variable has no E section"); + return 0; + } + + sprintf(allegro_error,"AWE32 detection failed on port 0x%04x",_emu8k_baseport); + + if ((read_word(7, 0,3)&0x000f)!=0x000c) return 0; + if ((read_word(1,29,1)&0x007e)!=0x0058) return 0; + if ((read_word(1,30,1)&0x0003)!=0x0003) return 0; + + *allegro_error=0; + return 1; +} + + + +/* emu_*: + * Functions to convert SoundFont information to EMU8000 parameters. + */ +static inline unsigned short emu_delay(int x) { + int a=0x8000-pow(2,x/1200.0)/0.000725; + return (a<0)?0:((a>0x8000)?0x8000:a); +} + +static inline unsigned char emu_attack(int x) { +/* + * AEPG doesn't specify exact conversion here; I'm using what Takashi Iwai used for + * his Linux driver + */ + int a,msec; + msec=pow(2,x/1200.0)*1000; + if (msec==0) return 0x7f; +// if (msec>=360) + a=11878/msec; +// else +// a=32+53.426*log10(360.0/msec); + + return (a<1)?1:((a>0x7f)?0x7f:a); +} + +static inline unsigned char emu_hold(int x) { + int a=0x7f-(int)(pow(2,x/1200.0)*0x7f/11.68); + return (a<0)?0:((a>0x7f)?0x7f:a); +} + +static inline unsigned char emu_decay(int x) { +/* + * AEPG doesn't specify exact conversion here; I'm using an adaptation of + * what Takashi Iwai used for his Linux driver + */ + int a,msec; + msec=pow(2,x/1200.0)*1000; + if (msec==0) return 0x7f; + a=0x7f-54.8*log10(msec/23.04); /* Takashi's */ +// a = 47349/(msec+349); /* mine */ + return (a<1)?1:((a>0x7f)?0x7f:a); +} + +static inline unsigned char emu_sustain(int x) { +/* This is not the same as in Takashi Iwai's Linux driver, but I think I'm right */ + int a=0x7f-x/7.5; + return (a<0)?0:((a>0x7f)?0x7f:a); +} + +static inline unsigned char emu_release(int x) { + return emu_decay(x); +} + +static inline unsigned char emu_mod(int x,int peak_deviation) { + int a=x*0x80/peak_deviation; + return (a<-0x80)?0x80:((a>0x7f)?0x7f:a); +} + +static inline unsigned char emu_freq(int x) { + int a=(8.176*pow(2,x/1200.0)+0.032)/0.042; + return (a<0)?0:((a>0xff)?0xff:a); +} + +static inline unsigned char emu_reverb(int x) { + int a=(x*0xff)/1000; + return (a<0)?0:((a>0xff)?0xff:a); +} + +static inline unsigned char emu_chorus(int x) { + int a=(x*0xff)/1000; + return (a<0)?0:((a>0xff)?0xff:a); +} + +static inline unsigned char emu_pan(int x) { + int a=0x7f-(x*0xff)/1000; + return (a<8)?8:((a>0xf8)?0xf8:a); +} + +static inline unsigned char emu_filterQ(int x) { + int a=(x/15); + return (a<0)?0:((a>15)?15:a); +} + +static inline unsigned int emu_address(int base,int offset,int coarse_offset) { + return base+offset+coarse_offset*32*1024; +} + +static inline unsigned short emu_pitch(int key,int rootkey,int scale,int coarse,int fine,int initial) { + int a=(((key-rootkey)*scale+coarse*100+fine-initial)*0x1000)/1200+0xE000; + return (a<0)?0:((a>0xFFFF)?0xFFFF:a); +} + +static inline unsigned char emu_filter(int x) { + int a = (x-4721)/25; + return (a<0)?0:((a>0xff)?0xff:a); +} + +static inline unsigned char emu_atten(int x) { + int a = x/3.75; + return (a<0)?0:((a>0xff)?0xff:a); +} + + + +/* emu8k_createenvelope: + * Converts a set of SoundFont generators to equivalent EMU8000 register + * settings, for passing to the sound playing functions above. + */ +envparms_t *emu8k_createenvelope(generators_t sfgen) { + envparms_t *envelope=(envparms_t *)_lock_malloc(sizeof(envparms_t)); + if (envelope) { + envelope->envvol = emu_delay(sfgen[sfgen_delayModEnv]); + envelope->envval = emu_delay(sfgen[sfgen_delayVolEnv]); + envelope->modsust = (emu_sustain(sfgen[sfgen_sustainModEnv])<<8); + envelope->modrel = (emu_release(sfgen[sfgen_releaseModEnv])<<0); + envelope->dcysus = (0<<15) // we're programming the decay, not the release + + envelope->modsust + + (0<<7) // unused + + (emu_decay(sfgen[sfgen_decayModEnv])<<0); + envelope->atkhldv = (0<<15) // 0 otherwise it won't attack + + (emu_hold(sfgen[sfgen_holdVolEnv])<<8) + + (0<<7) // unused + + (emu_attack(sfgen[sfgen_attackVolEnv])<<0); + envelope->lfo1val = emu_delay(sfgen[sfgen_delayModLFO]); + envelope->atkhld = (0<<15) // 0 otherwise it won't attack + + (emu_hold(sfgen[sfgen_holdModEnv])<<8) + + (0<<7) // unused + + (emu_attack(sfgen[sfgen_attackModEnv])<<0); + envelope->lfo2val = emu_delay(sfgen[sfgen_delayVibLFO]); + envelope->pitch = 0xe000; + envelope->ip = envelope->pitch; + envelope->filter = (emu_filter(sfgen[sfgen_initialFilterFc])<<8); + envelope->atten = (emu_atten(sfgen[sfgen_initialAttenuation])<<0); + envelope->ifatn = envelope->filter+envelope->atten; + envelope->pefe = (emu_mod(sfgen[sfgen_modEnvToPitch],1200)<<8) + + (emu_mod(sfgen[sfgen_modEnvToFilterFc],7200)<<0); + envelope->fmmod = (emu_mod(sfgen[sfgen_modLfoToPitch],1200)<<8) + + (emu_mod(sfgen[sfgen_modLfoToFilterFc],3600)<<0); + envelope->tremfrq = (emu_mod(sfgen[sfgen_modLfoToVolume],120)<<8) + + (emu_freq(sfgen[sfgen_freqModLFO])<<0); + envelope->fm2frq2 = (emu_mod(sfgen[sfgen_vibLfoToPitch],1200)<<8) + + (emu_freq(sfgen[sfgen_freqVibLFO])<<0); + envelope->volsust = (emu_sustain(sfgen[sfgen_sustainVolEnv])<<8); + envelope->volrel = (emu_release(sfgen[sfgen_releaseVolEnv])<<0); + envelope->dcysusv = (0<<15) // we're programming decay not release + + envelope->volsust + + (0<<7) // turn on envelope engine + + (emu_decay(sfgen[sfgen_decayVolEnv])<<0); + envelope->ptrx = (0x4000<<16) // ??? I thought the top word wasn't for me to use + + (emu_reverb(sfgen[sfgen_reverbEffectsSend])<<8) + + (0<<0); // unused + envelope->pan = emu_pan(sfgen[sfgen_pan]); + envelope->loopst = emu_address(sfgen[gfgen_startloopAddrs],sfgen[sfgen_startloopAddrsOffset],sfgen[sfgen_startloopAddrsCoarseOffset]); + envelope->sampend = emu_address(sfgen[gfgen_endAddrs],sfgen[sfgen_endAddrsOffset],sfgen[sfgen_endAddrsCoarseOffset]); + envelope->psst = (envelope->pan<<24) + + (envelope->loopst); + envelope->chorus = emu_chorus(sfgen[sfgen_chorusEffectsSend]); + envelope->csl = (envelope->chorus<<24) + + (emu_address(sfgen[gfgen_endloopAddrs],sfgen[sfgen_endloopAddrsOffset],sfgen[sfgen_endloopAddrsCoarseOffset])<<0); + envelope->ccca = (emu_filterQ(sfgen[sfgen_initialFilterQ])<<28) + + (0<<24) // DMA control bits + + (emu_address(sfgen[gfgen_startAddrs],sfgen[sfgen_startAddrsOffset],sfgen[sfgen_startAddrsCoarseOffset])<<0); + + envelope->rootkey = (sfgen[sfgen_overridingRootKey]!=-1)?sfgen[sfgen_overridingRootKey]:69; + envelope->ipbase = ((sfgen[sfgen_coarseTune]*100+sfgen[sfgen_fineTune]-envelope->rootkey*sfgen[sfgen_scaleTuning])*0x1000)/1200+0xE000; + envelope->ipscale = sfgen[sfgen_scaleTuning]; + + envelope->minkey = sfgen[sfgen_keyRange]&0xff; + envelope->maxkey = (sfgen[sfgen_keyRange]>>8)&0xff; + envelope->minvel = sfgen[sfgen_velRange]&0xff; + envelope->maxvel = (sfgen[sfgen_velRange]>>8)&0xff; + envelope->key = -1; + envelope->vel = -1; + envelope->exc = sfgen[sfgen_exclusiveClass]; + envelope->keyMEH = 0; + envelope->keyMED = 0; + envelope->keyVEH = 0; + envelope->keyVED = 0; + envelope->smpmode = sfgen[sfgen_sampleModes]; + } + return envelope; +} + + + +/* emu8k_destroyenvelope: + * Destroys an envelope created by emu8k_createenvelope. + */ +void emu8k_destroyenvelope(envparms_t *env) { + free(env); +} + + + +/* emu8k_lock: + * Locks all data and functions which might be called in an interrupt context. + */ +void emu8k_lock() { + LOCK_VARIABLE(_emu8k_baseport); + LOCK_VARIABLE(_emu8k_numchannels); + + LOCK_FUNCTION(emu8k_startsound); + LOCK_FUNCTION(emu8k_releasesound); + LOCK_FUNCTION(emu8k_modulate_atten); + LOCK_FUNCTION(emu8k_modulate_ip); + LOCK_FUNCTION(emu8k_modulate_pan); + LOCK_FUNCTION(emu8k_terminatesound); +} + diff --git a/arch/dos/allg_snd/sound/drv/emu8k.h b/arch/dos/allg_snd/sound/drv/emu8k.h new file mode 100644 index 00000000..2df56bf2 --- /dev/null +++ b/arch/dos/allg_snd/sound/drv/emu8k.h @@ -0,0 +1,121 @@ +/*-------------------------------------------------------------------------- + * emu8k.h - low-level functions for AWE32 driver + *-------------------------------------------------------------------------- + * + * (c) George Foot April-September 1997 + * + * Information taken primarily from "AWE32/EMU8000 Programmer's Guide" + * (AEPG) by Dave Rossum. The AEPG is part of the AWE32 Developers' + * Information Pack (ADIP) from Creative Labs. + * + * I/O port verification technique taken from "The Un-official Sound + * Blaster AWE32 Programming Guide" by Vince Vu a.k.a. Judge Dredd + * + */ + +#ifndef EMU8K_H +#define EMU8K_H + +#include + +typedef struct envparms_t { + int envvol, envval, dcysus, atkhldv, + lfo1val, atkhld, lfo2val, ip, + ifatn, pefe, fmmod, tremfrq, + fm2frq2, dcysusv, ptrx, psst, + csl, ccca, rootkey, ipbase, + ipscale, minkey, maxkey, minvel, + maxvel, key, vel, exc, + keyMEH, keyMED, keyVEH, keyVED, + filter, atten, smpmode, volrel, + modrel, pan, loopst, reverb, + chorus, volsust, modsust, pitch, + sampend; +} envparms_t; + +#define sfgen_startAddrsOffset 0 +#define sfgen_endAddrsOffset 1 +#define sfgen_startloopAddrsOffset 2 +#define sfgen_endloopAddrsOffset 3 +#define sfgen_startAddrsCoarseOffset 4 +#define sfgen_modLfoToPitch 5 +#define sfgen_vibLfoToPitch 6 +#define sfgen_modEnvToPitch 7 +#define sfgen_initialFilterFc 8 +#define sfgen_initialFilterQ 9 +#define sfgen_modLfoToFilterFc 10 +#define sfgen_modEnvToFilterFc 11 +#define sfgen_endAddrsCoarseOffset 12 +#define sfgen_modLfoToVolume 13 +#define sfgen_chorusEffectsSend 15 +#define sfgen_reverbEffectsSend 16 +#define sfgen_pan 17 +#define sfgen_delayModLFO 21 +#define sfgen_freqModLFO 22 +#define sfgen_delayVibLFO 23 +#define sfgen_freqVibLFO 24 +#define sfgen_delayModEnv 25 +#define sfgen_attackModEnv 26 +#define sfgen_holdModEnv 27 +#define sfgen_decayModEnv 28 +#define sfgen_sustainModEnv 29 +#define sfgen_releaseModEnv 30 +#define sfgen_keynumToModEnvHold 31 +#define sfgen_keynumToModEnvDecay 32 +#define sfgen_delayVolEnv 33 +#define sfgen_attackVolEnv 34 +#define sfgen_holdVolEnv 35 +#define sfgen_decayVolEnv 36 +#define sfgen_sustainVolEnv 37 +#define sfgen_releaseVolEnv 38 +#define sfgen_keynumToVolEnvHold 39 +#define sfgen_keynumToVolEnvDecay 40 +#define sfgen_instrument 41 +#define sfgen_keyRange 43 +#define sfgen_velRange 44 +#define sfgen_startloopAddrsCoarseOffset 45 +#define sfgen_keynum 46 +#define sfgen_velocity 47 +#define sfgen_initialAttenuation 48 +#define sfgen_endloopAddrsCoarseOffset 50 +#define sfgen_coarseTune 51 +#define sfgen_fineTune 52 +#define sfgen_sampleID 53 +#define sfgen_sampleModes 54 +#define sfgen_initialPitch 55 +#define sfgen_scaleTuning 56 +#define sfgen_exclusiveClass 57 +#define sfgen_overridingRootKey 58 + +#define gfgen_startAddrs 59 +#define gfgen_startloopAddrs 60 +#define gfgen_endloopAddrs 61 +#define gfgen_endAddrs 62 + +#define SOUNDFONT_NUM_GENERATORS 63 + +typedef int generators_t[SOUNDFONT_NUM_GENERATORS]; + +/*extern envparms_t env_default;*/ +extern int _emu8k_baseport; +extern int _emu8k_numchannels; + +void emu8k_init(); +void emu8k_startsound(int channel,struct envparms_t *envparms); +void emu8k_releasesound(int channel,struct envparms_t *envparms); +void emu8k_terminatesound(int channel); +int emu8k_detect(); + +void emu8k_modulate_atten (int channel, int atten); +void emu8k_modulate_ip (int channel, int ip); +void emu8k_modulate_pan (int channel, int pan); + +envparms_t *emu8k_createenvelope(generators_t); +void emu8k_destroyenvelope(envparms_t *); + +void emu8k_lock(); + +void *_lock_malloc(size_t size); /* malloc and lock */ + +#endif + diff --git a/arch/dos/allg_snd/sound/drv/emu8kmid.c b/arch/dos/allg_snd/sound/drv/emu8kmid.c new file mode 100644 index 00000000..bec6fec9 --- /dev/null +++ b/arch/dos/allg_snd/sound/drv/emu8kmid.c @@ -0,0 +1,408 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * By Shawn Hargreaves, + * 1 Salisbury Road, + * Market Drayton, + * Shropshire, + * England, TF9 1AJ. + * + * This file written by George Foot. + * + * AWE32/EMU8000 driver for the MIDI player. + * + * See readme.txt for copyright information. + */ + + +#ifndef DJGPP +#error This file should only be used by the djgpp version of Allegro +#endif + +#include +#include +#include + +#include "allegro.h" +#include "internal.h" + +#include "emu8k.h" + +/* Variables from awedata.c, containing the envelope data from synthgm.sf2 */ +extern short int _awe_sf_defaults[]; +extern int _awe_sf_num_presets; +extern short int _awe_sf_presets[]; +extern short int _awe_sf_splits[]; +extern short int _awe_sf_gens[]; +extern int _awe_sf_sample_data[]; + +/* external interface to the AWE32 driver */ +static int awe32_detect(); +static int awe32_init(int voices); +static void awe32_exit(); +static void awe32_key_on(int inst, int note, int bend, int vol, int pan); +static void awe32_key_off(int voice); +static void _awe32_do_note(int inst, int note, int bend, int vol, int pan); +static void awe32_set_volume (int voice, int vol); +static void awe32_set_pitch (int voice, int note, int bend); +static void translate_soundfont_into_something_useful(); +static void destroy_useful_version_of_soundfont(); + +static struct midi_preset_t { /* struct to hold envelope data for each preset */ + int num_splits; /* number of splits in this preset */ + struct envparms_t **split; /* array of num_splits pointers to envelope data */ +} *midi_preset; /* global variable to hold the data */ + +static struct envparms_t **voice_envelope; /* array of pointers pointing at the envelope playing on each voice */ +static int *exclusive_class_info; /* exclusive class information */ + +static char awe32_desc[256] = "not initialised"; + +MIDI_DRIVER midi_awe32 = { + "AWE32/EMU8000", /* name */ + awe32_desc, /* desc */ + 32, 0, 32, 32, -1, -1, /* voices, basevoice, max_voices, def_voices, xmin, xmax */ + awe32_detect, /* detect */ + awe32_init, /* init */ + awe32_exit, /* exit */ + NULL, /* mixer_volume */ + NULL, /* raw_midi */ + _dummy_load_patches, /* load_patches */ + _dummy_adjust_patches, /* adjust_patches */ + awe32_key_on, /* key_on */ + awe32_key_off, /* key_off */ + awe32_set_volume, /* set_volume */ + awe32_set_pitch, /* set_pitch */ + _dummy_noop2, /* set_pan */ + _dummy_noop2 /* set_vibrato */ +}; + + + +/* awe32_key_on: + * Triggers the specified voice. The instrument is specified as a GM + * patch number, pitch as a midi note number, and volume from 0-127. + * The bend parameter is _not_ expressed as a midi pitch bend value. + * It ranges from 0 (no pitch change) to 0xFFF (almost a semitone sharp). + * Drum sounds are indicated by passing an instrument number greater than + * 128, in which case the sound is GM percussion key #(inst-128). + */ +static void awe32_key_on(int inst, int note, int bend, int vol, int pan) { + if (inst > 127) { /* drum sound? */ + _awe32_do_note (128,inst-128,bend,vol,pan); + } else { /* regular instrument */ + _awe32_do_note (inst,note,bend,vol,pan); + } +} +static END_OF_FUNCTION(awe32_key_on); + + + +/* _awe32_do_note: + * Actually plays the note as described above; the above function just remaps + * the drums. + */ +static void _awe32_do_note(int inst, int note, int bend, int vol, int pan) { + int voice; + int i; + envparms_t *env; + int key,vel; + int atten; + int pan_pos; + + /* EMU8000 pan is back-to-front and twice the scale */ + pan = 0x100-2*pan; + if (pan>0xff) pan = 0xff; + if (pan<0x00) pan = 0x00; + + for (i=0;i=env->minkey)&&(note<=env->maxkey)&&( vol>=env->minvel)&&( vol<=env->maxvel)) { + + /* get a voice (any voice) to play it on */ + voice = _midi_allocate_voice (-1,-1); + + /* did we get one? */ + if (voice>=0) { + + /* set the current envelope for this voice */ + voice_envelope[voice]=env; + + /* set pitch and velocity */ + key = note*0x1000+bend; + vel = vol; + + /* override key and velocity if envelope says so */ + if ((env->key>=0)&&(env->key<=127)) key=env->key*0x1000; + if ((env->vel>=0)&&(env->vel<=127)) vel=env->vel; + + /* check key and velocity numbers are within range */ + if (key>0x7ffff) key=0x7ffff; + if (key<0) key=0; + if (vel>127) vel=127; + if (vel<0) vel=0; + + /* add one-off information to the envelope (these have no side-effects on the other voices using this envelope) */ + env->ip=env->ipbase+(env->ipscale*key)/1200; + + /* remap MIDI velocity to attenuation */ + if (vel) + atten = env->atten + (-20/0.375*log(vel/127.0)); + else + atten = 0xff; + if (atten<0x00) atten = 0x00; + if (atten>0xff) atten = 0xff; + + /* update it in the envelope */ + env->ifatn=env->filter+atten; + + /* modify pan with envelope's built-in pan */ + if (pan<0x80) { + pan_pos = (pan*env->pan)/0x80; + } else { + pan_pos = env->pan + (pan-0x80)*(256-env->pan)/0x80; + } + if (pan_pos<0x00) pan_pos=0x00; + if (pan_pos>0xff) pan_pos=0xff; + + /* update pan in the envelope */ + env->psst = (pan_pos<<24) + env->loopst; + + /* test exclusive class */ + exclusive_class_info[voice] = (inst << 8) + env->exc; + + if (env->exc) { + int chan; + for (chan = 0; chan < 32; chan++) + if ((chan != voice) && (exclusive_class_info[chan] == exclusive_class_info[voice])) + emu8k_terminatesound (chan); + } + + /* start the note playing */ + emu8k_startsound(voice,env); + + } + } + } +} +static END_OF_FUNCTION(_awe32_do_note); + + + +/* awe32_set_*: + * Modulation routines + */ +static void awe32_set_volume (int voice, int vol) { + int atten; + struct envparms_t *env; + + /* get envelope in use on this voice */ + env = voice_envelope[voice]; + + /* allow envelope to override new volume */ + if ((env->vel>=0)&&(env->vel<=127)) vol=env->vel; + + /* check velocity number is within range */ + if (vol>127) vol=127; + if (vol<0) vol=0; + + /* remap MIDI velocity to attenuation */ + if (vol) + atten = env->atten + (-20/0.375*log(vol/127.0)); + else + atten = 0xff; + if (atten<0x00) atten = 0x00; + if (atten>0xff) atten = 0xff; + + emu8k_modulate_atten(voice,atten); +} +static END_OF_FUNCTION(awe32_set_volume); + + + +static void awe32_set_pitch (int voice, int note, int bend) { + struct envparms_t *env; + int key,ip; + + /* get envelope in use on this voice */ + env = voice_envelope[voice]; + + key = note*0x1000+bend; + + /* override key if envelope says so */ + if ((env->key>=0)&&(env->key<=127)) key=env->key*0x1000; + + /* check key number is within range */ + if (key>0x7ffff) key=0x7ffff; + if (key<0) key=0; + + ip=env->ipbase+(env->ipscale*key)/1200; + + emu8k_modulate_ip(voice,ip); +} +static END_OF_FUNCTION (awe32_set_pitch); + + + +/* awe32_key_off: + * Hey, guess what this does :-) + */ +static void awe32_key_off(int voice) { + emu8k_releasesound (voice,voice_envelope[voice]); +} +static END_OF_FUNCTION(awe32_key_off); + + + +/* awe32_detect: + * AWE32/EMU8000 detection routine. + */ +static int awe32_detect() { + if (emu8k_detect()) { + sprintf (awe32_desc,"SB AWE32/compatible on port 0x%04x",_emu8k_baseport); + return TRUE; + } else { + sprintf(allegro_error, "AWE32 not detected"); + return FALSE; + } +} + + + +/* awe32_lockmem: + * Locks required memory blocks + */ +static void awe32_lockmem() { + +/* Functions */ + LOCK_FUNCTION(awe32_key_on); + LOCK_FUNCTION(awe32_key_off); + LOCK_FUNCTION(_awe32_do_note); + LOCK_FUNCTION(awe32_set_volume); + LOCK_FUNCTION(awe32_set_pitch); + +/* Data */ + /* Most data is locked on allocation */ + LOCK_VARIABLE(midi_preset); + LOCK_VARIABLE(voice_envelope); + LOCK_VARIABLE(exclusive_class_info); + LOCK_VARIABLE(midi_awe32); + +/* Stuff in emu8k.c */ + emu8k_lock(); + +} + + + +/* awe32_init: + * Setup the AWE32/EMU8000 driver. + */ +static int awe32_init(int voices) { + int chan; + + emu8k_init(); + translate_soundfont_into_something_useful(); + voice_envelope = (struct envparms_t **) _lock_malloc (32 * sizeof(struct envparms_t *)); + exclusive_class_info = (int *) _lock_malloc (32 * sizeof (int)); + awe32_lockmem(); + + for (chan = 0; chan < 32; chan++) { + voice_envelope[chan] = NULL; + exclusive_class_info[chan] = 0; + } + + return 0; +} + + + +/* awe32_exit: + * Cleanup when we are finished. + */ +static void awe32_exit() { + int i; + for (i=0;i<_emu8k_numchannels;i++) emu8k_terminatesound(i); + destroy_useful_version_of_soundfont(); + free (voice_envelope); + free (exclusive_class_info); +} + + + +/* translate_soundfont_into_something_useful: + * Like it says, translate the soundfont data into something we can use + * when playing notes. + */ +static void translate_soundfont_into_something_useful() { + int p,s,gen,weirdo; + struct midi_preset_t *thing_to_write=NULL; + generators_t temp_gens; + int global_split=0,global_weirdo=0,num_weirdos; + + midi_preset = (struct midi_preset_t *)_lock_malloc(129*sizeof(struct midi_preset_t)); + for (p=0;p<_awe_sf_num_presets;p++) { + if (_awe_sf_presets[p*3+1]==0) { + thing_to_write = &midi_preset[_awe_sf_presets[p*3+0]]; + } else if (_awe_sf_presets[p*3+1]==128) { + thing_to_write = &midi_preset[128]; + } else { + thing_to_write = NULL; + } + if (thing_to_write) { + thing_to_write->num_splits=_awe_sf_presets[p*3+2]; + thing_to_write->split=(struct envparms_t **)_lock_malloc(thing_to_write->num_splits*sizeof(struct envparms_t *)); + for (s=0;snum_splits;s++) { + for (gen=0;gensplit[s]=emu8k_createenvelope(temp_gens); + } + } else { + strcpy(allegro_error,"AWE32 driver: had trouble with the embedded data"); + } + } +} + + + +/* destroy_useful_version_of_soundfont: + * Destroys the data created by the above function + */ +static void destroy_useful_version_of_soundfont() { + int p,s; + for (p=0;p<129;p++) + if (midi_preset[p].num_splits>0) { + for (s=0;s +#include + +#include "allegro.h" +#include "internal.h" + + +static char gus_desc[80] = "not initialised"; + +static int gus_detect(); + +static int gus_digi_init(); +static void gus_digi_exit(); + + +DIGI_DRIVER digi_gus = /* GUS driver for playing digital sfx */ +{ + "Gravis Ultrasound", + gus_desc, + 0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX, + gus_detect, + gus_digi_init, + gus_digi_exit, + _dummy_mixer_volume, + _dummy_init_voice, + _dummy_noop1, + _dummy_noop1, + _dummy_noop1, + _dummy_noop2, + _dummy_get_position, + _dummy_noop2, + _dummy_get, + _dummy_noop2, + _dummy_noop3, + _dummy_noop1, + _dummy_get, + _dummy_noop2, + _dummy_noop3, + _dummy_noop1, + _dummy_get, + _dummy_noop2, + _dummy_noop3, + _dummy_noop1, + _dummy_noop3, + _dummy_noop3, + _dummy_noop3 +}; + + +static int gus_midi_init(); +static void gus_midi_exit(); +static int gus_load_patches(char *patches, char *drums); +static void gus_key_on(int inst, int note, int bend, int vol, int pan); +static void gus_key_off(int voice); +static void gus_set_volume(int voice, int vol); +static void gus_set_pitch(int voice, int note, int bend); + + +MIDI_DRIVER midi_gus = /* GUS driver for playing MIDI music */ +{ + "Gravis Ultrasound", + gus_desc, + 0, 0, -1, 24, -1, -1, + gus_detect, + gus_midi_init, + gus_midi_exit, + NULL, + NULL, + gus_load_patches, + _dummy_adjust_patches, + gus_key_on, + gus_key_off, + gus_set_volume, + gus_set_pitch, + _dummy_noop2, + _dummy_noop2 +}; + + +static void gus_lock_data(); + + + +/* gus_detect: + * GUS detection routine. Returns TRUE if a GUS exists, otherwise FALSE. + * It shouldn't do anything that drastically alters the state of the + * card, since it is likely to get called more than once. + */ +static int gus_detect() +{ + strcpy(allegro_error, "GUS driver not written yet"); + + /* if (no GUS present) */ + return FALSE; + + sprintf(gus_desc, "Some info about the GUS hardware"); + return TRUE; +} + + + +/* gus_digi_init: + * Called once at startup to initialise the digital sample playing code. + */ +static int gus_digi_init() +{ + gus_lock_data(); + +#if GOT_SOME_GUS_CODE_TO_PUT_IN_HERE + /* Allocate conventional memory buffers for the DMA transfer. Pass the + * size of the buffer in bytes, an int pointer which will be set to the + * protected mode selector to free the buffer with, and a pointer to a + * long which will be set to the linear address of the buffer in + * conventional memory. + */ + if (_dma_allocate_mem(buffer_size, &(int)selector, &(long)address) != 0) + return -1; + + /* Initialise the sample mixing module. Pass the size of each buffer + * (in samples, not bytes: if you pass 1024 for this parameter you would + * need a _dma_allocate_mem of 1024 bytes if you are using 8 bit data, but + * of 2048 if in 16 bit mode. Don't double the size for stereo modes + * though: in an 8 bit stereo mode passing 1024 will still cause it to + * mix 1024 bytes into each buffer, just the buffer will only last for + * half as long...). Also pass the sample frequency the GUS is running at, + * and whether you want stereo and/or 16 bit data. + */ + if (_mixer_init(buffer_size, gus_frequency, stereo, 16bit) != 0) + return -1; + + /* + Apart from those calls, do whatever GUS-type stuff you need to do, set + the dma transfer going (_dma_start(channel, addr, size, auto_init_flag)), + and whenever a buffer needs filling with some more samples, call + _mix_some_samples(linear_address_of_buffer_in_conventional_memory); + btw. the 16 bit sample mixing and 16 bit DMA transfer modes are not + tested, since I only have an 8 bit SB. If they don't work, it might well + be my fault :-) + */ +#endif + + return 0; +} + + + +/* gus_digi_exit: + * gus driver cleanup routine, removes ints, stops dma, frees buffers, etc. + */ +static void gus_digi_exit() +{ +#if GOT_SOME_GUS_CODE_TO_PUT_IN_HERE + + _dma_stop(whatever_dma_channel_you_are_using); + __dpmi_free_dos_memory(the selector returned by _dma_allocate_mem()); + _mixer_exit(); + + etc. + +#endif +} + + + +/* gus_midi_init: + * Called once at startup to setup the GUS MIDI driver. + */ +static int gus_midi_init() +{ + gus_lock_data(); + + /* etc */ + + return 0; +} + + + +/* gus_midi_exit: + * Cleanup the MIDI driver. I ought to have turned off all the active + * voices by the time this gets called, but it wouldn't hurt to reset + * them all anyway. + */ +static void gus_midi_exit() +{ +} + + + +/* gus_load_patches: + * Called before starting to play a MIDI file, to load all the patches it + * uses into GUS ram. No MIDI voices will be active when this is called, + * so you are free to unload whatever old data you want. Patches points + * to an array of 128 flags indicating which GM sounds are used in the + * piece, and drums to an array of 128 flags indicating which drum sounds + * are used (the GM standard only defines drum sounds 35 (base drum) to + * 81 (open triangle), so flags outside that range are guarranteed to be + * zero). Should return 0 for success, -1 on failure. + * + * What should we do if there isn't enough GUS ram to load all the samples? + * Return an error code and not play the midi file? Or replace some patches + * with others? And if so, should this routine do those replacements, or + * should you just return an error code to me, and me call you again with + * a reduced list of requirements? If we are going to do patch replacements, + * it would seem sensible to do it at a higher level than the GUS driver, + * so at a later date any other wavetable drivers could use the same code. + * What do you think? + */ +static int gus_load_patches(char *patches, char *drums) +{ + return 0; +} + +static END_OF_FUNCTION(gus_load_patches); + + + +/* gus_key_on: + * Triggers the specified MIDI voice. The instrument is specified as a + * GM patch number. Drums are indicated by passing an instrument greater + * than 128, in which case you should trigger the GM percussion sound + * normally mapped to drum key (inst-128). Drum sounds can ignore the + * pitch, bend, and pan parameters, but should respond to volume. The + * pitch is a midi note number (60=middle C, I think...). Pan and + * volume are from 0 (left/min) to 127 (right/max). The bend isn't a midi + * pitch bend value: it ranges from 0 (normal pitch) to 0xFFF (just a + * fraction flatter than a semitone up). + */ +static void gus_key_on(int inst, int note, int bend, int vol, int pan) +{ + int voice = _midi_allocate_voice(-1, -1); + if (voice < 0) + return; + + /* after you set the sample to play and trigger the note, this is pretty + * much equivelant to: + */ + gus_set_pitch(voice, note, bend); + gus_set_volume(voice, vol); +} + +static END_OF_FUNCTION(gus_key_on); + + + +/* gus_key_off: + * Hey, guess what this does :-) + */ +static void gus_key_off(int voice) +{ + /* do something */ +} + +static END_OF_FUNCTION(gus_key_off); + + + +/* gus_set_volume: + * Alters the volume of the specified voice (vol range 0-127). Should only + * ever be called while the voice is playing... + */ +static void gus_set_volume(int voice, int vol) +{ + /* do something */ +} + +static END_OF_FUNCTION(gus_set_volume); + + + +/* gus_set_pitch: + * Alters the pitch of the specified voice. Should only be called while + * the voice is playing... + */ +static void gus_set_pitch(int voice, int note, int bend) +{ + /* do something */ +} + +static END_OF_FUNCTION(gus_set_pitch); + + + +/* + * Locks all the memory touched by parts of the GUS code that are executed + * in an interrupt context. + */ +static void gus_lock_data() +{ + LOCK_VARIABLE(digi_gus); + LOCK_VARIABLE(midi_gus); + LOCK_FUNCTION(gus_load_patches); + LOCK_FUNCTION(gus_key_on); + LOCK_FUNCTION(gus_key_off); + LOCK_FUNCTION(gus_set_volume); + LOCK_FUNCTION(gus_set_pitch); +} + diff --git a/arch/dos/allg_snd/sound/drv/mpu.c b/arch/dos/allg_snd/sound/drv/mpu.c new file mode 100644 index 00000000..970c73d7 --- /dev/null +++ b/arch/dos/allg_snd/sound/drv/mpu.c @@ -0,0 +1,164 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * By Shawn Hargreaves, + * 1 Salisbury Road, + * Market Drayton, + * Shropshire, + * England, TF9 1AJ. + * + * Direct output to an MPU-401 MIDI interface. + * + * Marcel de Kogel fixed my original broken version, so that it now + * actually works :-) + * + * See readme.txt for copyright information. + */ + + +#ifndef DJGPP +#error This file should only be used by the djgpp version of Allegro +#endif + +#include +#include +#include + +#include "allegro.h" +#include "internal.h" + + +/* external interface to the MPU-401 driver */ +static int mpu_detect(); +static int mpu_init(int voices); +static void mpu_exit(); +static void mpu_output(unsigned char data); + +static char mpu_desc[80] = "not initialised"; + + +MIDI_DRIVER midi_mpu401 = +{ + "MPU-401", + mpu_desc, + 0, 0, 0xFFFF, 0, -1, -1, + mpu_detect, + mpu_init, + mpu_exit, + NULL, + mpu_output, + _dummy_load_patches, + _dummy_adjust_patches, + _dummy_key_on, + _dummy_noop1, + _dummy_noop2, + _dummy_noop3, + _dummy_noop2, + _dummy_noop2 +}; + + + +/* wait_for_mpu: + * Waits for the specified bit to clear on the specified port. Returns zero + * if it cleared, -1 if it timed out. + */ +static inline int wait_for_mpu(int flag, int port) +{ + int timeout; + + for (timeout=0; timeout<0x7FFF; timeout++) + if (!(inportb(port) & flag)) + return 0; + + return -1; +} + + + +/* mpu_output: + * Writes a byte to the MPU-401 midi interface. + */ +static void mpu_output(unsigned char data) +{ + outportb(_mpu_port, data); + inportb (_mpu_port); + wait_for_mpu(0x40, _mpu_port+1); +} + +static END_OF_FUNCTION(mpu_output); + + + +/* mpu_detect: + * Detects the presence of an MPU-401 compatible midi interface. + */ +static int mpu_detect() +{ + char *blaster = getenv("BLASTER"); + + /* parse BLASTER env */ + if ((blaster) && (_mpu_port < 0)) { + while (*blaster) { + while ((*blaster == ' ') || (*blaster == '\t')) + blaster++; + + if ((*blaster == 'p') || (*blaster == 'P')) + _mpu_port = strtol(blaster+1, NULL, 16); + + while ((*blaster) && (*blaster != ' ') && (*blaster != '\t')) + blaster++; + } + } + + /* if that didn't work, guess :-) */ + if (_mpu_port < 0) + _mpu_port = 0x330; + + /* check whether the MPU is there */ + outportb(_mpu_port+1,0xFF); /* reset the mpu */ + inportb(_mpu_port); + if (wait_for_mpu(0x40, _mpu_port+1) != 0) { /* wait for ready */ + strcpy(allegro_error, "MPU-401 not found"); + return FALSE; + } + + sprintf(mpu_desc, "MPU-401 MIDI interface on port %d", _mpu_port); + return TRUE; +} + + + +/* mpu_init: + * Initialises the MPU-401 midi interface. + */ +static int mpu_init(int voices) +{ + outportb(_mpu_port+1, 0x3F); /* put MPU in UART mode */ + inportb (_mpu_port); + wait_for_mpu (0x80,_mpu_port+1); + + LOCK_VARIABLE(midi_mpu401); + LOCK_VARIABLE(_mpu_port); + LOCK_FUNCTION(mpu_output); + + return 0; +} + + + +/* mpu_exit: + * Resets the MPU-401 midi interface when we are finished. + */ +static void mpu_exit() +{ + outportb(_mpu_port+1, 0xFF); +} + + diff --git a/arch/dos/allg_snd/sound/drv/sb.c b/arch/dos/allg_snd/sound/drv/sb.c new file mode 100644 index 00000000..55646d3d --- /dev/null +++ b/arch/dos/allg_snd/sound/drv/sb.c @@ -0,0 +1,795 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * By Shawn Hargreaves, + * 1 Salisbury Road, + * Market Drayton, + * Shropshire, + * England, TF9 1AJ. + * + * Soundblaster driver. Supports DMA driven sample playback (mixing + * up to eight samples at a time) and raw note output to the SB MIDI + * port. The Adlib (FM synth) MIDI playing code is in adlib.c. + * + * See readme.txt for copyright information. + */ + + +#ifndef DJGPP +#error This file should only be used by the djgpp version of Allegro +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "allegro.h" +#include "internal.h" + + +/* external interface to the digital SB driver */ +static int sb_detect(); +static int sb_init(int voices); +static void sb_exit(); +static int sb_mixer_volume(int volume); + +static char sb_desc[80] = "not initialised"; + + +DIGI_DRIVER digi_sb = +{ + "Sound Blaster", + sb_desc, + 0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX, + sb_detect, + sb_init, + sb_exit, + sb_mixer_volume, + _mixer_init_voice, + _mixer_release_voice, + _mixer_start_voice, + _mixer_stop_voice, + _mixer_loop_voice, + _mixer_get_position, + _mixer_set_position, + _mixer_get_volume, + _mixer_set_volume, + _mixer_ramp_volume, + _mixer_stop_volume_ramp, + _mixer_get_frequency, + _mixer_set_frequency, + _mixer_sweep_frequency, + _mixer_stop_frequency_sweep, + _mixer_get_pan, + _mixer_set_pan, + _mixer_sweep_pan, + _mixer_stop_pan_sweep, + _mixer_set_echo, + _mixer_set_tremolo, + _mixer_set_vibrato +}; + + +/* external interface to the SB midi output driver */ +static int sb_midi_init(int voices); +static void sb_midi_exit(); +static void sb_midi_output(unsigned char data); + +static char sb_midi_desc[80] = "not initialised"; + + +MIDI_DRIVER midi_sb_out = +{ + "SB MIDI interface", + sb_midi_desc, + 0, 0, 0xFFFF, 0, -1, -1, + sb_detect, + sb_midi_init, + sb_midi_exit, + NULL, + sb_midi_output, + _dummy_load_patches, + _dummy_adjust_patches, + _dummy_key_on, + _dummy_noop1, + _dummy_noop2, + _dummy_noop3, + _dummy_noop2, + _dummy_noop2 +}; + + +static int sb_in_use = FALSE; /* is SB being used? */ +static int sb_stereo = FALSE; /* in stereo mode? */ +static int sb_16bit = FALSE; /* in 16 bit mode? */ +static int sb_int = -1; /* interrupt vector */ +static int sb_dsp_ver = -1; /* SB DSP version */ +/*static*/ int sb_hw_dsp_ver = -1; /* as reported by autodetect */ +static int sb_dma_size = -1; /* size of dma transfer in bytes */ +static int sb_dma_mix_size = -1; /* number of samples to mix */ +static int sb_dma_count = 0; /* need to resync with dma? */ +static volatile int sb_semaphore = FALSE; /* reentrant interrupt? */ + +static int sb_sel[2]; /* selectors for the buffers */ +static unsigned long sb_buf[2]; /* pointers to the two buffers */ +static int sb_bufnum = 0; /* the one currently in use */ + +static unsigned char sb_default_pic1; /* PIC mask flags to restore */ +static unsigned char sb_default_pic2; + +static int sb_master_vol; /* stored mixer settings */ +static int sb_digi_vol; +static int sb_fm_vol; + +static void sb_lock_mem(); + + + +/* sb_read_dsp: + * Reads a byte from the SB DSP chip. Returns -1 if it times out. + */ +static inline volatile int sb_read_dsp() +{ + int x; + + for (x=0; x<0xffff; x++) + if (inportb(0x0E + _sb_port) & 0x80) + return inportb(0x0A+_sb_port); + + return -1; +} + + + +/* sb_write_dsp: + * Writes a byte to the SB DSP chip. Returns -1 if it times out. + */ +static inline volatile int sb_write_dsp(unsigned char byte) +{ + int x; + + for (x=0; x<0xffff; x++) { + if (!(inportb(0x0C+_sb_port) & 0x80)) { + outportb(0x0C+_sb_port, byte); + return 0; + } + } + return -1; +} + + + +/* sb_voice: + * Turns the SB speaker on or off. + */ +static void sb_voice(int state) +{ + if (state) { + sb_write_dsp(0xD1); + + if (sb_hw_dsp_ver >= 0x300) { /* set up the mixer */ + + outportb(_sb_port+4, 0x22); /* store master volume */ + sb_master_vol = inportb(_sb_port+5); + + outportb(_sb_port+4, 4); /* store DAC level */ + sb_digi_vol = inportb(_sb_port+5); + + outportb(_sb_port+4, 0x26); /* store FM level */ + sb_fm_vol = inportb(_sb_port+5); + } + } + else { + sb_write_dsp(0xD3); + + if (sb_hw_dsp_ver >= 0x300) { /* reset previous mixer settings */ + + outportb(_sb_port+4, 0x22); /* restore master volume */ + outportb(_sb_port+5, sb_master_vol); + + outportb(_sb_port+4, 4); /* restore DAC level */ + outportb(_sb_port+5, sb_digi_vol); + + outportb(_sb_port+4, 0x26); /* restore FM level */ + outportb(_sb_port+5, sb_fm_vol); + } + } +} + + + +/* _sb_set_mixer: + * Alters the SB-Pro hardware mixer. + */ +int _sb_set_mixer(int digi_volume, int midi_volume) +{ + if (sb_hw_dsp_ver < 0x300) + return -1; + + if (digi_volume >= 0) { /* set DAC level */ + outportb(_sb_port+4, 4); + outportb(_sb_port+5, (digi_volume & 0xF0) | (digi_volume >> 4)); + } + + if (midi_volume >= 0) { /* set FM level */ + outportb(_sb_port+4, 0x26); + outportb(_sb_port+5, (midi_volume & 0xF0) | (midi_volume >> 4)); + } + + return 0; +} + + + +/* sb_mixer_volume: + * Sets the SB mixer volume for playing digital samples. + */ +static int sb_mixer_volume(int volume) +{ + return _sb_set_mixer(volume, -1); +} + + + +/* sb_stereo_mode: + * Enables or disables stereo output for SB-Pro. + */ +static void sb_stereo_mode(int enable) +{ + outportb(_sb_port+0x04, 0x0E); + outportb(_sb_port+0x05, (enable ? 2 : 0)); +} + + + +/* sb_set_sample_rate: + * The parameter is the rate to set in Hz (samples per second). + */ +static void sb_set_sample_rate(unsigned int rate) +{ + if (sb_16bit) { + sb_write_dsp(0x41); + sb_write_dsp(rate >> 8); + sb_write_dsp(rate & 0xff); + } + else { + if (sb_stereo) + rate *= 2; + + sb_write_dsp(0x40); + sb_write_dsp((unsigned char)(256-1000000/rate)); + } +} + + + +/* sb_reset_dsp: + * Resets the SB DSP chip, returning -1 on error. + */ +static int sb_reset_dsp() +{ + int x; + + outportb(0x06+_sb_port, 1); + + for (x=0; x<8; x++) + inportb(0x06+_sb_port); + + outportb(0x06+_sb_port, 0); + + if (sb_read_dsp() != 0xAA) + return -1; + + return 0; +} + + + +/* _sb_read_dsp_version: + * Reads the version number of the SB DSP chip, returning -1 on error. + */ +int _sb_read_dsp_version() +{ + int x, y; + + if (sb_hw_dsp_ver > 0) + return sb_hw_dsp_ver; + + if (_sb_port <= 0) + _sb_port = 0x220; + + if (sb_reset_dsp() != 0) + sb_hw_dsp_ver = -1; + else { + sb_write_dsp(0xE1); + x = sb_read_dsp(); + y = sb_read_dsp(); + sb_hw_dsp_ver = ((x << 8) | y); + } + + return sb_hw_dsp_ver; +} + + + +/* sb_play_buffer: + * Starts a dma transfer of size bytes. On cards capable of it, the + * transfer will use auto-initialised dma, so there is no need to call + * this routine more than once. On older cards it must be called from + * the end-of-buffer handler to switch to the new buffer. + */ +static void sb_play_buffer(int size) +{ + if (sb_dsp_ver <= 0x200) { /* 8 bit single-shot */ + sb_write_dsp(0x14); + sb_write_dsp((size-1) & 0xFF); + sb_write_dsp((size-1) >> 8); + } + else if (sb_dsp_ver < 0x400) { /* 8 bit auto-initialised */ + sb_write_dsp(0x48); + sb_write_dsp((size-1) & 0xff); + sb_write_dsp((size-1) >> 8); + sb_write_dsp(0x90); + } + else { /* 16 bit */ + size /= 2; + sb_write_dsp(0xB6); + sb_write_dsp(0x20); + sb_write_dsp((size-1) & 0xFF); + sb_write_dsp((size-1) >> 8); + } +} + +static END_OF_FUNCTION(sb_play_buffer); + + + +/* sb_interrupt: + * The SB end-of-buffer interrupt handler. Swaps to the other buffer + * if the card doesn't have auto-initialised dma, and then refills the + * buffer that just finished playing. + */ +static int sb_interrupt() +{ + if (sb_dsp_ver <= 0x200) { /* not auto-initialised */ + _dma_start(_sb_dma, sb_buf[1-sb_bufnum], sb_dma_size, FALSE); + sb_play_buffer(sb_dma_size); + } + else { /* poll dma position */ + sb_dma_count++; + if (sb_dma_count > 16) { + sb_bufnum = (_dma_todo(_sb_dma) > (unsigned)sb_dma_size) ? 1 : 0; + sb_dma_count = 0; + } + } + + if (!sb_semaphore) { + sb_semaphore = TRUE; + + ENABLE(); /* mix some more samples */ + _mix_some_samples(sb_buf[sb_bufnum], _dos_ds, FALSE); + DISABLE(); + + sb_semaphore = FALSE; + } + + sb_bufnum = 1 - sb_bufnum; + + if (sb_16bit) /* acknowlege SB */ + inportb(_sb_port+0x0F); + else + inportb(_sb_port+0x0E); + + outportb(0x20, 0x20); /* acknowledge interrupt */ + outportb(0xA0, 0x20); + + return 0; +} + +static END_OF_FUNCTION(sb_interrupt); + + + +/* sb_detect: + * SB detection routine. Uses the BLASTER environment variable, + * or 'sensible' guesses if that doesn't exist. + */ +static int sb_detect() +{ + char *blaster = getenv("BLASTER"); + char *msg; + int dma8 = 1; + int dma16 = 5; + int max_freq; + int default_freq; + + /* what breed of SB are we looking for? */ + switch (digi_card) { + + case DIGI_SB10: + sb_dsp_ver = 0x100; + break; + + case DIGI_SB15: + sb_dsp_ver = 0x200; + break; + + case DIGI_SB20: + sb_dsp_ver = 0x201; + break; + + case DIGI_SBPRO: + sb_dsp_ver = 0x300; + break; + + case DIGI_SB16: + sb_dsp_ver = 0x400; + break; + + default: + sb_dsp_ver = -1; + break; + } + + /* parse BLASTER env */ + if (blaster) { + while (*blaster) { + while ((*blaster == ' ') || (*blaster == '\t')) + blaster++; + + if (*blaster) { + switch (*blaster) { + case 'a': case 'A': + if (_sb_port < 0) + _sb_port = strtol(blaster+1, NULL, 16); + break; + + case 'i': case 'I': + if (_sb_irq < 0) + _sb_irq = strtol(blaster+1, NULL, 10); + //added on 11/5/98 by Victor Rachels to hardwire irq 2->9 + if (_sb_irq == 0x02) + _sb_irq=0x09; + //end this section addition + break; + + case 'd': case 'D': + dma8 = strtol(blaster+1, NULL, 10); + break; + + case 'h': case 'H': + dma16 = strtol(blaster+1, NULL, 10); + break; + } + + while ((*blaster) && (*blaster != ' ') && (*blaster != '\t')) + blaster++; + } + } + } + + if (_sb_port < 0) + _sb_port = 0x220; + + if (_sb_irq < 0) + _sb_irq = 7; + + /* make sure we got a good port address */ + if (sb_reset_dsp() != 0) { + static int bases[] = { 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0 }; + int i; + + for (i=0; bases[i]; i++) { + _sb_port = bases[i]; + if (sb_reset_dsp() == 0) + break; + } + } + + /* check if the card really exists */ + _sb_read_dsp_version(); + if (sb_hw_dsp_ver < 0) { + strcpy(allegro_error, "Sound Blaster not found"); + return FALSE; + } + + if (sb_dsp_ver < 0) + sb_dsp_ver = sb_hw_dsp_ver; + else { + if (sb_dsp_ver > sb_hw_dsp_ver) { + sb_hw_dsp_ver = sb_dsp_ver = -1; + strcpy(allegro_error, "Older SB version detected"); + return FALSE; + } + } + + /* figure out the hardware interrupt number */ + if (_sb_irq > 7) + sb_int = _sb_irq + 104; + else + sb_int = _sb_irq + 8; + + /* what breed of SB? */ + if (sb_dsp_ver >= 0x400) { + msg = "SB 16"; + max_freq = 45454; + default_freq = 22727; + } + else if (sb_dsp_ver >= 0x300) { + msg = "SB Pro"; + max_freq = 22727; + default_freq = 22727; + } + else if (sb_dsp_ver >= 0x201) { + msg = "SB 2.0"; + max_freq = 45454; + default_freq = 22727; + } + else if (sb_dsp_ver >= 0x200) { + msg = "SB 1.5"; + max_freq = 16129; + default_freq = 16129; + } + else { + msg = "SB 1.0"; + max_freq = 16129; + default_freq = 16129; + } + + /* set up the playback frequency */ + if (_sb_freq <= 0) + _sb_freq = default_freq; + + if (_sb_freq < 15000) { + _sb_freq = 11906; + sb_dma_size = 128; + } + else if (MIN(_sb_freq, max_freq) < 20000) { + _sb_freq = 16129; + sb_dma_size = 128; + } + else if (MIN(_sb_freq, max_freq) < 40000) { + _sb_freq = 22727; + sb_dma_size = 256; + } + else { + _sb_freq = 45454; + sb_dma_size = 512; + } + + if (sb_dsp_ver <= 0x200) + sb_dma_size *= 4; + + sb_dma_mix_size = sb_dma_size; + + /* can we handle 16 bit playback? */ + if (sb_dsp_ver >= 0x400) { + if (_sb_dma < 0) + _sb_dma = dma16; + sb_16bit = TRUE; + sb_dma_size <<= 1; + } + else { + if (_sb_dma < 0) + _sb_dma = dma8; + sb_16bit = FALSE; + } + + /* can we handle stereo? */ + if (sb_dsp_ver >= 0x300) { + sb_stereo = TRUE; + sb_dma_size <<= 1; + sb_dma_mix_size <<= 1; + } + else + sb_stereo = FALSE; + + /* set up the card description */ + sprintf(sb_desc, "%s (%d hz) on port %X, using IRQ %d and DMA channel %d", + msg, _sb_freq, _sb_port, _sb_irq, _sb_dma); + + return TRUE; +} + + + +/* sb_init: + * SB init routine: returns zero on success, -1 on failure. + */ +static int sb_init(int voices) +{ + if (sb_in_use) { + strcpy(allegro_error, "Can't use SB MIDI interface and DSP at the same time"); + return -1; + } + + if ((digi_card == DIGI_SB) || (digi_card == DIGI_AUTODETECT)) { + if (sb_dsp_ver <= 0x100) + digi_card = DIGI_SB10; + else if (sb_dsp_ver <= 0x200) + digi_card = DIGI_SB15; + else if (sb_dsp_ver < 0x300) + digi_card = DIGI_SB20; + else if (sb_dsp_ver < 0x400) + digi_card = DIGI_SBPRO; + else + digi_card = DIGI_SB16; + } + + if (sb_dsp_ver <= 0x200) { /* two conventional mem buffers */ + if ((_dma_allocate_mem(sb_dma_size, &sb_sel[0], &sb_buf[0]) != 0) || + (_dma_allocate_mem(sb_dma_size, &sb_sel[1], &sb_buf[1]) != 0)) + return -1; + } + else { /* auto-init dma, one big buffer */ + if (_dma_allocate_mem(sb_dma_size*2, &sb_sel[0], &sb_buf[0]) != 0) + return -1; + + sb_sel[1] = sb_sel[0]; + sb_buf[1] = sb_buf[0] + sb_dma_size; + } + + sb_lock_mem(); + + digi_sb.voices = voices; + + if (_mixer_init(sb_dma_mix_size, _sb_freq, sb_stereo, sb_16bit, &digi_sb.voices) != 0) + return -1; + + _mix_some_samples(sb_buf[0], _dos_ds, FALSE); + _mix_some_samples(sb_buf[1], _dos_ds, FALSE); + sb_bufnum = 0; + + sb_default_pic1 = inportb(0x21); + sb_default_pic2 = inportb(0xA1); + + if (_sb_irq > 7) { /* enable irq2 and PIC-2 irq */ + outportb(0x21, sb_default_pic1 & 0xFB); + outportb(0xA1, sb_default_pic2 & (~(1<<(_sb_irq-8)))); + } + else /* enable PIC-1 irq */ + outportb(0x21, sb_default_pic1 & (~(1<<_sb_irq))); + + _install_irq(sb_int, sb_interrupt); + + sb_voice(1); + sb_set_sample_rate(_sb_freq); + + if ((sb_hw_dsp_ver >= 0x300) && (sb_dsp_ver < 0x400)) + sb_stereo_mode(sb_stereo); + + if (sb_dsp_ver <= 0x200) + _dma_start(_sb_dma, sb_buf[0], sb_dma_size, FALSE); + else + _dma_start(_sb_dma, sb_buf[0], sb_dma_size*2, TRUE); + + sb_play_buffer(sb_dma_size); + + sb_in_use = TRUE; + return 0; +} + + + +/* sb_exit: + * SB driver cleanup routine, removes ints, stops dma, frees buffers, etc. + */ +static void sb_exit() +{ + /* halt sound output */ + sb_voice(0); + + /* stop dma transfer */ + _dma_stop(_sb_dma); + + if (sb_dsp_ver <= 0x0200) + sb_write_dsp(0xD0); + + sb_reset_dsp(); + + /* restore interrupts */ + _remove_irq(sb_int); + + /* reset PIC channels */ + outportb(0x21, sb_default_pic1); + outportb(0xA1, sb_default_pic2); + + /* free conventional memory buffer */ + __dpmi_free_dos_memory(sb_sel[0]); + if (sb_sel[1] != sb_sel[0]) + __dpmi_free_dos_memory(sb_sel[1]); + + _mixer_exit(); + + sb_hw_dsp_ver = sb_dsp_ver = -1; + sb_in_use = FALSE; +} + + + +/* sb_midi_init: + * Initialises the SB midi interface, returning zero on success. + */ +static int sb_midi_init(int voices) +{ + if (sb_in_use) { + strcpy(allegro_error, "Can't use SB MIDI interface and DSP at the same time"); + return -1; + } + + sb_dsp_ver = -1; + + sb_lock_mem(); + + sprintf(sb_midi_desc, "Sound Blaster MIDI interface on port %X", _sb_port); + + sb_in_use = TRUE; + return 0; +} + + + +/* sb_midi_exit: + * Resets the SB midi interface when we are finished. + */ +static void sb_midi_exit() +{ + sb_reset_dsp(); + sb_in_use = FALSE; +} + + + +/* sb_midi_output: + * Writes a byte to the SB midi interface. + */ +static void sb_midi_output(unsigned char data) +{ + sb_write_dsp(0x38); + sb_write_dsp(data); +} + +static END_OF_FUNCTION(sb_midi_output); + + + +/* sb_lock_mem: + * Locks all the memory touched by parts of the SB code that are executed + * in an interrupt context. + */ +static void sb_lock_mem() +{ + LOCK_VARIABLE(digi_sb); + LOCK_VARIABLE(midi_sb_out); + LOCK_VARIABLE(_sb_freq); + LOCK_VARIABLE(_sb_port); + LOCK_VARIABLE(_sb_dma); + LOCK_VARIABLE(_sb_irq); + LOCK_VARIABLE(sb_int); + LOCK_VARIABLE(sb_in_use); + LOCK_VARIABLE(sb_dsp_ver); + LOCK_VARIABLE(sb_hw_dsp_ver); + LOCK_VARIABLE(sb_dma_size); + LOCK_VARIABLE(sb_dma_mix_size); + LOCK_VARIABLE(sb_sel); + LOCK_VARIABLE(sb_buf); + LOCK_VARIABLE(sb_bufnum); + LOCK_VARIABLE(sb_default_pic1); + LOCK_VARIABLE(sb_default_pic2); + LOCK_VARIABLE(sb_dma_count); + LOCK_VARIABLE(sb_semaphore); + LOCK_FUNCTION(sb_play_buffer); + LOCK_FUNCTION(sb_interrupt); + LOCK_FUNCTION(sb_midi_output); +} + diff --git a/arch/dos/allg_snd/sound/interndj.h b/arch/dos/allg_snd/sound/interndj.h new file mode 100644 index 00000000..25f80873 --- /dev/null +++ b/arch/dos/allg_snd/sound/interndj.h @@ -0,0 +1,210 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * By Shawn Hargreaves, + * 1 Salisbury Road, + * Market Drayton, + * Shropshire, + * England, TF9 1AJ. + * + * Some definitions for internal use by the library code. + * This should not be included by user programs. + * + * See readme.txt for copyright information. + */ + + +#ifndef INTERNDJ_H +#define INTERNDJ_H + +#ifndef DJGPP +#error This file should only be used by the djgpp version of Allegro +#endif + + +#include + + +/* file access macros */ +#define FILE_OPEN(filename, handle) handle = open(filename, O_RDONLY | O_BINARY, S_IRUSR | S_IWUSR) +#define FILE_CREATE(filename, handle) handle = open(filename, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR) +#define FILE_CLOSE(handle) close(handle) +#define FILE_READ(handle, buf, size, sz) sz = read(handle, buf, size) +#define FILE_WRITE(handle, buf, size, sz) sz = write(handle, buf, size) +#define FILE_SEARCH_STRUCT struct ffblk +#define FILE_FINDFIRST(filename, attrib, dta) findfirst(filename, dta, attrib) +#define FILE_FINDNEXT(dta) findnext(dta) +#define FILE_ATTRIB ff_attrib +#define FILE_SIZE ff_fsize +#define FILE_NAME ff_name +#define FILE_TIME ff_ftime +#define FILE_DATE ff_fdate + + +/* macros to enable and disable interrupts */ +#define DISABLE() asm volatile ("cli") +#define ENABLE() asm volatile ("sti") + + +__INLINE__ void enter_critical() +{ + if (windows_version >= 3) { + __dpmi_regs r; + r.x.ax = 0x1681; + __dpmi_int(0x2F, &r); + } + + DISABLE(); +} + + +__INLINE__ void exit_critical() +{ + if (windows_version >= 3) { + __dpmi_regs r; + r.x.ax = 0x1682; + __dpmi_int(0x2F, &r); + } + + ENABLE(); +} + + +/* interrupt hander stuff */ +int _install_irq(int num, int (*handler)()); +void _remove_irq(int num); + +typedef struct _IRQ_HANDLER +{ + int (*handler)(); /* our C handler */ + int number; /* irq number */ + __dpmi_paddr old_vector; /* original protected mode vector */ +} _IRQ_HANDLER; + + +/* DPMI memory mapping routines */ +int _create_physical_mapping(unsigned long *linear, int *segment, unsigned long physaddr, int size); +void _remove_physical_mapping(unsigned long *linear, int *segment); +int _create_linear_mapping(unsigned long *linear, unsigned long physaddr, int size); +void _remove_linear_mapping(unsigned long *linear); +int _create_selector(int *segment, unsigned long linear, int size); +void _remove_selector(int *segment); +void _unlock_dpmi_data(void *addr, int size); + + +/* bank switching routines */ +void _vesa_window_1(); +void _vesa_window_1_end(); +void _vesa_window_2(); +void _vesa_window_2_end(); + +void _vesa_pm_window_1(); +void _vesa_pm_window_1_end(); +void _vesa_pm_window_2(); +void _vesa_pm_window_2_end(); + +void _vesa_pm_es_window_1(); +void _vesa_pm_es_window_1_end(); +void _vesa_pm_es_window_2(); +void _vesa_pm_es_window_2_end(); + +void _vbeaf_bank(); +void _vbeaf_bank_end(); + +void _vbeaf_linear_lookup(); +void _vbeaf_linear_lookup_end(); + +void _ati_bank(); +void _ati_bank_end(); + +void _mach64_write_bank(); +void _mach64_write_bank_end(); +void _mach64_read_bank(); +void _mach64_read_bank_end(); + +void _cirrus64_write_bank(); +void _cirrus64_write_bank_end(); +void _cirrus64_read_bank(); +void _cirrus64_read_bank_end(); + +void _cirrus54_bank(); +void _cirrus54_bank_end(); + +void _paradise_write_bank(); +void _paradise_read_bank(); +void _paradise_write_bank_end(); +void _paradise_read_bank_end(); + +void _s3_bank(); +void _s3_bank_end(); + +void _trident_bank(); +void _trident_bank_end(); +void _trident_read_bank(); +void _trident_read_bank_end(); +void _trident_write_bank(); +void _trident_write_bank_end(); + +void _et3000_write_bank(); +void _et3000_write_bank_end(); +void _et3000_read_bank(); +void _et3000_read_bank_end(); + +void _et4000_write_bank(); +void _et4000_write_bank_end(); +void _et4000_read_bank(); +void _et4000_read_bank_end(); + +void _video7_bank(); +void _video7_bank_end(); + + +/* stuff for the VESA and VBE/AF drivers */ +extern __dpmi_regs _dpmi_reg; + +extern int _window_2_offset; + +extern void (*_pm_vesa_switcher)(); +extern void (*_pm_vesa_scroller)(); +extern void (*_pm_vesa_pallete)(); + +extern int _mmio_segment; + +extern void *_af_driver; + +extern int _af_active; + +extern void *_af_set_bank; +extern void *_af_wait_till_idle; +extern void *_af_enable_direct_access; + + +/* stuff for setting up bitmaps */ +long _vesa_vidmem_check(long mem); + + +/* sound lib stuff */ +extern int _fm_port; +extern int _mpu_port; +extern int _sb_freq; +extern int _sb_port; +extern int _sb_dma; +extern int _sb_irq; + +int _sb_read_dsp_version(); +int _sb_set_mixer(int digi_volume, int midi_volume); + +int _dma_allocate_mem(int bytes, int *sel, unsigned long *phys); +void _dma_start(int channel, unsigned long addr, int size, int auto_init); +void _dma_stop(int channel); +unsigned long _dma_todo(int channel); +void _dma_lock_mem(); + + +#endif /* ifndef INTERNDJ_H */ diff --git a/arch/dos/allg_snd/sound/midi.c b/arch/dos/allg_snd/sound/midi.c new file mode 100644 index 00000000..f2ca0382 --- /dev/null +++ b/arch/dos/allg_snd/sound/midi.c @@ -0,0 +1,1512 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * By Shawn Hargreaves, + * 1 Salisbury Road, + * Market Drayton, + * Shropshire, + * England, TF9 1AJ. + * + * The core MIDI file player. + * + * Pause and seek functions by George Foot. + * + * See readme.txt for copyright information. + */ + + +#include +#include +#include +#include + +#include "allegro.h" +#include "internal.h" + + +/* maximum number of layers in a single voice */ +#define MIDI_LAYERS 4 + + +typedef struct MIDI_TRACK /* a track in the MIDI file */ +{ + unsigned char *pos; /* position in track data */ + long timer; /* time until next event */ + unsigned char running_status; /* last MIDI event */ +} MIDI_TRACK; + + +typedef struct MIDI_CHANNEL /* a MIDI channel */ +{ + int patch; /* current sound */ + int volume; /* volume controller */ + int pan; /* pan position */ + int pitch_bend; /* pitch bend position */ + int new_volume; /* cached volume change */ + int new_pitch_bend; /* cached pitch bend */ + int note[128][MIDI_LAYERS]; /* status of each note */ +} MIDI_CHANNEL; + + +typedef struct MIDI_VOICE /* a voice on the soundcard */ +{ + int channel; /* MIDI channel */ + int note; /* note (-1 = off) */ + int volume; /* note velocity */ + long time; /* when note was triggered */ +} MIDI_VOICE; + + +typedef struct WAITING_NOTE /* a stored note-on request */ +{ + int channel; + int note; + int volume; +} WAITING_NOTE; + + +typedef struct PATCH_TABLE /* GM -> external synth */ +{ + int bank1; /* controller #0 */ + int bank2; /* controller #32 */ + int prog; /* program change */ + int pitch; /* pitch shift */ +} PATCH_TABLE; + + +volatile long midi_pos = -1; /* position in MIDI file */ +static long midi_pos_counter; /* delta for midi_pos */ + +volatile long _midi_tick = 0; /* counter for killing notes */ + +static void midi_player(); /* core MIDI player routine */ +static void prepare_to_play(MIDI *midi); +static void midi_lock_mem(); + +static MIDI *midifile = NULL; /* the file that is playing */ + +static int midi_loop = 0; /* repeat at eof? */ + +long midi_loop_start = -1; /* where to loop back to */ +long midi_loop_end = -1; /* loop at this position */ + +static int midi_semaphore = 0; /* reentrancy flag */ +static int midi_loaded_patches = FALSE; /* loaded entire patch set? */ + +static int midi_timer_speed; /* midi_player's timer speed */ +static int midi_pos_speed; /* MIDI delta -> midi_pos */ +static int midi_speed; /* MIDI delta -> timer */ +static int midi_new_speed; /* for tempo change events */ + +static int old_midi_volume = -1; /* stored global volume */ + +static int midi_alloc_channel; /* so _midi_allocate_voice */ +static int midi_alloc_note; /* knows which note the */ +static int midi_alloc_vol; /* sound is associated with */ + +static MIDI_TRACK midi_track[MIDI_TRACKS]; /* the active tracks */ +static MIDI_VOICE midi_voice[MIDI_VOICES]; /* synth voice status */ +static MIDI_CHANNEL midi_channel[16]; /* MIDI channel info */ +static WAITING_NOTE midi_waiting[MIDI_VOICES]; /* notes still to be played */ +static PATCH_TABLE patch_table[128]; /* GM -> external synth */ + +static int midi_seeking; /* set during seeks */ +static int midi_looping; /* set during loops */ + +/* hook functions */ +void (*midi_msg_callback)(int msg, int byte1, int byte2) = NULL; +void (*midi_meta_callback)(int type, unsigned char *data, int length) = NULL; +void (*midi_sysex_callback)(unsigned char *data, int length) = NULL; + + + +/* lock_midi: + * Locks a MIDI file into physical memory. Pretty important, since they + * are mostly accessed inside interrupt handlers. + */ +void lock_midi(MIDI *midi) +{ + int c; + + _go32_dpmi_lock_data(midi, sizeof(MIDI)); + + for (c=0; ctrack[c].data) + _go32_dpmi_lock_data(midi->track[c].data, midi->track[c].len); +} + + + +/* load_midi: + * Loads a standard MIDI file, returning a pointer to a MIDI structure, + * or NULL on error. + */ +MIDI *load_midi(char *filename) +{ + int trashtmp; + int c; + char buf[256]; + long data; + PACKFILE *fp; + MIDI *midi; + int num_tracks; + + fp = pack_fopen(filename, F_READ); /* open the file */ + if (!fp) + return NULL; + + midi = malloc(sizeof(MIDI)); /* get some memory */ + if (!midi) { + pack_fclose(fp); + return NULL; + } + + for (c=0; ctrack[c].data = NULL; + midi->track[c].len = 0; + } + + pack_fread(buf, 4, fp); /* read midi header */ + if (memcmp(buf, "MThd", 4)) + goto err; + + trashtmp=pack_mgetl(fp); /* skip header chunk length */ + + data = pack_mgetw(fp); /* MIDI file type */ + if ((data != 0) && (data != 1)) + goto err; + + num_tracks = pack_mgetw(fp); /* number of tracks */ + if ((num_tracks < 1) || (num_tracks > MIDI_TRACKS)) + goto err; + + data = pack_mgetw(fp); /* beat divisions */ + midi->divisions = ABS(data); + + for (c=0; ctrack[c].len = data; + + midi->track[c].data = malloc(data); /* allocate memory */ + if (!midi->track[c].data) + goto err; + /* finally, read track data */ + if (pack_fread(midi->track[c].data, data, fp) != data) + goto err; + } + + pack_fclose(fp); + lock_midi(midi); + return midi; + + /* oh dear... */ + err: + pack_fclose(fp); + destroy_midi(midi); + return NULL; +} + + + +/* destroy_midi: + * Frees the memory being used by a MIDI file. + */ +void destroy_midi(MIDI *midi) +{ + int c; + + if (midi == midifile) + stop_midi(); + + if (midi) { + for (c=0; ctrack[c].data) { + _unlock_dpmi_data(midi->track[c].data, midi->track[c].len); + free(midi->track[c].data); + } + } + _unlock_dpmi_data(midi, sizeof(MIDI)); + free(midi); + } +} + + + +/* parse_var_len: + * The MIDI file format is a strange thing. Time offsets are only 32 bits, + * yet they are compressed in a weird variable length format. This routine + * reads a variable length integer from a MIDI data stream. It returns the + * number read, and alters the data pointer according to the number of + * bytes it used. + */ +static unsigned long parse_var_len(unsigned char **data) +{ + unsigned long val = **data & 0x7F; + + while (**data & 0x80) { + (*data)++; + val <<= 7; + val += (**data & 0x7F); + } + + (*data)++; + return val; +} + +static END_OF_FUNCTION(parse_var_len); + + + +/* global_volume_fix: + * Converts a note volume, adjusting it according to the global + * _midi_volume variable. + */ +static inline int global_volume_fix(int vol) +{ + if (_midi_volume >= 0) + return (vol * _midi_volume) / 256; + + return vol; +} + + + +/* sort_out_volume: + * Converts a note volume, adjusting it according to the channel volume + * and the global _midi_volume variable. + */ +static inline int sort_out_volume(int c, int vol) +{ + return global_volume_fix((vol * midi_channel[c].volume) / 128); +} + + + +/* raw_program_change: + * Sends a program change message to a device capable of handling raw + * MIDI data, using patch mapping tables. Assumes that midi_driver->raw_midi + * isn't NULL, so check before calling it! + */ +static void raw_program_change(int channel, int patch) +{ + if (channel != 9) { + /* bank change #1 */ + if (patch_table[patch].bank1 >= 0) { + midi_driver->raw_midi(0xB0+channel); + midi_driver->raw_midi(0); + midi_driver->raw_midi(patch_table[patch].bank1); + } + + /* bank change #2 */ + if (patch_table[patch].bank2 >= 0) { + midi_driver->raw_midi(0xB0+channel); + midi_driver->raw_midi(32); + midi_driver->raw_midi(patch_table[patch].bank2); + } + + /* program change */ + midi_driver->raw_midi(0xC0+channel); + midi_driver->raw_midi(patch_table[patch].prog); + + /* update volume */ + midi_driver->raw_midi(0xB0+channel); + midi_driver->raw_midi(7); + midi_driver->raw_midi(global_volume_fix(midi_channel[channel].volume-1)); + } +} + +static END_OF_FUNCTION(raw_program_change); + + + +/* midi_note_off: + * Processes a MIDI note-off event. + */ +static void midi_note_off(int channel, int note) +{ + int done = FALSE; + int voice, layer; + int c; + + /* can we send raw MIDI data? */ + if (midi_driver->raw_midi) { + if (channel != 9) + note += patch_table[midi_channel[channel].patch].pitch; + + midi_driver->raw_midi(0x80+channel); + midi_driver->raw_midi(note); + midi_driver->raw_midi(0); + return; + } + + /* oh well, have to do it the long way... */ + for (layer=0; layer= 0) { + midi_driver->key_off(voice + midi_driver->basevoice); + midi_voice[voice].note = -1; + midi_voice[voice].time = _midi_tick; + midi_channel[channel].note[note][layer] = -1; + done = TRUE; + } + } + + /* if the note isn't playing, it must still be in the waiting room */ + if (!done) { + for (c=0; c= 0x1000) { + (*note)++; + (*bend) -= 0x1000; + } +} + + + +/* _midi_allocate_voice: + * Allocates a MIDI voice in the range min-max (inclusive). This is + * intended to be called by the key_on() handlers in the MIDI driver, + * and shouldn't be used by any other code. + */ +int _midi_allocate_voice(int min, int max) +{ + int c; + int layer; + int voice = -1; + int best_time = LONG_MAX; + + if (min < 0) + min = 0; + + if (max < 0) + max = midi_driver->voices-1; + + /* which layer can we use? */ + for (layer=0; layer= MIDI_LAYERS) + return -1; + + /* find a free voice */ + for (c=min; c<=max; c++) { + if ((midi_voice[c].note < 0) && + (midi_voice[c].time < best_time) && + ((c < midi_driver->xmin) || (c > midi_driver->xmax))) { + voice = c; + best_time = midi_voice[c].time; + } + } + + /* if there are no free voices, kill a note to make room */ + if (voice < 0) { + voice = -1; + best_time = LONG_MAX; + for (c=min; c<=max; c++) { + if ((midi_voice[c].time < best_time) && + ((c < midi_driver->xmin) || (c > midi_driver->xmax))) { + voice = c; + best_time = midi_voice[c].time; + } + } + if (voice >= 0) + midi_note_off(midi_voice[voice].channel, midi_voice[voice].note); + else + return -1; + } + + /* ok, we got it... */ + midi_voice[voice].channel = midi_alloc_channel; + midi_voice[voice].note = midi_alloc_note; + midi_voice[voice].volume = midi_alloc_vol; + midi_voice[voice].time = _midi_tick; + midi_channel[midi_alloc_channel].note[midi_alloc_note][layer] = voice; + + return voice + midi_driver->basevoice; +} + +END_OF_FUNCTION(_midi_allocate_voice); + + + +/* midi_note_on: + * Processes a MIDI note-on event. Tries to find a free soundcard voice, + * and if it can't either cuts off an existing note, or if 'polite' is + * set, just stores the channel, note and volume in the waiting list. + */ +static void midi_note_on(int channel, int note, int vol, int polite) +{ + int c, layer, inst, bend, corrected_note; + + /* it's easy if the driver can handle raw MIDI data */ + if (midi_driver->raw_midi) { + if (channel != 9) + note += patch_table[midi_channel[channel].patch].pitch; + + midi_driver->raw_midi(0x90+channel); + midi_driver->raw_midi(note); + midi_driver->raw_midi(vol); + return; + } + + /* if the note is already on, turn it off */ + for (layer=0; layer= 0) { + midi_note_off(channel, note); + return; + } + } + + /* if zero volume and the note isn't playing, we can just ignore it */ + if (vol == 0) + return; + + if (channel != 9) { + /* are there any free voices? */ + for (c=0; cvoices; c++) + if ((midi_voice[c].note < 0) && + ((c < midi_driver->xmin) || (c > midi_driver->xmax))) + break; + + /* if there are no free voices, remember the note for later */ + if ((c >= midi_driver->voices) && (polite)) { + for (c=0; ckey_on(inst, corrected_note, bend, + sort_out_volume(channel, vol), + midi_channel[channel].pan); +} + +static END_OF_FUNCTION(midi_note_on); + + + +/* all_notes_off: + * Turns off all active notes. + */ +static void all_notes_off(int channel) +{ + if (midi_driver->raw_midi) { + midi_driver->raw_midi(0xB0+channel); + midi_driver->raw_midi(123); + midi_driver->raw_midi(0); + return; + } + else { + int note, layer; + + for (note=0; note<128; note++) + for (layer=0; layer= 0) + midi_note_off(channel, note); + } +} + +static END_OF_FUNCTION(all_notes_off); + + + +/* reset_controllers: + * Resets volume, pan, pitch bend, etc, to default positions. + */ +static void reset_controllers(int channel) +{ + midi_channel[channel].new_volume = 128; + midi_channel[channel].new_pitch_bend = 0x2000; + + switch (channel % 3) { + case 0: midi_channel[channel].pan = ((channel/3) & 1) ? 60 : 68; break; + case 1: midi_channel[channel].pan = 104; break; + case 2: midi_channel[channel].pan = 24; break; + } + + if (midi_driver->raw_midi) { + midi_driver->raw_midi(0xB0+channel); + midi_driver->raw_midi(10); + midi_driver->raw_midi(midi_channel[channel].pan); + } +} + +static END_OF_FUNCTION(reset_controllers); + + + +/* update_controllers: + * Checks cached controller information and updates active voices. + */ +static void update_controllers() +{ + int c, c2; + + for (c=0; c<16; c++) { + /* check for volume controller change */ + if ((midi_channel[c].volume != midi_channel[c].new_volume) || + (old_midi_volume != _midi_volume)) { + midi_channel[c].volume = midi_channel[c].new_volume; + if (midi_driver->raw_midi) { + midi_driver->raw_midi(0xB0+c); + midi_driver->raw_midi(7); + midi_driver->raw_midi(global_volume_fix(midi_channel[c].volume-1)); + } + else { + for (c2=0; c2= 0)) { + int vol = sort_out_volume(c, midi_voice[c2].volume); + midi_driver->set_volume(c2 + midi_driver->basevoice, vol); + } + } + } + } + + /* check for pitch bend change */ + if (midi_channel[c].pitch_bend != midi_channel[c].new_pitch_bend) { + midi_channel[c].pitch_bend = midi_channel[c].new_pitch_bend; + if (midi_driver->raw_midi) { + midi_driver->raw_midi(0xE0+c); + midi_driver->raw_midi(midi_channel[c].pitch_bend & 0x7F); + midi_driver->raw_midi(midi_channel[c].pitch_bend >> 7); + } + else { + for (c2=0; c2= 0)) { + int bend = midi_channel[c].pitch_bend; + int note = midi_voice[c2].note; + sort_out_pitch_bend(&bend, ¬e); + midi_driver->set_pitch(c2 + midi_driver->basevoice, note, bend); + } + } + } + } + } + + old_midi_volume = _midi_volume; +} + +static END_OF_FUNCTION(update_controllers); + + + +/* process_controller: + * Deals with a MIDI controller message on the specified channel. + */ +static void process_controller(int channel, int ctrl, int data) +{ + switch (ctrl) { + + case 7: /* main volume */ + midi_channel[channel].new_volume = data+1; + break; + + case 10: /* pan */ + midi_channel[channel].pan = data; + if (midi_driver->raw_midi) { + midi_driver->raw_midi(0xB0+channel); + midi_driver->raw_midi(10); + midi_driver->raw_midi(data); + } + break; + + case 121: /* reset all controllers */ + reset_controllers(channel); + break; + + case 123: /* all notes off */ + case 124: /* omni mode off */ + case 125: /* omni mode on */ + case 126: /* poly mode off */ + case 127: /* poly mode on */ + all_notes_off(channel); + break; + } +} + +static END_OF_FUNCTION(process_controller); + + + +/* process_meta_event: + * Processes the next meta-event on the specified track. + */ +static void process_meta_event(unsigned char **pos, long *timer) +{ + unsigned char metatype = *((*pos)++); + long length = parse_var_len(pos); + long tempo; + + if (midi_meta_callback) + midi_meta_callback(metatype, *pos, length); + + if (metatype == 0x2F) { /* end of track */ + *pos = NULL; + *timer = LONG_MAX; + return; + } + + if (metatype == 0x51) { /* tempo change */ + tempo = (*pos)[0] * 0x10000L + (*pos)[1] * 0x100 + (*pos)[2]; + midi_new_speed = (tempo/1000) * (TIMERS_PER_SECOND/1000); + midi_new_speed /= midifile->divisions; + } + + (*pos) += length; +} + +static END_OF_FUNCTION(process_meta_event); + + + +/* process_midi_event: + * Processes the next MIDI event on the specified track. + */ +static void process_midi_event(unsigned char **pos, unsigned char *running_status, long *timer) +{ + unsigned char byte1, byte2; + int channel; + unsigned char event; + long l; + + event = *((*pos)++); + + if (event & 0x80) { /* regular message */ + /* no running status for sysex and meta-events! */ + if ((event != 0xF0) && (event != 0xF7) && (event != 0xFF)) + *running_status = event; + byte1 = (*pos)[0]; + byte2 = (*pos)[1]; + } + else { /* use running status */ + byte1 = event; + byte2 = (*pos)[0]; + event = *running_status; + (*pos)--; + } + + /* program callback? */ + if ((midi_msg_callback) && + (event != 0xF0) && (event != 0xF7) && (event != 0xFF)) + midi_msg_callback(event, byte1, byte2); + + channel = event & 0x0F; + + switch (event>>4) { + + case 0x08: /* note off */ + midi_note_off(channel, byte1); + (*pos) += 2; + break; + + case 0x09: /* note on */ + midi_note_on(channel, byte1, byte2, 1); + (*pos) += 2; + break; + + case 0x0A: /* note aftertouch */ + (*pos) += 2; + break; + + case 0x0B: /* control change */ + process_controller(channel, byte1, byte2); + (*pos) += 2; + break; + + case 0x0C: /* program change */ + midi_channel[channel].patch = byte1; + if (midi_driver->raw_midi) + raw_program_change(channel, byte1); + (*pos) += 1; + break; + + case 0x0D: /* channel aftertouch */ + (*pos) += 1; + break; + + case 0x0E: /* pitch bend */ + midi_channel[channel].new_pitch_bend = byte1 + (byte2<<7); + (*pos) += 2; + break; + + case 0x0F: /* special event */ + switch (event) { + case 0xF0: /* sysex */ + case 0xF7: + l = parse_var_len(pos); + if (midi_sysex_callback) + midi_sysex_callback(*pos, l); + (*pos) += l; + break; + + case 0xF2: /* song position */ + (*pos) += 2; + break; + + case 0xF3: /* song select */ + (*pos)++; + break; + + case 0xFF: /* meta-event */ + process_meta_event(pos, timer); + break; + + default: + /* the other special events don't have any data bytes, + so we don't need to bother skipping past them */ + break; + } + break; + + default: + /* something has gone badly wrong if we ever get to here */ + break; + } +} + +static END_OF_FUNCTION(process_midi_event); + + + +/* midi_player: + * The core MIDI player: to be used as a timer callback. + */ +static void midi_player() +{ + int c; + long l; + int active; + + if (!midifile) + return; + + if (midi_semaphore) { + midi_timer_speed += BPS_TO_TIMER(40); + install_int_ex(midi_player, BPS_TO_TIMER(40)); + return; + } + + midi_semaphore = TRUE; + _midi_tick++; + + do_it_all_again: + + for (c=0; c 0) { + for (c=0; cdivisions; + midi_new_speed = -1; + } + + /* figure out how long until we need to be called again */ + active = 0; + midi_timer_speed = LONG_MAX; + for (c=0; c 0) && (midi_pos >= midi_loop_end))) { + if ((midi_loop) && (!midi_looping)) { + if (midi_loop_start > 0) { + remove_int(midi_player); + midi_semaphore = FALSE; + midi_looping = TRUE; + if (midi_seek(midi_loop_start) != 0) { + midi_looping = FALSE; + stop_midi(); + return; + } + midi_looping = FALSE; + midi_semaphore = TRUE; + goto do_it_all_again; + } + else { + for (c=0; c<16; c++) + all_notes_off(c); + prepare_to_play(midifile); + goto do_it_all_again; + } + } + else { + stop_midi(); + midi_semaphore = FALSE; + return; + } + } + + /* reprogram the timer */ + if (midi_timer_speed < BPS_TO_TIMER(40)) + midi_timer_speed = BPS_TO_TIMER(40); + + if (!midi_seeking) + install_int_ex(midi_player, midi_timer_speed); + + /* controller changes are cached and only processed here, so we can + condense streams of controller data into just a few voice updates */ + update_controllers(); + + /* and deal with any notes that are still waiting to be played */ + for (c=0; c= 0) + midi_note_on(midi_waiting[c].channel, midi_waiting[c].note, + midi_waiting[c].volume, 0); + + midi_semaphore = FALSE; +} + +static END_OF_FUNCTION(midi_player); + + + +/* midi_init: + * Sets up the MIDI player ready for use. Returns non-zero on failure. + */ +static int midi_init() +{ + int c, c2, c3; + int argc; + char **argv; + char buf[16]; + + midi_loaded_patches = FALSE; + + midi_lock_mem(); + + for (c=0; c<16; c++) { + midi_channel[c].volume = 128; + midi_channel[c].pitch_bend = 0x2000; + + for (c2=0; c2<128; c2++) + for (c3=0; c3track[c].data; + end = p + midi->track[c].len; + running_status = 0; + + while (p < end) { /* work through data stream */ + event = *p; + if (event & 0x80) { /* regular message */ + p++; + if ((event != 0xF0) && (event != 0xF7) && (event != 0xFF)) + running_status = event; + } + else /* use running status */ + event = running_status; + + switch (event>>4) { + + case 0x0C: /* program change! */ + patches[*p] = TRUE; + p++; + break; + + case 0x09: /* note on, is it a drum? */ + if ((event & 0x0F) == 9) + drums[*p] = TRUE; + p += 2; + break; + + case 0x08: /* note off */ + case 0x0A: /* note aftertouch */ + case 0x0B: /* control change */ + case 0x0E: /* pitch bend */ + p += 2; + break; + + case 0x0D: /* channel aftertouch */ + p += 1; + break; + + case 0x0F: /* special event */ + switch (event) { + case 0xF0: /* sysex */ + case 0xF7: + l = parse_var_len(&p); + p += l; + break; + + case 0xF2: /* song position */ + p += 2; + break; + + case 0xF3: /* song select */ + p++; + break; + + case 0xFF: /* meta-event */ + p++; + l = parse_var_len(&p); + p += l; + break; + + default: + /* the other special events don't have any data bytes, + so we don't need to bother skipping past them */ + break; + } + break; + + default: + /* something has gone badly wrong if we ever get to here */ + break; + } + + if (p < end) /* skip time offset */ + parse_var_len(&p); + } + } + + /* tell the driver to do its stuff */ + return midi_driver->load_patches(patches, drums); +} + + + +/* prepare_to_play: + * Sets up all the global variables needed to play the specified file. + */ +static void prepare_to_play(MIDI *midi) +{ + int c; + + for (c=0; c<16; c++) + reset_controllers(c); + + update_controllers(); + + midifile = midi; + midi_pos = 0; + midi_pos_counter = 0; + midi_speed = TIMERS_PER_SECOND / 2 / midifile->divisions; /* 120 bpm */ + midi_new_speed = -1; + midi_pos_speed = midi_speed * midifile->divisions; + midi_timer_speed = 0; + midi_seeking = 0; + midi_looping = 0; + + for (c=0; c<16; c++) { + midi_channel[c].patch = 0; + if (midi_driver->raw_midi) + raw_program_change(c, 0); + } + + for (c=0; ctrack[c].data) { + midi_track[c].pos = midi->track[c].data; + midi_track[c].timer = parse_var_len(&midi_track[c].pos); + midi_track[c].timer *= midi_speed; + } + else { + midi_track[c].pos = NULL; + midi_track[c].timer = LONG_MAX; + } + midi_track[c].running_status = 0; + } +} + +static END_OF_FUNCTION(prepare_to_play); + + + +/* play_midi: + * Starts playing the specified MIDI file. If loop is set, the MIDI file + * will be repeated until replaced with something else, otherwise it will + * stop at the end of the file. Passing a NULL MIDI file will stop whatever + * music is currently playing: allegro.h defines the macro stop_midi() to + * be play_midi(NULL, FALSE); Returns non-zero if an error occurs (this + * may happen if a patch-caching wavetable driver is unable to load the + * required samples). + */ +int play_midi(MIDI *midi, int loop) +{ + int c; + + remove_int(midi_player); + + for (c=0; c<16; c++) + all_notes_off(c); + + if (midi) { + if (!midi_loaded_patches) + if (load_patches(midi) != 0) + return -1; + + midi_loop = loop; + midi_loop_start = -1; + midi_loop_end = -1; + + prepare_to_play(midi); + + /* arbitrary speed, midi_player() will adjust it */ + install_int(midi_player, 20); + } + else { + midifile = NULL; + midi_pos = -1; + } + + return 0; +} + +END_OF_FUNCTION(play_midi); + + + +/* play_looped_midi: + * Like play_midi(), but the file loops from the specified end position + * back to the specified start position (the end position can be -1 to + * indicate the end of the file). + */ +int play_looped_midi(MIDI *midi, int loop_start, int loop_end) +{ + if (play_midi(midi, TRUE) != 0) + return -1; + + midi_loop_start = loop_start; + midi_loop_end = loop_end; + + return 0; +} + + + +/* stop_midi: + * Stops whatever MIDI file is currently playing. + */ +void stop_midi() +{ + play_midi(NULL, FALSE); +} + +END_OF_FUNCTION(stop_midi); + + + +/* midi_pause: + * Pauses the currently playing MIDI file. + */ +void midi_pause() +{ + int c; + + if (!midifile) + return; + + remove_int(midi_player); + + for (c=0; c<16; c++) + all_notes_off(c); +} + +END_OF_FUNCTION(midi_pause); + + + +/* midi_resume: + * Resumes playing a paused MIDI file. + */ +void midi_resume() +{ + if (!midifile) + return; + + install_int_ex(midi_player, midi_timer_speed); +} + +END_OF_FUNCTION(midi_resume); + + + +/* midi_seek: + * Seeks to the given midi_pos in the current MIDI file. If the target + * is earlier in the file than the current midi_pos it seeks from the + * beginning; otherwise it seeks from the current position. Returns zero + * if successful, non-zero if it hit the end of the file (1 means it + * stopped playing, 2 means it looped back to the start). + */ +int midi_seek(int target) +{ + int old_midi_loop; + MIDI *old_midifile; + MIDI_DRIVER *old_driver; + int old_patch[16]; + int old_volume[16]; + int old_pan[16]; + int old_pitch_bend[16]; + int c; + + if (!midifile) + return -1; + + /* first stop the player */ + midi_pause(); + + /* store current settings */ + for (c=0; c<16; c++) { + old_patch[c] = midi_channel[c].patch; + old_volume[c] = midi_channel[c].volume; + old_pan[c] = midi_channel[c].pan; + old_pitch_bend[c] = midi_channel[c].pitch_bend; + } + + /* save some variables and give temporary values */ + old_driver = midi_driver; + midi_driver = &midi_none; + old_midi_loop = midi_loop; + midi_loop = 0; + old_midifile = midifile; + + /* set flag to tell midi_player not to reinstall itself */ + midi_seeking = 1; + + /* are we seeking backwards? If so, skip back to the start of the file */ + if (target <= midi_pos) + prepare_to_play(midifile); + + /* now sit back and let midi_player get to the position */ + while ((midi_pos < target) && (midi_pos != -1)) { + int mmpc = midi_pos_counter; + int mmp = midi_pos; + + mmpc -= midi_timer_speed; + while (mmpc <= 0) { + mmpc += midi_pos_speed; + mmp++; + } + + if (mmp >= target) + break; + + midi_player(); + } + + /* restore previously saved variables */ + midi_loop = old_midi_loop; + midi_driver = old_driver; + midi_seeking = 0; + + if (midi_pos != -1) { + /* refresh the driver with any changed parameters */ + if (midi_driver->raw_midi) { + for (c=0; c<16; c++) { + /* program change (this sets the volume as well) */ + if ((midi_channel[c].patch != old_patch[c]) || + (midi_channel[c].volume != old_volume[c])) + raw_program_change(c, midi_channel[c].patch); + + /* pan */ + if (midi_channel[c].pan != old_pan[c]) { + midi_driver->raw_midi(0xB0+c); + midi_driver->raw_midi(10); + midi_driver->raw_midi(midi_channel[c].pan); + } + + /* pitch bend */ + if (midi_channel[c].pitch_bend != old_pitch_bend[c]) { + midi_driver->raw_midi(0xE0+c); + midi_driver->raw_midi(midi_channel[c].pitch_bend & 0x7F); + midi_driver->raw_midi(midi_channel[c].pitch_bend >> 7); + } + } + } + + /* if we didn't hit the end of the file, continue playing */ + if (!midi_looping) + install_int(midi_player, 20); + + return 0; + } + + if ((midi_loop) && (!midi_looping)) { /* was file was looped? */ + prepare_to_play(old_midifile); + install_int(midi_player, 20); + return 2; /* seek past EOF => file restarted */ + } + + return 1; /* seek past EOF => file stopped */ +} + +END_OF_FUNCTION(midi_seek); + + + +/* midi_out: + * Inserts MIDI command bytes into the output stream, in realtime. + */ +void midi_out(unsigned char *data, int length) +{ + unsigned char *pos = data; + unsigned char running_status = 0; + long timer = 0; + + midi_semaphore = TRUE; + _midi_tick++; + + while (pos < data+length) + process_midi_event(&pos, &running_status, &timer); + + midi_semaphore = FALSE; +} + + + +/* load_midi_patches: + * Tells the MIDI driver to preload the entire sample set. + */ +int load_midi_patches() +{ + char patches[128], drums[128]; + int c, ret; + + for (c=0; c<128; c++) + patches[c] = drums[c] = TRUE; + + midi_semaphore = TRUE; + ret = midi_driver->load_patches(patches, drums); + midi_semaphore = FALSE; + + midi_loaded_patches = TRUE; + + return ret; +} + + + +/* midi_lock_mem: + * Locks all the memory that the midi player touches inside the timer + * interrupt handler (which is most of it). + */ +static void midi_lock_mem() +{ + LOCK_VARIABLE(midi_pos); + LOCK_VARIABLE(midi_pos_counter); + LOCK_VARIABLE(_midi_tick); + LOCK_VARIABLE(midifile); + LOCK_VARIABLE(midi_semaphore); + LOCK_VARIABLE(midi_loop); + LOCK_VARIABLE(midi_loop_start); + LOCK_VARIABLE(midi_loop_end); + LOCK_VARIABLE(midi_timer_speed); + LOCK_VARIABLE(midi_pos_speed); + LOCK_VARIABLE(midi_speed); + LOCK_VARIABLE(midi_new_speed); + LOCK_VARIABLE(old_midi_volume); + LOCK_VARIABLE(midi_alloc_channel); + LOCK_VARIABLE(midi_alloc_note); + LOCK_VARIABLE(midi_alloc_vol); + LOCK_VARIABLE(midi_track); + LOCK_VARIABLE(midi_voice); + LOCK_VARIABLE(midi_channel); + LOCK_VARIABLE(midi_waiting); + LOCK_VARIABLE(patch_table); + LOCK_VARIABLE(midi_msg_callback); + LOCK_VARIABLE(midi_meta_callback); + LOCK_VARIABLE(midi_sysex_callback); + LOCK_VARIABLE(midi_seeking); + LOCK_VARIABLE(midi_looping); + LOCK_FUNCTION(parse_var_len); + LOCK_FUNCTION(raw_program_change); + LOCK_FUNCTION(midi_note_off); + LOCK_FUNCTION(_midi_allocate_voice); + LOCK_FUNCTION(midi_note_on); + LOCK_FUNCTION(all_notes_off); + LOCK_FUNCTION(reset_controllers); + LOCK_FUNCTION(update_controllers); + LOCK_FUNCTION(process_controller); + LOCK_FUNCTION(process_meta_event); + LOCK_FUNCTION(process_midi_event); + LOCK_FUNCTION(midi_player); + LOCK_FUNCTION(prepare_to_play); + LOCK_FUNCTION(play_midi); + LOCK_FUNCTION(stop_midi); + LOCK_FUNCTION(midi_pause); + LOCK_FUNCTION(midi_resume); + LOCK_FUNCTION(midi_seek); +} + + + +/* midi_constructor: + * Register my functions with the code in sound.c. + */ +static void midi_constructor() __attribute__ ((constructor)); +static void midi_constructor() +{ + _midi_init = midi_init; + _midi_exit = midi_exit; +} + diff --git a/arch/dos/allg_snd/sound/mixer.c b/arch/dos/allg_snd/sound/mixer.c new file mode 100644 index 00000000..6f8f8a0a --- /dev/null +++ b/arch/dos/allg_snd/sound/mixer.c @@ -0,0 +1,975 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * By Shawn Hargreaves, + * 1 Salisbury Road, + * Market Drayton, + * Shropshire, + * England, TF9 1AJ. + * + * Sample mixing code. + * + * See readme.txt for copyright information. + */ + + +#include +#include +#include +#include +#include +#include + +#ifdef DJGPP +#include +#include +#endif + +#include "allegro.h" +#include "internal.h" + + +typedef struct MIXER_VOICE +{ + int playing; /* are we active? */ + unsigned char *data8; /* data for 8 bit samples */ + unsigned short *data16; /* data for 16 bit samples */ + long pos; /* fixed point position in sample */ + long diff; /* fixed point speed of play */ + long len; /* fixed point sample length */ + long loop_start; /* fixed point loop start position */ + long loop_end; /* fixed point loop end position */ + int lvol; /* left channel volume */ + int rvol; /* right channel volume */ +} MIXER_VOICE; + + +#define MIXER_VOLUME_LEVELS 32 +#define MIXER_FIX_SHIFT 8 + +#define UPDATE_FREQ 16 + + +/* the samples currently being played */ +static MIXER_VOICE mixer_voice[MIXER_MAX_SFX]; + +/* temporary sample mixing buffer */ +static unsigned short *mix_buffer = NULL; + +/* lookup table for converting sample volumes */ +typedef signed short MIXER_VOL_TABLE[256]; +static MIXER_VOL_TABLE *mix_vol_table = NULL; + +/* lookup table for amplifying and clipping samples */ +static unsigned short *mix_clip_table = NULL; + +#define MIX_RES_16 14 +#define MIX_RES_8 10 + +/* flags for the mixing code */ +static int mix_voices; +static int mix_size; +static int mix_freq; +static int mix_stereo; +static int mix_16bit; + + +static void mixer_lock_mem(); + + + +/* _mixer_init: + * Initialises the sample mixing code, returning 0 on success. You should + * pass it the number of samples you want it to mix each time the refill + * buffer routine is called, the sample rate to mix at, and two flags + * indicating whether the mixing should be done in stereo or mono and with + * eight or sixteen bits. The bufsize parameter is the number of samples, + * not bytes. It should take into account whether you are working in stereo + * or not (eg. double it if in stereo), but it should not be affected by + * whether each sample is 8 or 16 bits. + */ +int _mixer_init(int bufsize, int freq, int stereo, int is16bit, int *voices) +{ + int i, j; + int clip_size; + int clip_scale; + int clip_max; + + mix_voices = 1; + while ((mix_voices < MIXER_MAX_SFX) && (mix_voices < *voices)) + mix_voices <<= 1; + + *voices = mix_voices; + + mix_size = bufsize; + mix_freq = freq; + mix_stereo = stereo; + mix_16bit = is16bit; + + for (i=0; i= 8) { + /* clip extremes of the sample range */ + for (i=0; ivol >> 12; + int pan = pv->pan >> 12; + int lvol, rvol; + + if (mix_stereo) { + lvol = vol * (256-pan) * MIXER_VOLUME_LEVELS / 32768; + rvol = vol * pan * MIXER_VOLUME_LEVELS / 32768; + } + else + lvol = rvol = vol * MIXER_VOLUME_LEVELS / 256; + + mv->lvol = MID(0, lvol, MIXER_VOLUME_LEVELS-1); + mv->rvol = MID(0, rvol, MIXER_VOLUME_LEVELS-1); +} + + + +/* update_mixer_freq: + * Called whenever the voice frequency changes, to update the sample + * delta value. + */ +static inline void update_mixer_freq(MIXER_VOICE *mv, PHYS_VOICE *pv) +{ + mv->diff = (pv->freq >> (12 - MIXER_FIX_SHIFT)) / mix_freq; + + if (pv->playmode & PLAYMODE_BACKWARD) + mv->diff = -mv->diff; +} + + + +/* helper for constructing the body of a sample mixing routine */ +#define MIXER() \ +{ \ + if ((voice->playmode & PLAYMODE_LOOP) && \ + (spl->loop_start < spl->loop_end)) { \ + restart: \ + if (voice->playmode & PLAYMODE_BACKWARD) { \ + /* mix a backward looping sample */ \ + while (len-- > 0) { \ + MIX(); \ + spl->pos += spl->diff; \ + if (spl->pos < spl->loop_start) { \ + if (voice->playmode & PLAYMODE_BIDIR) { \ + spl->diff = -spl->diff; \ + spl->pos += spl->diff * 2; \ + voice->playmode ^= PLAYMODE_BACKWARD; \ + goto restart; \ + } \ + else \ + spl->pos += (spl->loop_end - spl->loop_start); \ + } \ + UPDATE(); \ + } \ + } \ + else { \ + /* mix a forward looping sample */ \ + while (len-- > 0) { \ + MIX(); \ + spl->pos += spl->diff; \ + if (spl->pos >= spl->loop_end) { \ + if (voice->playmode & PLAYMODE_BIDIR) { \ + spl->diff = -spl->diff; \ + spl->pos += spl->diff * 2; \ + voice->playmode ^= PLAYMODE_BACKWARD; \ + goto restart; \ + } \ + else \ + spl->pos -= (spl->loop_end - spl->loop_start); \ + } \ + UPDATE(); \ + } \ + } \ + } \ + else { \ + /* mix a non-looping sample */ \ + while (len-- > 0) { \ + MIX(); \ + spl->pos += spl->diff; \ + if ((unsigned long)spl->pos >= (unsigned long)spl->len) { \ + /* note: we don't need a different version for reverse play, */ \ + /* as this will wrap and automatically do the Right Thing */ \ + spl->playing = FALSE; \ + return; \ + } \ + UPDATE(); \ + } \ + } \ +} + + + +#define UPDATE() + + + +/* mix_mono_8_samples: + * Mixes from an eight bit sample into a mono buffer, until either len + * samples have been mixed or until the end of the sample is reached. + */ +static void mix_mono_8_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) +{ + signed short *vol = (short *)(mix_vol_table + spl->lvol); + + #define MIX() \ + *(buf++) += vol[spl->data8[spl->pos>>MIXER_FIX_SHIFT]]; + + MIXER(); + + #undef MIX +} + +static END_OF_FUNCTION(mix_mono_8_samples); + + + +/* mix_stereo_8_samples: + * Mixes from an eight bit sample into a stereo buffer, until either len + * samples have been mixed or until the end of the sample is reached. + */ +static void mix_stereo_8_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) +{ + signed short *lvol = (short *)(mix_vol_table + spl->lvol); + signed short *rvol = (short *)(mix_vol_table + spl->rvol); + + len >>= 1; + + #define MIX() \ + *(buf++) += lvol[spl->data8[spl->pos>>MIXER_FIX_SHIFT]]; \ + *(buf++) += rvol[spl->data8[spl->pos>>MIXER_FIX_SHIFT]]; + + MIXER(); + + #undef MIX +} + +static END_OF_FUNCTION(mix_stereo_8_samples); + + + +/* mix_mono_16_samples: + * Mixes from a 16 bit sample into a mono buffer, until either len samples + * have been mixed or until the end of the sample is reached. + */ +static void mix_mono_16_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) +{ + signed short *vol = (short *)(mix_vol_table + spl->lvol); + + #define MIX() \ + *(buf++) += vol[(spl->data16[spl->pos>>MIXER_FIX_SHIFT])>>8]; + + MIXER(); + + #undef MIX +} + +static END_OF_FUNCTION(mix_mono_16_samples); + + + +/* mix_stereo_16_samples: + * Mixes from a 16 bit sample into a stereo buffer, until either len samples + * have been mixed or until the end of the sample is reached. + */ +static void mix_stereo_16_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) +{ + signed short *lvol = (short *)(mix_vol_table + spl->lvol); + signed short *rvol = (short *)(mix_vol_table + spl->rvol); + + len >>= 1; + + #define MIX() \ + *(buf++) += lvol[(spl->data16[spl->pos>>MIXER_FIX_SHIFT])>>8]; \ + *(buf++) += rvol[(spl->data16[spl->pos>>MIXER_FIX_SHIFT])>>8]; + + MIXER(); + + #undef MIX +} + +static END_OF_FUNCTION(mix_stereo_16_samples); + + + +#undef UPDATE + + +/* helper for updating the volume ramp and pitch/pan sweep status */ +#define UPDATE() \ +{ \ + if ((len & (UPDATE_FREQ-1)) == 0) { \ + /* update volume ramp */ \ + if (voice->dvol) { \ + voice->vol += voice->dvol; \ + if (((voice->dvol > 0) && (voice->vol >= voice->target_vol)) || \ + ((voice->dvol < 0) && (voice->vol <= voice->target_vol))) { \ + voice->vol = voice->target_vol; \ + voice->dvol = 0; \ + } \ + } \ + \ + /* update frequency sweep */ \ + if (voice->dfreq) { \ + voice->freq += voice->dfreq; \ + if (((voice->dfreq > 0) && (voice->freq >= voice->target_freq)) || \ + ((voice->dfreq < 0) && (voice->freq <= voice->target_freq))) { \ + voice->freq = voice->target_freq; \ + voice->dfreq = 0; \ + } \ + } \ + \ + /* update pan sweep */ \ + if (voice->dpan) { \ + voice->pan += voice->dpan; \ + if (((voice->dpan > 0) && (voice->pan >= voice->target_pan)) || \ + ((voice->dpan < 0) && (voice->pan <= voice->target_pan))) { \ + voice->pan = voice->target_pan; \ + voice->dpan = 0; \ + } \ + } \ + \ + update_mixer_volume(spl, voice); \ + update_mixer_freq(spl, voice); \ + } \ +} + + + +/* mix_mono_8_samples_slow: + * Mixes from an eight bit sample into a mono buffer, until either len + * samples have been mixed or until the end of the sample is reached, + * using the slow mixing code that supports volume ramps and frequency/pan + * sweep effects. + */ +static void mix_mono_8_samples_slow(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) +{ + signed short *vol = (short *)(mix_vol_table + spl->lvol); + + #define MIX() \ + *(buf++) += vol[spl->data8[spl->pos>>MIXER_FIX_SHIFT]]; + + MIXER(); + + #undef MIX +} + +static END_OF_FUNCTION(mix_mono_8_samples_slow); + + + +/* mix_stereo_8_samples_slow: + * Mixes from an eight bit sample into a stereo buffer, until either len + * samples have been mixed or until the end of the sample is reached, + * using the slow mixing code that supports volume ramps and frequency/pan + * sweep effects. + */ +static void mix_stereo_8_samples_slow(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) +{ + signed short *lvol = (short *)(mix_vol_table + spl->lvol); + signed short *rvol = (short *)(mix_vol_table + spl->rvol); + + len >>= 1; + + #define MIX() \ + *(buf++) += lvol[spl->data8[spl->pos>>MIXER_FIX_SHIFT]]; \ + *(buf++) += rvol[spl->data8[spl->pos>>MIXER_FIX_SHIFT]]; + + MIXER(); + + #undef MIX +} + +static END_OF_FUNCTION(mix_stereo_8_samples_slow); + + + +/* mix_mono_16_samples_slow: + * Mixes from a 16 bit sample into a mono buffer, until either len samples + * have been mixed or until the end of the sample is reached, using the + * slow mixing code that supports volume ramps and frequency/pan sweep + * effects. + */ +static void mix_mono_16_samples_slow(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) +{ + signed short *vol = (short *)(mix_vol_table + spl->lvol); + + #define MIX() \ + *(buf++) += vol[(spl->data16[spl->pos>>MIXER_FIX_SHIFT])>>8]; + + MIXER(); + + #undef MIX +} + +static END_OF_FUNCTION(mix_mono_16_samples_slow); + + + +/* mix_stereo_16_samples_slow: + * Mixes from a 16 bit sample into a stereo buffer, until either len samples + * have been mixed or until the end of the sample is reached, using the + * slow mixing code that supports volume ramps and frequency/pan sweep + * effects. + */ +static void mix_stereo_16_samples_slow(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) +{ + signed short *lvol = (short *)(mix_vol_table + spl->lvol); + signed short *rvol = (short *)(mix_vol_table + spl->rvol); + + len >>= 1; + + #define MIX() \ + *(buf++) += lvol[(spl->data16[spl->pos>>MIXER_FIX_SHIFT])>>8]; \ + *(buf++) += rvol[(spl->data16[spl->pos>>MIXER_FIX_SHIFT])>>8]; + + MIXER(); + + #undef MIX +} + +static END_OF_FUNCTION(mix_stereo_16_samples_slow); + + + +/* _mix_some_samples: + * Mixes samples into a buffer in conventional memory (the buf parameter + * should be a linear offset into the specified segment), using the buffer + * size, sample frequency, etc, set when you called _mixer_init(). This + * should be called by the hardware end-of-buffer interrupt routine to + * get the next buffer full of samples to DMA to the card. + */ +void _mix_some_samples(unsigned long buf, unsigned short seg, int issigned) +{ + int i; + unsigned short *p = mix_buffer; + unsigned long *l = (unsigned long *)p; + + /* clear mixing buffer */ + for (i=0; i 0) || (_phys_voice[i].dvol > 0))) { + if ((_phys_voice[i].dvol) || (_phys_voice[i].dfreq) || (_phys_voice[i].dpan)) { + if (mixer_voice[i].data8) + mix_stereo_8_samples_slow(mixer_voice+i, _phys_voice+i, p, mix_size); + else + mix_stereo_16_samples_slow(mixer_voice+i, _phys_voice+i, p, mix_size); + } + else { + if (mixer_voice[i].data8) + mix_stereo_8_samples(mixer_voice+i, _phys_voice+i, p, mix_size); + else + mix_stereo_16_samples(mixer_voice+i, _phys_voice+i, p, mix_size); + } + } + } + } + else { + for (i=0; i 0) || (_phys_voice[i].dvol > 0))) { + if ((_phys_voice[i].dvol) || (_phys_voice[i].dfreq) || (_phys_voice[i].dpan)) { + if (mixer_voice[i].data8) + mix_mono_8_samples_slow(mixer_voice+i, _phys_voice+i, p, mix_size); + else + mix_mono_16_samples_slow(mixer_voice+i, _phys_voice+i, p, mix_size); + } + else { + if (mixer_voice[i].data8) + mix_mono_8_samples(mixer_voice+i, _phys_voice+i, p, mix_size); + else + mix_mono_16_samples(mixer_voice+i, _phys_voice+i, p, mix_size); + } + } + } + } + + _farsetsel(seg); + + /* transfer to conventional memory buffer */ + if (mix_16bit) { + if (issigned) { + for (i=0; i> (16-MIX_RES_16)] ^ 0x8000); + buf += 2; + p++; + } + } + else { + for (i=0; i> (16-MIX_RES_16)]); + buf += 2; + p++; + } + } + } + else { + for (i=0; i> (16-MIX_RES_8)]); + buf++; + p++; + } + } +} + +END_OF_FUNCTION(_mix_some_samples); + + + +/* _mixer_init_voice: + * Initialises the specificed voice ready for playing a sample. + */ +void _mixer_init_voice(int voice, SAMPLE *sample) +{ + mixer_voice[voice].playing = FALSE; + mixer_voice[voice].pos = 0; + mixer_voice[voice].len = sample->len << MIXER_FIX_SHIFT; + mixer_voice[voice].loop_start = sample->loop_start << MIXER_FIX_SHIFT; + mixer_voice[voice].loop_end = sample->loop_end << MIXER_FIX_SHIFT; + + if (sample->bits == 8) { + mixer_voice[voice].data8 = sample->data; + mixer_voice[voice].data16 = NULL; + } + else { + mixer_voice[voice].data8 = NULL; + mixer_voice[voice].data16 = sample->data; + } + + update_mixer_volume(mixer_voice+voice, _phys_voice+voice); + update_mixer_freq(mixer_voice+voice, _phys_voice+voice); +} + +END_OF_FUNCTION(_mixer_init_voice); + + + +/* _mixer_release_voice: + * Releases a voice when it is no longer required. + */ +void _mixer_release_voice(int voice) +{ + mixer_voice[voice].playing = FALSE; + mixer_voice[voice].data8 = NULL; + mixer_voice[voice].data16 = NULL; +} + +END_OF_FUNCTION(_mixer_release_voice); + + + +/* _mixer_start_voice: + * Activates a voice, with the currently selected parameters. + */ +void _mixer_start_voice(int voice) +{ + if (mixer_voice[voice].pos >= mixer_voice[voice].len) + mixer_voice[voice].pos = 0; + + mixer_voice[voice].playing = TRUE; +} + +END_OF_FUNCTION(_mixer_start_voice); + + + +/* _mixer_stop_voice: + * Stops a voice from playing. + */ +void _mixer_stop_voice(int voice) +{ + mixer_voice[voice].playing = FALSE; +} + +END_OF_FUNCTION(_mixer_stop_voice); + + + +/* _mixer_loop_voice: + * Sets the loopmode for a voice. + */ +void _mixer_loop_voice(int voice, int loopmode) +{ + update_mixer_freq(mixer_voice+voice, _phys_voice+voice); +} + +END_OF_FUNCTION(_mixer_loop_voice); + + + +/* _mixer_get_position: + * Returns the current play position of a voice, or -1 if it has finished. + */ +int _mixer_get_position(int voice) +{ + if (mixer_voice[voice].pos >= mixer_voice[voice].len) + return -1; + + return (mixer_voice[voice].pos >> MIXER_FIX_SHIFT); +} + +END_OF_FUNCTION(_mixer_get_position); + + + +/* _mixer_set_position: + * Sets the current play position of a voice. + */ +void _mixer_set_position(int voice, int position) +{ + mixer_voice[voice].pos = (position << MIXER_FIX_SHIFT); + + if (mixer_voice[voice].pos >= mixer_voice[voice].len) + mixer_voice[voice].playing = FALSE; +} + +END_OF_FUNCTION(_mixer_set_position); + + + +/* _mixer_get_volume: + * Returns the current volume of a voice. + */ +int _mixer_get_volume(int voice) +{ + return (_phys_voice[voice].vol >> 12); +} + +END_OF_FUNCTION(_mixer_get_volume); + + + +/* _mixer_set_volume: + * Sets the volume of a voice. + */ +void _mixer_set_volume(int voice, int volume) +{ + update_mixer_volume(mixer_voice+voice, _phys_voice+voice); +} + +END_OF_FUNCTION(_mixer_set_volume); + + + +/* _mixer_ramp_volume: + * Starts a volume ramping operation. + */ +void _mixer_ramp_volume(int voice, int time, int endvol) +{ + int d = (endvol << 12) - _phys_voice[voice].vol; + time = MAX(time * (mix_freq / UPDATE_FREQ) / 1000, 1); + + _phys_voice[voice].target_vol = endvol << 12; + _phys_voice[voice].dvol = d / time; +} + +END_OF_FUNCTION(_mixer_ramp_volume); + + + +/* _mixer_stop_volume_ramp: + * Ends a volume ramp operation. + */ +void _mixer_stop_volume_ramp(int voice) +{ + _phys_voice[voice].dvol = 0; +} + +END_OF_FUNCTION(_mixer_stop_volume_ramp); + + + +/* _mixer_get_frequency: + * Returns the current frequency of a voice. + */ +int _mixer_get_frequency(int voice) +{ + return (_phys_voice[voice].freq >> 12); +} + +END_OF_FUNCTION(_mixer_get_frequency); + + + +/* _mixer_set_frequency: + * Sets the frequency of a voice. + */ +void _mixer_set_frequency(int voice, int frequency) +{ + update_mixer_freq(mixer_voice+voice, _phys_voice+voice); +} + +END_OF_FUNCTION(_mixer_set_frequency); + + + +/* _mixer_sweep_frequency: + * Starts a frequency sweep. + */ +void _mixer_sweep_frequency(int voice, int time, int endfreq) +{ + int d = (endfreq << 12) - _phys_voice[voice].freq; + time = MAX(time * (mix_freq / UPDATE_FREQ) / 1000, 1); + + _phys_voice[voice].target_freq = endfreq << 12; + _phys_voice[voice].dfreq = d / time; +} + +END_OF_FUNCTION(_mixer_sweep_frequency); + + + +/* _mixer_stop_frequency_sweep: + * Ends a frequency sweep. + */ +void _mixer_stop_frequency_sweep(int voice) +{ + _phys_voice[voice].dfreq = 0; +} + +END_OF_FUNCTION(_mixer_stop_frequency_sweep); + + + +/* _mixer_get_pan: + * Returns the current pan position of a voice. + */ +int _mixer_get_pan(int voice) +{ + return (_phys_voice[voice].pan >> 12); +} + +END_OF_FUNCTION(_mixer_get_pan); + + + +/* _mixer_set_pan: + * Sets the pan position of a voice. + */ +void _mixer_set_pan(int voice, int pan) +{ + update_mixer_volume(mixer_voice+voice, _phys_voice+voice); +} + +END_OF_FUNCTION(_mixer_set_pan); + + + +/* _mixer_sweep_pan: + * Starts a pan sweep. + */ +void _mixer_sweep_pan(int voice, int time, int endpan) +{ + int d = (endpan << 12) - _phys_voice[voice].pan; + time = MAX(time * (mix_freq / UPDATE_FREQ) / 1000, 1); + + _phys_voice[voice].target_pan = endpan << 12; + _phys_voice[voice].dpan = d / time; +} + +END_OF_FUNCTION(_mixer_sweep_pan); + + + +/* _mixer_stop_pan_sweep: + * Ends a pan sweep. + */ +void _mixer_stop_pan_sweep(int voice) +{ + _phys_voice[voice].dpan = 0; +} + +END_OF_FUNCTION(_mixer_stop_pan_sweep); + + + +/* _mixer_set_echo: + * Sets the echo parameters for a voice. + */ +void _mixer_set_echo(int voice, int strength, int delay) +{ + /* not implemented */ +} + +END_OF_FUNCTION(_mixer_set_echo); + + + +/* _mixer_set_tremolo: + * Sets the tremolo parameters for a voice. + */ +void _mixer_set_tremolo(int voice, int rate, int depth) +{ + /* not implemented */ +} + +END_OF_FUNCTION(_mixer_set_tremolo); + + + +/* _mixer_set_vibrato: + * Sets the amount of vibrato for a voice. + */ +void _mixer_set_vibrato(int voice, int rate, int depth) +{ + /* not implemented */ +} + +END_OF_FUNCTION(_mixer_set_vibrato); + + + +/* mixer_lock_mem: + * Locks memory used by the functions in this file. + */ +static void mixer_lock_mem() +{ + LOCK_VARIABLE(mixer_voice); + LOCK_VARIABLE(mix_buffer); + LOCK_VARIABLE(mix_vol_table); + LOCK_VARIABLE(mix_clip_table); + LOCK_VARIABLE(mix_voices); + LOCK_VARIABLE(mix_size); + LOCK_VARIABLE(mix_freq); + LOCK_VARIABLE(mix_stereo); + LOCK_VARIABLE(mix_16bit); + LOCK_FUNCTION(mix_mono_8_samples); + LOCK_FUNCTION(mix_stereo_8_samples); + LOCK_FUNCTION(mix_mono_16_samples); + LOCK_FUNCTION(mix_stereo_16_samples); + LOCK_FUNCTION(mix_mono_8_samples_slow); + LOCK_FUNCTION(mix_stereo_8_samples_slow); + LOCK_FUNCTION(mix_mono_16_samples_slow); + LOCK_FUNCTION(mix_stereo_16_samples_slow); + LOCK_FUNCTION(_mix_some_samples); + LOCK_FUNCTION(_mixer_init_voice); + LOCK_FUNCTION(_mixer_release_voice); + LOCK_FUNCTION(_mixer_start_voice); + LOCK_FUNCTION(_mixer_stop_voice); + LOCK_FUNCTION(_mixer_loop_voice); + LOCK_FUNCTION(_mixer_get_position); + LOCK_FUNCTION(_mixer_set_position); + LOCK_FUNCTION(_mixer_get_volume); + LOCK_FUNCTION(_mixer_set_volume); + LOCK_FUNCTION(_mixer_ramp_volume); + LOCK_FUNCTION(_mixer_stop_volume_ramp); + LOCK_FUNCTION(_mixer_get_frequency); + LOCK_FUNCTION(_mixer_set_frequency); + LOCK_FUNCTION(_mixer_sweep_frequency); + LOCK_FUNCTION(_mixer_stop_frequency_sweep); + LOCK_FUNCTION(_mixer_get_pan); + LOCK_FUNCTION(_mixer_set_pan); + LOCK_FUNCTION(_mixer_sweep_pan); + LOCK_FUNCTION(_mixer_stop_pan_sweep); + LOCK_FUNCTION(_mixer_set_echo); + LOCK_FUNCTION(_mixer_set_tremolo); + LOCK_FUNCTION(_mixer_set_vibrato); +} + + + diff --git a/arch/dos/allg_snd/sound/readme.d1 b/arch/dos/allg_snd/sound/readme.d1 new file mode 100644 index 00000000..e8c19d2a --- /dev/null +++ b/arch/dos/allg_snd/sound/readme.d1 @@ -0,0 +1,6 @@ +This is a stripped version of the Allegro game programming +library by Shawn Hargreaves, I left only the sound stuff in. + +See readme.txt for for information about Allegro. + +Arne diff --git a/arch/dos/allg_snd/sound/readme.txt b/arch/dos/allg_snd/sound/readme.txt new file mode 100644 index 00000000..1d122fa6 --- /dev/null +++ b/arch/dos/allg_snd/sound/readme.txt @@ -0,0 +1,323 @@ + ______ ___ ___ + /\ _ \ /\_ \ /\_ \ + \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + /\____/ + \_/__/ Version 3.0 + + + A game programming library + + By Shawn Hargreaves, 1994/97 + + + +#include + + "I do not accept responsibility for any effects, adverse or otherwise, + that this code may have on you, your computer, your sanity, your dog, + and anything else that you can think of. Use it at your own risk." + + + +====================================== +============ Introduction ============ +====================================== + + Allegro is a library of functions for use in computer games, written for + the djgpp compiler in a mixture of C and assembly language. This is + version 3.0: see the NEWS file for a list of differences from the + previous release. + + According to the Oxford Companion to Music, Allegro is the Italian for + "quick, lively, bright". Once upon a time it was also an acronym for + "Atari Low Level Game Routines", but it is a long time since I did any + programming on the Atari, and the name is pretty much the only thing left + of the original Atari code. + + + +================================== +============ Features ============ +================================== + + Supports VGA mode 13h, mode-X (twenty two tweaked VGA resolutions plus + unchained 640x400 Xtended mode), and SVGA modes with 8, 15, 16, 24, and + 32 bit color depths. Uses VESA 2.0 linear framebuffers if they are + available, and also contains register level drivers for ATI, Cirrus, + Paradise, S3, Trident, Tseng, and Video-7 cards. + + Drawing functions including putpixel, getpixel, lines, rectangles, flat + shaded, gouraud shaded, and texture mapped polygons, circles, floodfill, + bezier splines, patterned fills, masked, run length encoded, and compiled + sprites, blitting, bitmap scaling and rotation, translucency/lighting, + and text output with proportional fonts. Supports clipping, and can draw + directly to the screen or to memory bitmaps of any size. + + Hardware scrolling, mode-X split screens, and palette manipulation. + + FLI/FLC animation player. + + Plays background MIDI music and up to 32 simultaneous sound effects. + Samples can be looped (forwards, backwards, or bidirectionally), and the + volume, pan, pitch, etc, can be adjusted while they are playing. The MIDI + player responds to note on, note off, main volume, pan, pitch bend, and + program change messages, using the General MIDI patch set and drum + mappings. Currently supports Adlib, SB, SB Pro, SB16, AWE32, MPU-401, and + software wavetable MIDI. + + Easy access to the mouse, keyboard, joystick, and high resolution timer + interrupts, including a vertical retrace interrupt simulator. + + Routines for reading and writing LZSS compressed files. + + Multi-object data files and a grabber utility. + + Math functions including fixed point arithmetic, lookup table trig, and + 3d vector/matrix manipulation. + + GUI dialog manager and file selector. + + + +=================================== +============ Copyright ============ +=================================== + + Allegro is swap-ware. You may use, modify, redistribute, and generally + hack it about in any way you like, but if you do you must send me + something in exchange. This could be a complimentary copy of a game, an + addition or improvement to Allegro, a bug report, some money (this is + particularly encouraged if you use Allegro in a commercial product), or + just a copy of your autoexec.bat if you don't have anything better. If + you redistribute parts of Allegro or make a game using it, it would be + nice if you mentioned me somewhere in the credits, but if you just want + to pinch a few routines that is OK too. I'll trust you not to rip me off. + + + +============================================ +============ Supported hardware ============ +============================================ + + The bare minimum you need to use Allegro is a 386 with a VGA graphics + card, but a 486 is strongly recommended. To get into SVGA modes you will + need a compatible SVGA card, which means either one of the cards that is + supported directly, or a card with a working VESA driver. If you have a + VESA 2.0 implementation such as UniVBE (which you can get from the + Display Doctor link on http://www.scitechsoft.com/), you are fine just + using that. If you don't, beware. For one thing, everything will be much + slower if Allegro can't use the sexy VBE 2.0 features. For another, I + could go on all day telling horror stories about the buggy and generally + just pathetic VESA implementations that I've come across. If you are + having trouble with the SVGA modes, try getting a copy of UniVBE and see + if that clears things up (it probably will: SciTech usually get these + things right). + + On the sound front, Allegro supports sample playback on the SB (mono), + the SB Pro (stereo), and the SB16. It has MIDI drivers for the OPL2 FM + synth (Adlib and SB cards), the OPL3 (Adlib Gold, SB Pro-II and above), + the pair of OPL2 chips found in the SB Pro-I, the AWE32 EMU8000 chip, the + raw SB MIDI output, and the MPU-401 interface, plus it can emulate a + wavetable MIDI synth in software, running on top of any of the supported + digital soundcards. If you feel like coming up with drivers for any other + hardware, they would be much appreciated. + + You may notice that this release contains some code for building a Linux + version, but don't bother trying this: it won't work! A _lot_ more work + is needed before Allegro will be usable under Linux. + + There is also the first part of a VBE/AF driver in this package. VBE/AF + is an extension to the VBE 2.0 API which provides a standard way of + accessing hardware accelerator features. My driver implements all the + basic mode set and bank switch functions, so it works as well as the + regular VESA drivers, but it doesn't yet support any accelerated drawing + operations. This is because SciTech have, so far, only implemented VBE/AF + on the ATI Mach64 chipset, and I don't have access to a Mach64. I'll + finish the driver as soon as they implement VBE/AF on the Matrox Mystique. + + + +============================================ +============ Installing Allegro ============ +============================================ + + To conserve space I decided to make this a source-only distribution, so + you will have to compile Allegro before you can use it. To do this you + should: + + - Go to wherever you want to put your copy of Allegro (your main djgpp + directory would be fine, but you can put it somewhere else if you + prefer), and unzip everything. Allegro contains several subdirectories, + so you must specify the -d flag to pkunzip. + + - If you are using PGCC, uncomment the definition of PGCC at the top of + the makefile, or set the environment variable "PGCC=1". + + - Type "cd allegro", followed by "make". Then go do something + interesting while everything compiles. If all goes according to plan + you will end up with a bunch of test programs, some tools like the + grabber, and the library itself, liballeg.a. + + If you have any trouble with the build, look at faq.txt for the + solutions to some of the more common problems. + + - If you want to use the sound routines or a non-US keyboard layout, it + is a good idea to set up an allegro.cfg file: see below. + + - If you want to read the Allegro documentation with the Info viewer + or the Rhide online help system, edit the file djgpp\info\dir, and in + the menu section add the lines: + + * Allegro: (allegro.inf). + The Allegro game programming library + + - If you want to create the HTML documentation as one large allegro.html + file rather than splitting it into sections, edit docs\allegro._tx, + remove the @multiplefiles statement from line 8, and run make again. + + To use Allegro in your programs you should: + + - Put the following line at the beginning of all C or C++ files that use + Allegro: + + #include + + - If you compile from the command line or with a makefile, add '-lalleg' + to the end of the gcc command, eg: + + gcc foo.c -o foo.exe -lalleg + + - If you are using Rhide, go to the Options/Libraries menu, type 'alleg' + into the first empty space, and make sure the box next to it is checked. + + See allegro.txt for details of how to use the Allegro functions, and how + to build a debug version of the library. + + + +======================================= +============ Configuration ============ +======================================= + +When Allegro initialises the keyboard and sound routines it reads +information about your hardware from a file called allegro.cfg or sound.cfg. +If this file doesn't exist it will autodetect (ie. guess :-) You can write +your config file by hand with a text editor, or you can use the setup +utility program. + +Normally setup.exe and allegro.cfg will go in the same directory as the +Allegro program they are controlling. This is fine for the end user, but it +can be a pain for a programmer using Allegro because you may have several +programs in different directories and want to use a single allegro.cfg for +all of them. If this is the case you can set the environment variable +ALLEGRO to the directory containing your allegro.cfg, and Allegro will look +there if there is no allegro.cfg in the current directory. + +The mapping tables used to store different keyboard layouts are stored in a +file called keyboard.dat. This must either be located in the same directory +as your Allegro program, or in the directory pointed to by the ALLEGRO +environment variable. If you want to support different international +keyboard layouts, you must distribute a copy of keyboard.dat along with your +program. + +See allegro.txt for details of the config file format. + + + +================================================ +============ Notes for the musician ============ +================================================ + +The OPL2 synth chip can provide either nine voice polyphony or six voices +plus five drum channels. How to make music sound good on the OPL2 is left as +an exercise for the reader :-) On an SB Pro or above you will have eighteen +voices, or fifteen plus drums. Allegro decides whether to use drum mode +individually for each MIDI file you play, based on whether it contains any +drum sounds or not. If you have an orchestral piece with just the odd cymbal +crash, you might be better removing the drums altogether as that will let +Allegro use the non-drum mode and give you an extra three notes polyphony. + +When Allegro is playing a MIDI file in looped mode, it jumps back to the +start of the file when it reaches the end of the piece. To control the exact +loop point, you may need to insert a dummy marker event such as a controller +message on an unused channel. + +All the OPL chips have very limited stereo capabilities. On an OPL2, +everything is of course played in mono. On the SB Pro-I, sounds can only be +panned hard left or right. With the OPL3 chip in the SB Pro-II and above, +they can be panned left, right, or centre. I could use two voices per note +to provide more flexible panning, but that would reduce the available +polyphony and I don't want to do that. So don't try to move sounds around +the stereo image with streams of pan controller messages, because they will +jerk horribly. It is also worth thinking out the panning of each channel so +that the music will sound ok on both SB Pro-I and OPL3 cards. If you want a +sound panned left or right, use a pan value less than 48 or greater than 80. +If you want it centred, use a pan value between 48 and 80, but put it +slightly to one side of the exactly central 64 to control which speaker will +be used if the central panning isn't possible. + +The DIGMID wavetable driver uses standard GUS format .pat files, and you +will need a collection of such instruments before you can use it. This can +either be in the standard GUS format (a set of .pat files and a default.cfg +index), or a patches.dat file as produced by the pat2dat utility. You can +also use pat2dat to convert AWE32 SoundFont banks into the patches.dat +format, and if you list some MIDI files on the command line it will filter +the sample set to only include the instruments that are actually used by +those tunes, so it can be useful for getting rid of unused instruments when +you are preparing to distribute a game. See the Allegro website for some +links to suitable sample sets. + +The DIGMID driver normally only loads the patches needed for each song when +the tune is first played. This reduces the memory usage, but can result in a +longish delay the first time you play each MIDI file. If you prefer to load +the entire patch set in one go, call the load_midi_patches() function. + +The CPU sample mixing code can support between 1 and 32 voices, going up in +powers of two (ie. either 1, 2, 4, 8, 16, or 32 channels). By default it +provides 8 digital voices, or 8 digital plus 24 MIDI voices (a total of 32) +if the DIGMID driver is in use. But the more voices, the lower the output +volume and quality, so you may wish to change this by calling the +reserve_voices() function or setting the digi_voices and midi_voices +parameters in allegro.cfg. + + + +====================================== +============ Contact info ============ +====================================== + + WWW: http://www.talula.demon.co.uk/allegro/ + + Mailing list: allegro@canvaslink.com. To add or remove yourself, + write to listserv@canvaslink.com with the text + "subscribe allegro yourname" or "unsubscribe + allegro" in the body of your message. + + Usenet: Try the djgpp newsgroup, comp.os.msdos.djgpp + + IRC: #allegro channel on EFnet + + My email: shawn@talula.demon.co.uk + + Snail mail: Shawn Hargreaves, + 1 Salisbury Road, + Market Drayton, + Shropshire, + England, TF9 1AJ. + + Telephone: UK 01630 654346 + + On Foot: Coming down Shrewsbury Road from the town centre, + turn off down Salisbury Road and it is the first + house on the left. + + If all else fails: 52 deg 54' N + 2 deg 29' W + + The latest version of Allegro can always be found on the Allegro + homepage, http://www.talula.demon.co.uk/allegro/. + diff --git a/arch/dos/allg_snd/sound/snddrv.c b/arch/dos/allg_snd/sound/snddrv.c new file mode 100644 index 00000000..3c8d9b43 --- /dev/null +++ b/arch/dos/allg_snd/sound/snddrv.c @@ -0,0 +1,42 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * By Shawn Hargreaves, + * 1 Salisbury Road, + * Market Drayton, + * Shropshire, + * England, TF9 1AJ. + * + * List of available sound drivers, kept in a seperate file so that + * they can be overriden by user programs. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + + + +DECLARE_DIGI_DRIVER_LIST +( + DIGI_DRIVER_GUS + DIGI_DRIVER_SB +) + + +DECLARE_MIDI_DRIVER_LIST +( + MIDI_DRIVER_AWE32 + MIDI_DRIVER_DIGMID + MIDI_DRIVER_ADLIB + MIDI_DRIVER_SB_OUT + MIDI_DRIVER_MPU +) + diff --git a/arch/dos/allg_snd/sound/sound.c b/arch/dos/allg_snd/sound/sound.c new file mode 100644 index 00000000..c409d97b --- /dev/null +++ b/arch/dos/allg_snd/sound/sound.c @@ -0,0 +1,1579 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * By Shawn Hargreaves, + * 1 Salisbury Road, + * Market Drayton, + * Shropshire, + * England, TF9 1AJ. + * + * Sound setup routines and API framework functions. + * + * See readme.txt for copyright information. + */ + + +#include +#include +#include +#include +#include +#include + +#ifdef DJGPP +#include +#include +#endif + +#include "allegro.h" +#include "internal.h" + + + +/* dummy functions for the nosound drivers */ +int _dummy_detect() { return TRUE; } +int _dummy_init(int voices) { return 0; } +void _dummy_exit() { } +int _dummy_mixer_volume(int volume) { return 0; } +void _dummy_init_voice(int voice, SAMPLE *sample) { } +void _dummy_noop1(int p) { } +void _dummy_noop2(int p1, int p2) { } +void _dummy_noop3(int p1, int p2, int p3) { } +int _dummy_get_position(int voice) { return -1; } +int _dummy_get(int voice) { return 0; } +void _dummy_raw_midi(unsigned char data) { } +int _dummy_load_patches(char *patches, char *drums) { return 0; } +void _dummy_adjust_patches(char *patches, char *drums) { } +void _dummy_key_on(int inst, int note, int bend, int vol, int pan) { } + +/* put this after all the dummy functions, so they will all get locked */ +END_OF_FUNCTION(_dummy_detect); + + + +DIGI_DRIVER digi_none = +{ + "No sound", "The sound of silence", + 0, 0, 0xFFFF, 0, + _dummy_detect, + _dummy_init, + _dummy_exit, + _dummy_mixer_volume, + _dummy_init_voice, + _dummy_noop1, + _dummy_noop1, + _dummy_noop1, + _dummy_noop2, + _dummy_get_position, + _dummy_noop2, + _dummy_get, + _dummy_noop2, + _dummy_noop3, + _dummy_noop1, + _dummy_get, + _dummy_noop2, + _dummy_noop3, + _dummy_noop1, + _dummy_get, + _dummy_noop2, + _dummy_noop3, + _dummy_noop1, + _dummy_noop3, + _dummy_noop3, + _dummy_noop3 +}; + + +MIDI_DRIVER midi_none = +{ + "No sound", "The sound of silence", + 0, 0, 0xFFFF, 0, -1, -1, + _dummy_detect, + _dummy_init, + _dummy_exit, + _dummy_mixer_volume, + _dummy_raw_midi, + _dummy_load_patches, + _dummy_adjust_patches, + _dummy_key_on, + _dummy_noop1, + _dummy_noop2, + _dummy_noop3, + _dummy_noop2, + _dummy_noop2 +}; + + +int digi_card = DIGI_AUTODETECT; /* current driver ID numbers */ +int midi_card = MIDI_AUTODETECT; + +DIGI_DRIVER *digi_driver = &digi_none; /* these things do all the work */ +MIDI_DRIVER *midi_driver = &midi_none; + +static int sound_installed = FALSE; /* are we installed? */ + +static int digi_reserve = -1; /* how many voices to reserve */ +static int midi_reserve = -1; + +VOICE _voice[VIRTUAL_VOICES]; /* list of active samples */ + +PHYS_VOICE _phys_voice[DIGI_VOICES]; /* physical -> virtual voice map */ + +int _digi_volume = -1; /* current volume settings */ +int _midi_volume = -1; + +int _flip_pan = FALSE; /* reverse l/r sample panning? */ + +int _sb_freq = -1; /* hardware parameters */ +int _sb_port = -1; +int _sb_dma = -1; +int _sb_irq = -1; +int _fm_port = -1; +int _mpu_port = -1; + +#define SWEEP_FREQ 50 + +static void update_sweeps(); +static void sound_lock_mem(); + +int (*_midi_init)() = NULL; +void (*_midi_exit)() = NULL; + + + +/* read_sound_config: + * Helper for reading the sound hardware configuration data. + */ +static void read_sound_config() +{ + _flip_pan = get_config_int("sound", "flip_pan", FALSE); + _sb_port = get_config_hex("sound", "sb_port", -1); + _sb_dma = get_config_int("sound", "sb_dma", -1); + _sb_irq = get_config_int("sound", "sb_irq", -1); + _sb_freq = get_config_int("sound", "sb_freq", -1); + _fm_port = get_config_hex("sound", "fm_port", -1); + _mpu_port = get_config_hex("sound", "mpu_port", -1); + _digi_volume = get_config_int("sound", "digi_volume", -1); + _midi_volume = get_config_int("sound", "midi_volume", -1); +} + + + +/* detect_digi_driver: + * Detects whether the specified digital sound driver is available, + * returning the maximum number of voices that it can provide, or + * zero if the device is not present. This function must be called + * _before_ install_sound(). + */ +int detect_digi_driver(int driver_id) +{ + int i; + + if (sound_installed) + return 0; + + read_sound_config(); + + for (i=0; _digi_driver_list[i].driver_id; i++) { + if (_digi_driver_list[i].driver_id == driver_id) { + digi_card = driver_id; + midi_card = MIDI_AUTODETECT; + if (_digi_driver_list[i].driver->detect()) + return _digi_driver_list[i].driver->max_voices; + else + return 0; + } + } + + return digi_none.max_voices; +} + + + +/* detect_midi_driver: + * Detects whether the specified midi sound driver is available, + * returning the maximum number of voices that it can provide, or + * zero if the device is not present. If this routine returns -1, + * it is a note-stealing MIDI driver, which shares voices with the + * current digital driver. In this situation you can use the + * reserve_voices() function to specify how the available voices are + * divided between the digital and MIDI playback routines. This function + * must be called _before_ install_sound(). + */ +int detect_midi_driver(int driver_id) +{ + int i; + + if (sound_installed) + return 0; + + read_sound_config(); + + for (i=0; _midi_driver_list[i].driver_id; i++) { + if (_midi_driver_list[i].driver_id == driver_id) { + digi_card = DIGI_AUTODETECT; + midi_card = driver_id; + if (_midi_driver_list[i].driver->detect()) + return _midi_driver_list[i].driver->max_voices; + else + return 0; + } + } + + return midi_none.max_voices; +} + + + +/* reserve_voices: + * Reserves a number of voices for the digital and MIDI sound drivers + * respectively. This must be called _before_ install_sound(). If you + * attempt to reserve too many voices, subsequent calls to install_sound() + * will fail. Note that depending on the driver you may actually get + * more voices than you reserve: these values just specify the minimum + * that is appropriate for your application. Pass a negative reserve value + * to use the default settings. + */ +void reserve_voices(int digi_voices, int midi_voices) +{ + digi_reserve = digi_voices; + midi_reserve = midi_voices; +} + + + +/* install_sound: + * Initialises the sound module, returning zero on success. The two card + * parameters should use the DIGI_* and MIDI_* constants defined in + * allegro.h. Pass DIGI_AUTODETECT and MIDI_AUTODETECT if you don't know + * what the soundcard is. + */ +int install_sound(int digi, int midi, char *cfg_path) +{ + int digi_voices, midi_voices; + int c; + + if (sound_installed) + return 0; + + for (c=0; cdetect()) { + digi_driver = &digi_none; + if (_midi_exit) + _midi_exit(); + return -1; + } + break; + } + } + + /* autodetect digital driver */ + if (!digi_driver) { + for (c=0; _digi_driver_list[c].driver; c++) { + digi_card = _digi_driver_list[c].driver_id; + if ((_digi_driver_list[c].autodetect) && + (_digi_driver_list[c].driver->detect())) { + digi_driver = _digi_driver_list[c].driver; + break; + } + } + } + + midi_driver = NULL; + + /* search table for a specific MIDI driver */ + for (c=0; _midi_driver_list[c].driver; c++) { + if (_midi_driver_list[c].driver_id == midi_card) { + midi_driver = _midi_driver_list[c].driver; + if (!midi_driver->detect()) { + digi_driver = &digi_none; + midi_driver = &midi_none; + if (_midi_exit) + _midi_exit(); + return -1; + } + break; + } + } + + /* autodetect MIDI driver */ + if (!midi_driver) { + for (c=0; _midi_driver_list[c].driver; c++) { + midi_card = _midi_driver_list[c].driver_id; + if ((_midi_driver_list[c].autodetect) && + (_midi_driver_list[c].driver->detect())) { + midi_driver = _midi_driver_list[c].driver; + break; + } + } + } + + /* work out how many voices to allocate for each driver */ + if (digi_reserve >= 0) + digi_voices = digi_reserve; + else + digi_voices = digi_driver->def_voices; + + if (midi_driver->max_voices < 0) { + /* MIDI driver steals voices from the digital player */ + if (midi_reserve >= 0) + midi_voices = midi_reserve; + else + midi_voices = MID(0, digi_driver->max_voices - digi_voices, midi_driver->def_voices); + + digi_voices += midi_voices; + } + else { + /* MIDI driver has voices of its own */ + if (midi_reserve >= 0) + midi_voices = midi_reserve; + else + midi_voices = midi_driver->def_voices; + } + + /* make sure this is a reasonable number of voices to use */ + if ((digi_voices > DIGI_VOICES) || (midi_voices > MIDI_VOICES)) { + sprintf(allegro_error, "Insufficient %s voices available", + (digi_voices > DIGI_VOICES) ? "digital" : "MIDI"); + digi_driver = &digi_none; + midi_driver = &midi_none; + if (_midi_exit) + _midi_exit(); + return -1; + } + + /* initialise the digital sound driver */ + if (digi_driver->init(digi_voices) != 0) { + digi_driver = &digi_none; + midi_driver = &midi_none; + if (_midi_exit) + _midi_exit(); + return -1; + } + + /* initialise the midi driver */ + if (midi_driver->init(midi_voices) != 0) { + digi_driver->exit(); + digi_driver = &digi_none; + midi_driver = &midi_none; + if (_midi_exit) + _midi_exit(); + return -1; + } + + digi_driver->voices = MIN(digi_driver->voices, DIGI_VOICES); + midi_driver->voices = MIN(midi_driver->voices, MIDI_VOICES); + + /* check that we actually got enough voices */ + if ((digi_driver->voices < digi_voices) || + ((midi_driver->voices < midi_voices) && (!midi_driver->raw_midi))) { + sprintf(allegro_error, "Insufficient %s voices available", + (digi_driver->voices < digi_voices) ? "digital" : "MIDI"); + midi_driver->exit(); + digi_driver->exit(); + digi_driver = &digi_none; + midi_driver = &midi_none; + if (_midi_exit) + _midi_exit(); + return -1; + } + + /* adjust for note-stealing MIDI drivers */ + if (midi_driver->max_voices < 0) { + midi_voices += (digi_driver->voices - digi_voices) * 3/4; + digi_driver->voices -= midi_voices; + midi_driver->basevoice = VIRTUAL_VOICES - midi_voices; + midi_driver->voices = midi_voices; + + for (c=0; cbasevoice+c].num = digi_driver->voices+c; + _phys_voice[digi_driver->voices+c].num = midi_driver->basevoice+c; + } + } + + /* simulate ramp/sweep effects for drivers that don't do it directly */ + if ((!digi_driver->ramp_volume) || + (!digi_driver->sweep_frequency) || + (!digi_driver->sweep_pan)) + install_int_ex(update_sweeps, BPS_TO_TIMER(SWEEP_FREQ)); + + /* set the global sound volume */ + if ((_digi_volume >= 0) || (_midi_volume >= 0)) + set_volume(_digi_volume, _midi_volume); + + _add_exit_func(remove_sound); + sound_installed = TRUE; + return 0; +} + + + +/* remove_sound: + * Sound module cleanup routine. + */ +void remove_sound() +{ + int c; + + if (sound_installed) { + remove_int(update_sweeps); + + for (c=0; cexit(); + midi_driver = &midi_none; + + digi_driver->exit(); + digi_driver = &digi_none; + + _remove_exit_func(remove_sound); + sound_installed = FALSE; + } +} + + + +/* set_volume: + * Alters the global sound output volume. Specify volumes for both digital + * samples and MIDI playback, as integers from 0 to 255. If possible this + * routine will use a hardware mixer to control the volume, otherwise it + * will tell the sample mixer and MIDI player to simulate a mixer in + * software. + */ +void set_volume(int digi_volume, int midi_volume) +{ + if (digi_volume >= 0) { + digi_volume = MID(0, digi_volume, 255); + + if ((digi_driver->mixer_volume) && + (digi_driver->mixer_volume(digi_volume) == 0)) + _digi_volume = -1; + else + _digi_volume = digi_volume; + } + + if (midi_volume >= 0) { + midi_volume = MID(0, midi_volume, 255); + + if ((midi_driver->mixer_volume) && + (midi_driver->mixer_volume(midi_volume) == 0)) + _midi_volume = -1; + else + _midi_volume = midi_volume; + } +} + + + +/* lock_sample: + * Locks a SAMPLE struct into physical memory. Pretty important, since + * they are mostly accessed inside interrupt handlers. + */ +void lock_sample(SAMPLE *spl) +{ + #ifdef DJGPP + _go32_dpmi_lock_data(spl, sizeof(SAMPLE)); + _go32_dpmi_lock_data(spl->data, spl->len*spl->bits/8); + #endif +} + + + +/* load_sample: + * Loads a sample from disk. + */ +SAMPLE *load_sample(char *filename) +{ + if (stricmp(get_extension(filename), "wav") == 0) + return load_wav(filename); + else if (stricmp(get_extension(filename), "voc") == 0) + return load_voc(filename); + else + return NULL; +} + + + +/* load_voc: + * Reads a mono 8 bit VOC format sample file, returning a SAMPLE structure, + * or NULL on error. + */ +SAMPLE *load_voc(char *filename) +{ + PACKFILE *f; + char buffer[30]; + int freq = 22050; + int bits = 8; + SAMPLE *spl = NULL; + int len; + int x; + + f = pack_fopen(filename, F_READ); + if (!f) + return NULL; + + pack_fread(buffer, 0x16, f); + + if (memcmp(buffer, "Creative Voice File", 0x13)) + goto getout; + + if (pack_igetw(f) != 0x010A) /* version: should be 0x010A */ + goto getout; + + if (pack_igetw(f) != 0x1129) /* subversion: should be 0x1129 */ + goto getout; + + if (pack_getc(f) != 0x01) /* sound data: should be 0x01 */ + goto getout; + + len = pack_igetw(f); /* length is three bytes long: two */ + x = pack_getc(f); /* .. and one byte */ + x <<= 16; + len += x-2; + + x = pack_getc(f); /* one byte of frequency */ + freq = 1000000 / (256-x); + + x = pack_getc(f); /* skip one byte */ + + spl = malloc(sizeof(SAMPLE)); + + if (spl) { + spl->bits = bits; + spl->freq = freq; + spl->len = len; + spl->priority = 255; + spl->loop_start = 0; + spl->loop_end = len; + spl->param = -1; + + spl->data = malloc(len); + if (!spl->data) { + free(spl); + spl = NULL; + } + else { + pack_fread(spl->data, len, f); + if (errno) { + free(spl->data); + free(spl); + spl = NULL; + } + } + } + + getout: + + pack_fclose(f); + + if (spl) + lock_sample(spl); + + return spl; +} + + + +/* load_wav: + * Reads a mono RIFF WAV format sample file, returning a SAMPLE structure, + * or NULL on error. + */ +SAMPLE *load_wav(char *filename) +{ + int trashtmp; + PACKFILE *f; + char buffer[25]; + int i; + int length, len; + int freq = 22050; + int bits = 8; + signed short s; + SAMPLE *spl = NULL; + + f = pack_fopen(filename, F_READ); + if (!f) + return NULL; + + pack_fread(buffer, 12, f); /* check RIFF header */ + if (memcmp(buffer, "RIFF", 4) || memcmp(buffer+8, "WAVE", 4)) + goto getout; + + while (!pack_feof(f)) { + if (pack_fread(buffer, 4, f) != 4) + break; + + length = pack_igetl(f); /* read chunk length */ + + if (memcmp(buffer, "fmt ", 4) == 0) { + i = pack_igetw(f); /* should be 1 for PCM data */ + length -= 2; + if (i != 1) + goto getout; + + i = pack_igetw(f); /* should be 1 for mono data */ + length -= 2; + if (i != 1) + goto getout; + + freq = pack_igetl(f); /* sample frequency */ + length -= 4; + + trashtmp=pack_igetl(f); /* skip six bytes */ + trashtmp=pack_igetw(f); + length -= 6; + + bits = pack_igetw(f); /* 8 or 16 bit data? */ + length -= 2; + if ((bits != 8) && (bits != 16)) + goto getout; + } + else if (memcmp(buffer, "data", 4) == 0) { + len = length; + if (bits == 16) + len /= 2; + + spl = malloc(sizeof(SAMPLE)); + + if (spl) { /* initialise the sample struct */ + spl->bits = bits; + spl->freq = freq; + spl->len = len; + spl->priority = 255; + spl->loop_start = 0; + spl->loop_end = len; + spl->param = -1; + + spl->data = malloc(length); + + if (!spl->data) { + free(spl); + spl = NULL; + } + else { /* read the actual sample data */ + if (bits == 8) { + pack_fread(spl->data, length, f); + } + else { + for (i=0; idata)[i] = s^0x8000; + } + } + + length -= len; + + if (errno) { + free(spl->data); + free(spl); + spl = NULL; + } + } + } + } + + while (length > 0) { /* skip the remainder of the chunk */ + if (pack_getc(f) == EOF) + break; + + length--; + } + } + + getout: + + pack_fclose(f); + + if (spl) + lock_sample(spl); + + return spl; +} + + + +/* destroy_sample: + * Frees a SAMPLE struct, checking whether the sample is currently playing, + * and stopping it if it is. + */ +void destroy_sample(SAMPLE *spl) +{ + if (spl) { + stop_sample(spl); + + if (spl->data) { + _unlock_dpmi_data(spl->data, spl->len*spl->bits/8); + free(spl->data); + } + + _unlock_dpmi_data(spl, sizeof(SAMPLE)); + free(spl); + } +} + + + +/* absolute_freq: + * Converts a pitch from the relative 1000 = original format to an absolute + * value in hz. + */ +static inline int absolute_freq(int freq, SAMPLE *spl) +{ + if (freq == 1000) + return spl->freq; + else + return (spl->freq * freq) / 1000; +} + + + +/* play_sample: + * Triggers a sample at the specified volume, pan position, and frequency. + * The volume and pan range from 0 (min/left) to 255 (max/right), although + * the resolution actually used by the playback routines is likely to be + * less than this. Frequency is relative rather than absolute: 1000 + * represents the frequency that the sample was recorded at, 2000 is + * twice this, etc. If loop is true the sample will repeat until you call + * stop_sample(), and can be manipulated while it is playing by calling + * adjust_sample(). + */ +int play_sample(SAMPLE *spl, int vol, int pan, int freq, int loop) +{ + int voice = allocate_voice(spl); + + if (voice >= 0) { + voice_set_volume(voice, vol); + voice_set_pan(voice, pan); + voice_set_frequency(voice, absolute_freq(freq, spl)); + voice_set_playmode(voice, (loop ? PLAYMODE_LOOP : PLAYMODE_PLAY)); + voice_start(voice); + release_voice(voice); + } + + return voice; +} + +END_OF_FUNCTION(play_sample); + + + +/* adjust_sample: + * Alters the parameters of a sample while it is playing, useful for + * manipulating looped sounds. You can alter the volume, pan, and + * frequency, and can also remove the looping flag, which will stop + * the sample when it next reaches the end of its loop. If there are + * several copies of the same sample playing, this will adjust the + * first one it comes across. If the sample is not playing it has no + * effect. + */ +void adjust_sample(SAMPLE *spl, int vol, int pan, int freq, int loop) +{ + int c; + + for (c=0; cvoices; c++) + if (_phys_voice[c].num < 0) + return c; + + /* look for an autokill voice that has stopped */ + for (c=0; cvoices; c++) { + voice = _voice + _phys_voice[c].num; + if ((voice->autokill) && (digi_driver->get_position(c) < 0)) { + digi_driver->release_voice(c); + voice->sample = NULL; + voice->num = -1; + _phys_voice[c].num = -1; + return c; + } + } + + /* ok, we're going to have to get rid of something to make room... */ + for (c=0; cvoices; c++) { + voice = _voice + _phys_voice[c].num; + + /* sort by voice priorities */ + if (voice->priority <= priority) { + score = 65536 - voice->priority * 256; + + /* bias with a least-recently-used counter */ + score += MID(0, retrace_count - voice->time, 32768); + + /* bias according to whether the voice is looping or not */ + if (!(_phys_voice[c].playmode & PLAYMODE_LOOP)) + score += 32768; + + if (score > best_score) { + best = c; + best_score = score; + } + } + } + + if (best >= 0) { + /* kill off the old voice */ + digi_driver->stop_voice(best); + digi_driver->release_voice(best); + _voice[_phys_voice[best].num].num = -1; + _phys_voice[best].num = -1; + return best; + } + + return -1; +} + + + +/* allocate_virtual_voice: + * Allocates a virtual voice. This doesn't need to worry about killing off + * others to make room, as we allow up to 256 virtual voices to be used + * simultaneously. + */ +static inline int allocate_virtual_voice() +{ + int virt_voices, c; + + virt_voices = VIRTUAL_VOICES; + if (midi_driver->max_voices < 0) + virt_voices -= midi_driver->voices; + + /* look for a free voice */ + for (c=0; cget_position(_voice[c].num) < 0) { + digi_driver->release_voice(_voice[c].num); + _phys_voice[_voice[c].num].num = -1; + _voice[c].sample = NULL; + _voice[c].num = -1; + return c; + } + } + } + } + + return -1; +} + + + +/* allocate_voice: + * Allocates a voice ready for playing the specified sample, returning + * the voice number (note this is not the same as the physical voice + * number used by the sound drivers, and must only be used with the other + * voice functions, _not_ passed directly to the driver routines). + * Returns -1 if there is no voice available (this should never happen, + * since there are 256 virtual voices and anyone who needs more than that + * needs some urgent repairs to their brain :-) + */ +int allocate_voice(SAMPLE *spl) +{ + int phys = allocate_physical_voice(spl->priority); + int virt = allocate_virtual_voice(); + + if (virt >= 0) { + _voice[virt].sample = spl; + _voice[virt].num = phys; + _voice[virt].autokill = FALSE; + _voice[virt].time = retrace_count; + _voice[virt].priority = spl->priority; + + if (phys >= 0) { + _phys_voice[phys].num = virt; + _phys_voice[phys].playmode = 0; + _phys_voice[phys].vol = ((_digi_volume >= 0) ? _digi_volume : 255) << 12; + _phys_voice[phys].pan = 128 << 12; + _phys_voice[phys].freq = spl->freq << 12; + _phys_voice[phys].dvol = 0; + _phys_voice[phys].dpan = 0; + _phys_voice[phys].dfreq = 0; + + digi_driver->init_voice(phys, spl); + } + } + + return virt; +} + +END_OF_FUNCTION(allocate_voice); + + + +/* deallocate_voice: + * Releases a voice that was previously returned by allocate_voice(). + */ +void deallocate_voice(int voice) +{ + if (_voice[voice].num >= 0) { + digi_driver->stop_voice(_voice[voice].num); + digi_driver->release_voice(_voice[voice].num); + _phys_voice[_voice[voice].num].num = -1; + _voice[voice].num = -1; + } + + _voice[voice].sample = NULL; +} + +END_OF_FUNCTION(deallocate_voice); + + + +/* reallocate_voice: + * Switches an already-allocated voice to use a different sample. + */ +void reallocate_voice(int voice, SAMPLE *spl) +{ + int phys = _voice[voice].num; + + if (phys >= 0) { + digi_driver->stop_voice(phys); + digi_driver->release_voice(phys); + } + + _voice[voice].sample = spl; + _voice[voice].autokill = FALSE; + _voice[voice].time = retrace_count; + _voice[voice].priority = spl->priority; + + if (phys >= 0) { + _phys_voice[phys].playmode = 0; + _phys_voice[phys].vol = ((_digi_volume >= 0) ? _digi_volume : 255) << 12; + _phys_voice[phys].pan = 128 << 12; + _phys_voice[phys].freq = spl->freq << 12; + _phys_voice[phys].dvol = 0; + _phys_voice[phys].dpan = 0; + _phys_voice[phys].dfreq = 0; + + digi_driver->init_voice(phys, spl); + } +} + +END_OF_FUNCTION(reallocate_voice); + + + +/* release_voice: + * Flags that a voice is no longer going to be updated, so it can + * automatically be freed as soon as the sample finishes playing. + */ +void release_voice(int voice) +{ + _voice[voice].autokill = TRUE; +} + +END_OF_FUNCTION(release_voice); + + + +/* voice_start: + * Starts a voice playing. + */ +void voice_start(int voice) +{ + if (_voice[voice].num >= 0) + digi_driver->start_voice(_voice[voice].num); + + _voice[voice].time = retrace_count; +} + +END_OF_FUNCTION(voice_start); + + + +/* voice_stop: + * Stops a voice from playing. + */ +void voice_stop(int voice) +{ + if (_voice[voice].num >= 0) + digi_driver->stop_voice(_voice[voice].num); +} + +END_OF_FUNCTION(voice_stop); + + + +/* voice_set_priority: + * Adjusts the priority of a voice (0-255). + */ +void voice_set_priority(int voice, int priority) +{ + _voice[voice].priority = priority; +} + +END_OF_FUNCTION(voice_set_priority); + + + +/* voice_check: + * Checks whether a voice is playing, returning the sample if it is, + * or NULL if it has finished or been preempted by a different sound. + */ +SAMPLE *voice_check(int voice) +{ + if (_voice[voice].sample) { + if (_voice[voice].num < 0) + return NULL; + + if (_voice[voice].autokill) + if (voice_get_position(voice) < 0) + return NULL; + + return _voice[voice].sample; + } + else + return NULL; +} + +END_OF_FUNCTION(voice_check); + + + +/* voice_get_position: + * Returns the current play position of a voice, or -1 if that cannot + * be determined (because it has finished or been preempted by a + * different sound). + */ +int voice_get_position(int voice) +{ + if (_voice[voice].num >= 0) + return digi_driver->get_position(_voice[voice].num); + else + return -1; +} + +END_OF_FUNCTION(voice_get_position); + + + +/* voice_set_position: + * Sets the play position of a voice. + */ +void voice_set_position(int voice, int position) +{ + if (_voice[voice].num >= 0) + digi_driver->set_position(_voice[voice].num, position); +} + +END_OF_FUNCTION(voice_set_position); + + + +/* voice_set_playmode: + * Sets the loopmode of a voice. + */ +void voice_set_playmode(int voice, int playmode) +{ + if (_voice[voice].num >= 0) { + _phys_voice[_voice[voice].num].playmode = playmode; + digi_driver->loop_voice(_voice[voice].num, playmode); + + if (playmode & PLAYMODE_BACKWARD) + digi_driver->set_position(_voice[voice].num, _voice[voice].sample->len-1); + } +} + +END_OF_FUNCTION(voice_set_playmode); + + + +/* voice_get_volume: + * Returns the current volume of a voice, or -1 if that cannot + * be determined (because it has finished or been preempted by a + * different sound). + */ +int voice_get_volume(int voice) +{ + int vol; + + if (_voice[voice].num >= 0) + vol = digi_driver->get_volume(_voice[voice].num); + else + vol = -1; + + if ((vol >= 0) && (_digi_volume >= 0)) { + if (_digi_volume > 0) + vol = MID(0, (vol * 255) / _digi_volume, 255); + else + vol = 0; + } + + return vol; +} + +END_OF_FUNCTION(voice_get_volume); + + + +/* voice_set_volume: + * Sets the current volume of a voice. + */ +void voice_set_volume(int voice, int volume) +{ + if (_digi_volume >= 0) + volume = (volume * _digi_volume) / 255; + + if (_voice[voice].num >= 0) { + _phys_voice[_voice[voice].num].vol = volume << 12; + _phys_voice[_voice[voice].num].dvol = 0; + + digi_driver->set_volume(_voice[voice].num, volume); + } +} + +END_OF_FUNCTION(voice_set_volume); + + + +/* voice_ramp_volume: + * Begins a volume ramp operation. + */ +void voice_ramp_volume(int voice, int time, int endvol) +{ + if (_digi_volume >= 0) + endvol = (endvol * _digi_volume) / 255; + + if (_voice[voice].num >= 0) { + if (digi_driver->ramp_volume) { + digi_driver->ramp_volume(_voice[voice].num, time, endvol); + } + else { + int d = (endvol << 12) - _phys_voice[_voice[voice].num].vol; + time = MAX(time * SWEEP_FREQ / 1000, 1); + _phys_voice[_voice[voice].num].target_vol = endvol << 12; + _phys_voice[_voice[voice].num].dvol = d / time; + } + } +} + +END_OF_FUNCTION(voice_ramp_volume); + + + +/* voice_stop_volumeramp: + * Ends a volume ramp operation. + */ +void voice_stop_volumeramp(int voice) +{ + if (_voice[voice].num >= 0) { + _phys_voice[_voice[voice].num].dvol = 0; + + if (digi_driver->stop_volume_ramp) + digi_driver->stop_volume_ramp(_voice[voice].num); + } +} + +END_OF_FUNCTION(voice_stop_volumeramp); + + + +/* voice_get_frequency: + * Returns the current frequency of a voice, or -1 if that cannot + * be determined (because it has finished or been preempted by a + * different sound). + */ +int voice_get_frequency(int voice) +{ + if (_voice[voice].num >= 0) + return digi_driver->get_frequency(_voice[voice].num); + else + return -1; +} + +END_OF_FUNCTION(voice_get_frequency); + + + +/* voice_set_frequency: + * Sets the pitch of a voice. + */ +void voice_set_frequency(int voice, int frequency) +{ + if (_voice[voice].num >= 0) { + _phys_voice[_voice[voice].num].freq = frequency << 12; + _phys_voice[_voice[voice].num].dfreq = 0; + + digi_driver->set_frequency(_voice[voice].num, frequency); + } +} + +END_OF_FUNCTION(voice_set_frequency); + + + +/* voice_sweep_frequency: + * Begins a frequency sweep (glissando) operation. + */ +void voice_sweep_frequency(int voice, int time, int endfreq) +{ + if (_voice[voice].num >= 0) { + if (digi_driver->sweep_frequency) { + digi_driver->sweep_frequency(_voice[voice].num, time, endfreq); + } + else { + int d = (endfreq << 12) - _phys_voice[_voice[voice].num].freq; + time = MAX(time * SWEEP_FREQ / 1000, 1); + _phys_voice[_voice[voice].num].target_freq = endfreq << 12; + _phys_voice[_voice[voice].num].dfreq = d / time; + } + } +} + +END_OF_FUNCTION(voice_sweep_frequency); + + + +/* voice_stop_frequency_sweep: + * Ends a frequency sweep. + */ +void voice_stop_frequency_sweep(int voice) +{ + if (_voice[voice].num >= 0) { + _phys_voice[_voice[voice].num].dfreq = 0; + + if (digi_driver->stop_frequency_sweep) + digi_driver->stop_frequency_sweep(_voice[voice].num); + } +} + +END_OF_FUNCTION(voice_stop_frequency_sweep); + + + +/* voice_get_pan: + * Returns the current pan position of a voice, or -1 if that cannot + * be determined (because it has finished or been preempted by a + * different sound). + */ +int voice_get_pan(int voice) +{ + int pan; + + if (_voice[voice].num >= 0) + pan = digi_driver->get_pan(_voice[voice].num); + else + pan = -1; + + if ((pan >= 0) && (_flip_pan)) + pan = 255 - pan; + + return pan; +} + +END_OF_FUNCTION(voice_get_pan); + + + +/* voice_set_pan: + * Sets the pan position of a voice. + */ +void voice_set_pan(int voice, int pan) +{ + if (_flip_pan) + pan = 255 - pan; + + if (_voice[voice].num >= 0) { + _phys_voice[_voice[voice].num].pan = pan << 12; + _phys_voice[_voice[voice].num].dpan = 0; + + digi_driver->set_pan(_voice[voice].num, pan); + } +} + +END_OF_FUNCTION(voice_set_pan); + + + +/* voice_sweep_pan: + * Begins a pan sweep (left <-> right movement) operation. + */ +void voice_sweep_pan(int voice, int time, int endpan) +{ + if (_flip_pan) + endpan = 255 - endpan; + + if (_voice[voice].num >= 0) { + if (digi_driver->sweep_pan) { + digi_driver->sweep_pan(_voice[voice].num, time, endpan); + } + else { + int d = (endpan << 12) - _phys_voice[_voice[voice].num].pan; + time = MAX(time * SWEEP_FREQ / 1000, 1); + _phys_voice[_voice[voice].num].target_pan = endpan << 12; + _phys_voice[_voice[voice].num].dpan = d / time; + } + } +} + +END_OF_FUNCTION(voice_sweep_pan); + + + +/* voice_stop_pan_sweep: + * Ends a pan sweep. + */ +void voice_stop_pan_sweep(int voice) +{ + if (_voice[voice].num >= 0) { + _phys_voice[_voice[voice].num].dpan = 0; + + if (digi_driver->stop_pan_sweep) + digi_driver->stop_pan_sweep(_voice[voice].num); + } +} + +END_OF_FUNCTION(voice_stop_pan_sweep); + + + +/* voice_set_echo: + * Sets the echo parameters of a voice. + */ +void voice_set_echo(int voice, int strength, int delay) +{ + if ((_voice[voice].num >= 0) && (digi_driver->set_echo)) + digi_driver->set_echo(_voice[voice].num, strength, delay); +} + +END_OF_FUNCTION(voice_set_echo); + + + +/* voice_set_tremolo: + * Sets the tremolo parameters of a voice. + */ +void voice_set_tremolo(int voice, int rate, int depth) +{ + if ((_voice[voice].num >= 0) && (digi_driver->set_tremolo)) + digi_driver->set_tremolo(_voice[voice].num, rate, depth); +} + +END_OF_FUNCTION(voice_set_tremolo); + + + +/* voice_set_vibrato: + * Sets the vibrato parameters of a voice. + */ +void voice_set_vibrato(int voice, int rate, int depth) +{ + if ((_voice[voice].num >= 0) && (digi_driver->set_vibrato)) + digi_driver->set_vibrato(_voice[voice].num, rate, depth); +} + +END_OF_FUNCTION(voice_set_vibrato); + + + +/* update_sweeps: + * Timer callback routine used to implement volume/frequency/pan sweep + * effects, for those drivers that can't do them directly. + */ +static void update_sweeps() +{ + int phys_voices, i; + + phys_voices = digi_driver->voices; + if (midi_driver->max_voices < 0) + phys_voices += midi_driver->voices; + + for (i=0; i= 0) { + /* update volume ramp */ + if ((!digi_driver->ramp_volume) && (_phys_voice[i].dvol)) { + _phys_voice[i].vol += _phys_voice[i].dvol; + + if (((_phys_voice[i].dvol > 0) && (_phys_voice[i].vol >= _phys_voice[i].target_vol)) || + ((_phys_voice[i].dvol < 0) && (_phys_voice[i].vol <= _phys_voice[i].target_vol))) { + _phys_voice[i].vol = _phys_voice[i].target_vol; + _phys_voice[i].dvol = 0; + } + + digi_driver->set_volume(i, _phys_voice[i].vol >> 12); + } + + /* update frequency sweep */ + if ((!digi_driver->sweep_frequency) && (_phys_voice[i].dfreq)) { + _phys_voice[i].freq += _phys_voice[i].dfreq; + + if (((_phys_voice[i].dfreq > 0) && (_phys_voice[i].freq >= _phys_voice[i].target_freq)) || + ((_phys_voice[i].dfreq < 0) && (_phys_voice[i].freq <= _phys_voice[i].target_freq))) { + _phys_voice[i].freq = _phys_voice[i].target_freq; + _phys_voice[i].dfreq = 0; + } + + digi_driver->set_frequency(i, _phys_voice[i].freq >> 12); + } + + /* update pan sweep */ + if ((!digi_driver->sweep_pan) && (_phys_voice[i].dpan)) { + _phys_voice[i].pan += _phys_voice[i].dpan; + + if (((_phys_voice[i].dpan > 0) && (_phys_voice[i].pan >= _phys_voice[i].target_pan)) || + ((_phys_voice[i].dpan < 0) && (_phys_voice[i].pan <= _phys_voice[i].target_pan))) { + _phys_voice[i].pan = _phys_voice[i].target_pan; + _phys_voice[i].dpan = 0; + } + + digi_driver->set_pan(i, _phys_voice[i].pan >> 12); + } + } + } +} + +static END_OF_FUNCTION(update_sweeps); + + + +/* sound_lock_mem: + * Locks memory used by the functions in this file. + */ +static void sound_lock_mem() +{ + LOCK_VARIABLE(digi_none); + LOCK_VARIABLE(midi_none); + LOCK_VARIABLE(digi_card); + LOCK_VARIABLE(midi_card); + LOCK_VARIABLE(digi_driver); + LOCK_VARIABLE(midi_driver); + LOCK_VARIABLE(_voice); + LOCK_VARIABLE(_phys_voice); + LOCK_VARIABLE(_digi_volume); + LOCK_VARIABLE(_midi_volume); + LOCK_VARIABLE(_flip_pan); + LOCK_FUNCTION(_dummy_detect); + LOCK_FUNCTION(play_sample); + LOCK_FUNCTION(adjust_sample); + LOCK_FUNCTION(stop_sample); + LOCK_FUNCTION(allocate_voice); + LOCK_FUNCTION(deallocate_voice); + LOCK_FUNCTION(reallocate_voice); + LOCK_FUNCTION(voice_start); + LOCK_FUNCTION(voice_stop); + LOCK_FUNCTION(voice_set_priority); + LOCK_FUNCTION(voice_check); + LOCK_FUNCTION(voice_get_position); + LOCK_FUNCTION(voice_set_position); + LOCK_FUNCTION(voice_set_playmode); + LOCK_FUNCTION(voice_get_volume); + LOCK_FUNCTION(voice_set_volume); + LOCK_FUNCTION(voice_ramp_volume); + LOCK_FUNCTION(voice_stop_volumeramp); + LOCK_FUNCTION(voice_get_frequency); + LOCK_FUNCTION(voice_set_frequency); + LOCK_FUNCTION(voice_sweep_frequency); + LOCK_FUNCTION(voice_stop_frequency_sweep); + LOCK_FUNCTION(voice_get_pan); + LOCK_FUNCTION(voice_set_pan); + LOCK_FUNCTION(voice_sweep_pan); + LOCK_FUNCTION(voice_stop_pan_sweep); + LOCK_FUNCTION(voice_set_echo); + LOCK_FUNCTION(voice_set_tremolo); + LOCK_FUNCTION(voice_set_vibrato); + LOCK_FUNCTION(update_sweeps); +} + diff --git a/arch/dos/bak/ipx.c b/arch/dos/bak/ipx.c new file mode 100644 index 00000000..b482bda7 --- /dev/null +++ b/arch/dos/bak/ipx.c @@ -0,0 +1,936 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/arch/dos/bak/ipx.c,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:15 $ + * + * Routines for IPX communications. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:00:03 donut + * Import of d1x 1.37 source. + * + * Revision 2.10 1995/03/29 17:27:55 john + * Added code to not duplicate broadcasts. + * + * Revision 2.9 1995/03/29 15:32:07 john + * NEatened. + * + * Revision 2.8 1995/03/29 15:07:31 john + * Added network support. + * + * Revision 2.7 1995/03/29 11:22:27 john + * Added broadcasting over a net. + * + * Revision 2.6 1995/03/28 20:05:03 john + * Took away alternate server stuff. + * + * Revision 2.5 1995/03/23 19:14:29 john + * Added better MAX_USERS message. + * + * Revision 2.4 1995/03/23 19:00:02 john + * Added user list capabitly. + * + * Revision 2.3 1995/03/23 12:27:05 john + * Move IPX into bios lib. + * + * Revision 2.2 1995/03/22 19:08:15 john + * Added code to fix sending packets over router... now + * we just need to make broadcasts go over router!! + * + * Revision 2.1 1995/03/21 08:40:16 john + * Ifdef'd out the NETWORK code. + * + * Revision 2.0 1995/02/27 11:30:45 john + * New version 2.0, which has no anonymous unions, builds with + * Watcom 10.0, and doesn't require parsing BITMAPS.TBL. + * + * Revision 1.31 1995/02/16 17:35:03 john + * Added code to allow dynamic socket changing. + * + * Revision 1.30 1995/02/01 21:03:45 john + * Lintified. + * + * Revision 1.29 1995/01/22 14:31:05 john + * Added key.h + * + * Revision 1.28 1995/01/22 14:29:26 john + * Added code to bypass broadcast messages. + * + * Revision 1.27 1995/01/03 13:46:16 john + * Added code that should make ipx work over different servers, + * but ifdef'd it out with SHAREWARE in ipx.c. I haven't tested + * this, and I hope it doesn't introduce net bugs. + * + * Revision 1.26 1994/12/14 11:54:37 rob + * Reduce # of ipx packets. + * + * Revision 1.25 1994/12/11 00:43:28 john + * Locked down DOS ipx buffers... probably not necessary, tho. + * + * Revision 1.24 1994/12/08 15:49:58 rob + * Bumped up the # of ipx packets. + * + * Revision 1.23 1994/12/04 15:23:54 rob + * Reduced packet # constants. + * + * Revision 1.22 1994/11/27 23:12:39 matt + * Made changes for new mprintf calling convention + * + * Revision 1.21 1994/11/19 15:15:19 mike + * remove unused code and data + * + * Revision 1.20 1994/11/10 11:06:07 rob + * Raised number of ipx packets to 64 and buffers to 128 (for 8-way games) + * Removed (commented out) all the spx support stuff. + * + * Revision 1.19 1994/11/07 17:50:12 rob + * Bumped up max_packets and ipx_num_packets to double their previous + * values. + * + * Revision 1.18 1994/11/07 15:39:01 rob + * Removed temporary hacked ipx_send_object function. + * Replaced with a more general thing. + * + * Revision 1.17 1994/11/05 16:08:40 rob + * Made a change necessary for object syncing on rejoin. + * + * Revision 1.16 1994/11/01 15:57:12 rob + * Added support for SPX sockets for critical messages. + * + * Revision 1.15 1994/10/31 19:21:01 rob + * Added a routine for sending objects via ipx. Its a hack and shoukld + * be replaced by something more general time permitting. + * + * Revision 1.14 1994/10/20 14:57:42 john + * Some test stuff. + * + * Revision 1.13 1994/10/20 11:22:45 john + * Tweaked the number of waiting packets. Added code to print + * total packets missed, and to limit the packet send rate to + * 10 packets per second unless firing. + * + * Revision 1.12 1994/10/03 20:50:11 john + * Started adding sound pause functions. + * + * Revision 1.11 1994/09/15 08:54:24 mike + * comment out a mprintf. + * + * Revision 1.10 1994/09/12 19:38:20 john + * Made some stuff that prints to the DOS screen go to the + * mono instead, since it really is debugging info. + * + * Revision 1.9 1994/09/07 13:32:03 john + * Made ipx_close explicitly close the socket we were using, + * because it seems that VLM's don't automatically close them + * like the older NETX stuff did (Going from Novell 3.11 driver + * to 3.12 anyway). + * + * Revision 1.8 1994/09/06 19:29:20 john + * Added trial version of rejoin function. + * + * Revision 1.7 1994/08/09 19:31:50 john + * Networking changes. + * + * Revision 1.6 1994/08/05 16:11:41 john + * Psuedo working version of networking. + * + * Revision 1.5 1994/08/04 19:17:21 john + * Inbetween version of network stuff. + * + * Revision 1.4 1994/07/29 16:08:57 john + * *** empty log message *** + * + * Revision 1.3 1994/07/25 12:33:31 john + * Network "pinging" in. + * + * Revision 1.2 1994/07/20 15:58:28 john + * First installment of ipx stuff. + * + * Revision 1.1 1994/07/19 15:42:00 john + * Initial revision + * + * + */ + +#ifdef RCS +static char rcsid[] = "$Id: ipx.c,v 1.1.1.1 2001-01-19 03:30:15 bradleyb Exp $"; +#endif + +#ifdef __GNUC__ +#define _BORLAND_DOS_REGS 1 +#define far +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "types.h" +#include "timer.h" +#include "ipx.h" +#include "error.h" +#include "u_dpmi.h" +#include "key.h" + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; + +typedef struct local_address { + ubyte address[6]; +} __pack__ local_address; + +typedef struct net_address { + BYTE network_id[4]; + local_address node_id; + WORD socket_id; +} __pack__ net_address; + +typedef struct ipx_header { + WORD checksum; + WORD length; + BYTE transport_control; + BYTE packet_type; + net_address destination; + net_address source; +} __pack__ ipx_header; + +typedef struct ecb_header { + WORD link[2]; + WORD esr_address[2]; + BYTE in_use; + BYTE completion_code; + WORD socket_id; + BYTE ipx_reserved[14]; + WORD connection_id; + local_address immediate_address; + WORD fragment_count; + WORD fragment_pointer[2]; + WORD fragment_size; +} __pack__ ecb_header; + +typedef struct packet_data { + int packetnum; + byte data[IPX_MAX_DATA_SIZE]; +} __pack__ packet_data; + +typedef struct ipx_packet { + ecb_header ecb; + ipx_header ipx; + packet_data pd; +} __pack__ ipx_packet; + +typedef struct user_address { + ubyte network[4]; + ubyte node[6]; + ubyte address[6]; +} __pack__ user_address; + +#define MAX_USERS 64 +int Ipx_num_users = 0; +user_address Ipx_users[MAX_USERS]; + +#define MAX_NETWORKS 64 +int Ipx_num_networks = 0; +uint Ipx_networks[MAX_NETWORKS]; + +int ipx_packetnum = 0; + +#define MAX_PACKETS 64 + +static packet_data packet_buffers[MAX_PACKETS]; +static short packet_free_list[MAX_PACKETS]; +static int num_packets = 0; +static int largest_packet_index = 0; +static short packet_size[MAX_PACKETS]; + +//added on 10/29/98 by Kevin Bently to add ipx stuff +WORD ipx_num_outgoing_packets = 8; +ipx_packet * outpackets; +//end this section addition - Kevin Bently + +WORD ipx_socket=0; +ubyte ipx_installed=0; +WORD ipx_vector_segment; +WORD ipx_vector_offset; +ubyte ipx_socket_life = 0; // 0=closed at prog termination, 0xff=closed when requested. +DWORD ipx_network = 0; +local_address ipx_my_node; +WORD ipx_num_packets=32; // 32 Ipx packets +ipx_packet * packets; +int neterrors = 0; +ushort ipx_packets_selector; + +ecb_header * last_ecb=NULL; +int lastlen=0; + +void got_new_packet( ecb_header * ecb ); +void ipx_listen_for_packet(ecb_header * ecb ); + +void free_packet( int id ) +{ + packet_buffers[id].packetnum = -1; + packet_free_list[ --num_packets ] = id; + if (largest_packet_index==id) + while ((--largest_packet_index>0) && (packet_buffers[largest_packet_index].packetnum == -1 )); +} + +int ipx_get_packet_data( ubyte * data ) +{ + int i, n, best, best_id, size; + + for (i=1; i -1 ) { + n++; + if ( best == -1 || (packet_buffers[i].packetnum ", neterrors )); + + if ( best_id < 0 ) return 0; + + size = packet_size[best_id]; + memcpy( data, packet_buffers[best_id].data, size ); + free_packet(best_id); + + return size; +} + +#ifndef __GNUC__ +unsigned int swap_short( unsigned int short ) +#pragma aux swap_short parm [eax] = "xchg al,ah"; +#else +static inline unsigned int swap_short( unsigned int sshort ) { + int __retval; + asm("xchg %%ah,%%al" : "=a" (__retval) : "a" (sshort)); + return __retval; +} +#endif + +void got_new_packet( ecb_header * ecb ) +{ + ipx_packet * p; + int id; + unsigned short datasize; + + datasize = 0; + last_ecb = ecb; + p = (ipx_packet *)ecb; + + if ( p->ecb.in_use ) { neterrors++; return; } + if ( p->ecb.completion_code ) { neterrors++; return; } + + // Error( "Recieve error %d for completion code", p->ecb.completion_code ); + + if ( memcmp( &p->ipx.source.node_id, &ipx_my_node, 6 ) ) { + datasize=swap_short(p->ipx.length); + lastlen=datasize; + datasize -= sizeof(ipx_header); + // Find slot to put packet in... + if ( datasize > 0 && datasize <= sizeof(packet_data) ) { + if ( num_packets >= MAX_PACKETS ) { + //printf( 1, "IPX: Packet buffer overrun!!!\n" ); + neterrors++; + return; + } + id = packet_free_list[ num_packets++ ]; + if (id > largest_packet_index ) largest_packet_index = id; + packet_size[id] = datasize-sizeof(int); + packet_buffers[id].packetnum = p->pd.packetnum; + if ( packet_buffers[id].packetnum < 0 ) { neterrors++; return; } + memcpy( packet_buffers[id].data, p->pd.data, packet_size[id] ); + } else { + neterrors++; return; + } + } + // Repost the ecb + p->ecb.in_use = 0; + //ipx_listen_for_packet(&p->ecb); +} + +ubyte * ipx_get_my_local_address() +{ + return ipx_my_node.address; +} + +ubyte * ipx_get_my_server_address() +{ + return (ubyte *)&ipx_network; +} + +void ipx_listen_for_packet(ecb_header * ecb ) +{ + dpmi_real_regs rregs; + ecb->in_use = 0x1d; + memset(&rregs,0,sizeof(dpmi_real_regs)); + rregs.ebx = 4; // Listen For Packet function + rregs.esi = DPMI_real_offset(ecb); + rregs.es = DPMI_real_segment(ecb); + dpmi_real_int386x( 0x7A, &rregs ); +} + +void ipx_cancel_listen_for_packet(ecb_header * ecb ) +{ + dpmi_real_regs rregs; + memset(&rregs,0,sizeof(dpmi_real_regs)); + rregs.ebx = 6; // IPX Cancel event + rregs.esi = DPMI_real_offset(ecb); + rregs.es = DPMI_real_segment(ecb); + dpmi_real_int386x( 0x7A, &rregs ); +} + + +void ipx_send_packet(ecb_header * ecb ) +{ + dpmi_real_regs rregs; + memset(&rregs,0,sizeof(dpmi_real_regs)); + rregs.ebx = 3; // Send Packet function + rregs.esi = DPMI_real_offset(ecb); + rregs.es = DPMI_real_segment(ecb); + dpmi_real_int386x( 0x7A, &rregs ); +} + +typedef struct { + ubyte network[4]; + ubyte node[6]; + ubyte local_target[6]; +} __pack__ net_xlat_info; + +void ipx_get_local_target( ubyte * server, ubyte * node, ubyte * local_target ) +{ + net_xlat_info * info; + dpmi_real_regs rregs; + + // Get dos memory for call... + info = (net_xlat_info *)dpmi_get_temp_low_buffer( sizeof(net_xlat_info) ); + assert( info != NULL ); + memcpy( info->network, server, 4 ); + memcpy( info->node, node, 6 ); + + memset(&rregs,0,sizeof(dpmi_real_regs)); + + rregs.ebx = 2; // Get Local Target + rregs.es = DPMI_real_segment(info); + rregs.esi = DPMI_real_offset(info->network); + rregs.edi = DPMI_real_offset(info->local_target); + + dpmi_real_int386x( 0x7A, &rregs ); + + // Save the local target... + memcpy( local_target, info->local_target, 6 ); +} + +void ipx_close() +{ + dpmi_real_regs rregs; + if ( ipx_installed ) { + // When using VLM's instead of NETX, the sockets don't + // seem to automatically get closed, so we must explicitly + // close them at program termination. + ipx_installed = 0; + memset(&rregs,0,sizeof(dpmi_real_regs)); + rregs.edx = ipx_socket; + rregs.ebx = 1; // Close socket + dpmi_real_int386x( 0x7A, &rregs ); + } +} + + +//--------------------------------------------------------------- +// Initializes all IPX internals. +// If socket_number==0, then opens next available socket. +// Returns: 0 if successful. +// -1 if socket already open. +// -2 if socket table full. +// -3 if IPX not installed. +// -4 if couldn't allocate low dos memory +// -5 if error with getting internetwork address + +int ipx_init( int socket_number, int show_address ) +{ + dpmi_real_regs rregs; + ubyte *ipx_real_buffer; + int i; + + atexit(ipx_close); + + ipx_packetnum = 0; + + // init packet buffers. + for (i=0; i= IPX_MAX_DATA_SIZE ) { + printf( "Data too big\n" ); + exit(1); + } + + + +//added/replaced on 10/29/98 by Kevin Bently for new ipx stuff +//-killed- // Make sure no one is already sending something +//-killed- while( packets[0].ecb.in_use ) +//-killed- { +//-killed- } +//-killed- +//-killed- if (packets[0].ecb.completion_code) { +//-killed- printf( "Send error %d for completion code\n", packets[0].ecb.completion_code ); +//-killed- //killed on 10/25/98 by Victor Rachels to fix LAN crash +//-killed- //-killed- exit(1); +//-killed- //end this section kill - Victor +//-killed- } + while(!sendpacket) + for(i=0;iipx.destination.network_id, network, 4 ); + else + memset( sendpacket->ipx.destination.network_id, 0, 4 ); + memcpy( sendpacket->ipx.destination.node_id.address, address, 6 ); + memcpy( sendpacket->ecb.immediate_address.address, immediate_address, 6 ); + sendpacket->pd.packetnum = ipx_packetnum++; + + // Fill in data to send + sendpacket->ecb.fragment_size = sizeof(ipx_header) + sizeof(int) + datasize; + + assert( datasize > 1 ); + assert( sendpacket->ecb.fragment_size <= 576 ); + + memcpy( sendpacket->pd.data, data, datasize ); + + // Send it + ipx_send_packet( &sendpacket->ecb ); + +} + +void ipx_send_broadcast_packet_data( ubyte * data, int datasize ) +{ + int i, j; + ubyte broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + ubyte local_address[6]; + + // Set to all networks besides mine + for (i=0; i= Ipx_num_networks ) { + memcpy( &Ipx_networks[Ipx_num_networks++], tmp.network, 4 ); + printf(" %02x%02x%02x%02x\n", tmp.network[0], tmp.network[1], tmp.network[2], tmp.network[3] ); + } + } else { + printf( "Too many networks in %s! (Limit of %d)\n", filename, MAX_NETWORKS ); + fclose(fp); + return; + } + } + fclose(fp); + +} + +//---typedef struct rip_entry { +//--- uint network; +//--- ushort nhops; +//--- ushort nticks; +//---} rip_entry; +//--- +//---typedef struct rip_packet { +//--- ushort operation; //1=request, 2=response +//--- rip_entry rip[50]; +//---} rip_packet; +//--- +//--- +//---void ipx_find_all_servers() +//---{ +//--- int i; +//--- rip_packet * rp; +//--- assert(ipx_installed); +//--- +//--- ipx_change_default_socket( 0x0453 ); +//--- // ipx_change_default_socket( 0x5304 ); +//--- +//--- // Make sure no one is already sending something +//--- while( packets[0].ecb.in_use ) +//--- { +//--- } +//--- +//--- if (packets[0].ecb.completion_code) { +//--- printf( "AAAA:Send error %d for completion code\n", packets[0].ecb.completion_code ); +//--- //exit(1); +//--- } +//--- +//--- rp = (rip_packet *)&packets[0].pd; +//--- +//--- // Fill in destination address +//--- { +//--- char mzero1[] = {0,0,0,1}; +//--- char mzero[] = {0,0,0,0,0,1}; +//--- char immediate[6]; +//--- //memcpy( packets[0].ipx.destination.network_id, &ipx_network, 4 ); +//--- //memcpy( packets[0].ipx.destination.node_id.address, ipx_my_node.address, 6 ); +//--- +//--- memcpy( packets[0].ipx.destination.network_id, mzero1, 4 ); +//--- memcpy( packets[0].ipx.destination.node_id.address, mzero, 6 ); +//--- +//--- memcpy( packets[0].ipx.destination.socket_id, &ipx_socket, 2 ); +//--- memcpy( packets[0].ipx.source.network_id, &ipx_network, 4 ); +//--- memcpy( packets[0].ipx.source.node_id.address, ipx_my_node.address, 6 ); +//--- memcpy( packets[0].ipx.source.socket_id, &ipx_socket, 2 ); +//--- //memcpy( packets[0].ecb.immediate_address.address, ipx_my_node.address, 6 ); +//--- //mzero1[3] = 1; +//--- //memcpy( packets[0].ipx.destination.network_id, mzero1, 4 ); +//--- //mzero[5] = 1; +//--- //memcpy( packets[0].ipx.destination.node_id.address, mzero, 6 ); +//--- //ipx_get_local_target( mzero1, mzero, immediate ); +//--- //memcpy( packets[0].ecb.immediate_address.address, mzero, 6 ); +//--- //memcpy( packets[0].ecb.immediate_address.address, immediate, 6 ); +//--- //mzero[5] = 0; +//--- } +//--- +//--- packets[0].ipx.packet_type = 1; // RIP packet +//--- +//--- // Fill in data to send +//--- packets[0].ecb.fragment_size = sizeof(ipx_header) + sizeof(rip_packet); +//--- assert( packets[0].ecb.fragment_size <= 576 ); +//--- +//--- rp->operation = 0; // Request +//--- for (i=0;i<50; i++) { +//--- rp->rip[i].network = 0xFFFFFFFF; +//--- rp->rip[i].nhops = 0; +//--- rp->rip[i].nticks = 0; +//--- } +//--- +//--- // Send it +//--- ipx_send_packet( &packets[0].ecb ); +//--- +//--- for (i=0;i<50; i++) { +//--- if ( rp->rip[i].network != 0xFFFFFFFF ) +//--- printf( "Network = %8x, Hops=%d, Ticks=%d\n", rp->rip[i].network, rp->rip[i].nhops, rp->rip[i].nticks ); +//--- } +//---} +//--- +//--- diff --git a/arch/dos/bcd.c b/arch/dos/bcd.c new file mode 100644 index 00000000..09b1ce92 --- /dev/null +++ b/arch/dos/bcd.c @@ -0,0 +1,745 @@ +/* bcd.c -- Brennan's CD-ROM Audio Playing Library + by Brennan Underwood, http://brennan.home.ml.org/ */ +//edited on 9/15/98 by Victor Rachels to stick it in d1x without extra crap + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bcd.h" + +typedef struct { + int is_audio; + int start, end, len; +} Track; + +static int mscdex_version; +static int first_drive; +static int num_tracks; +static int lowest_track, highest_track; +static int audio_length; + +static Track *tracks; + +static int dos_mem_segment, dos_mem_selector = -1; + +int _status, _error, _error_code; +char *_bcd_error = NULL; + +#define RESET_ERROR (_error = _error_code = 0) +#define ERROR_BIT (1 << 15) +#define BUSY_BIT (1 << 9) +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#pragma pack(1) + +/* I know 'typedef struct {} bleh' is a bad habit, but... */ +typedef struct { + unsigned char len __attribute__((packed)); + unsigned char unit __attribute__((packed)); + unsigned char command __attribute__((packed)); + unsigned short status __attribute__((packed)); + unsigned char reserved[8] __attribute__((packed)); +} RequestHeader; + +typedef struct { + RequestHeader request_header __attribute__((packed)); + unsigned char descriptor __attribute__((packed)); + unsigned long address __attribute__((packed)); + unsigned short len __attribute__((packed)); + unsigned short secnum __attribute__((packed)); + unsigned long ptr __attribute__((packed)); +} IOCTLI; + +typedef struct { + unsigned char control __attribute__((packed)); + unsigned char lowest __attribute__((packed)); + unsigned char highest __attribute__((packed)); + unsigned char total[4] __attribute__((packed)); +} DiskInfo; + +typedef struct { + unsigned char control __attribute__((packed)); + unsigned char track_number __attribute__((packed)); + unsigned char start[4] __attribute__((packed)); + unsigned char info __attribute__((packed)); +} TrackInfo; + +typedef struct { + RequestHeader request __attribute__((packed)); + unsigned char mode __attribute__((packed)); + unsigned long start __attribute__((packed)); + unsigned long len __attribute__((packed)); +} PlayRequest; + +typedef struct { + RequestHeader request __attribute__((packed)); +} StopRequest; + +typedef struct { + RequestHeader request __attribute__((packed)); +} ResumeRequest; + +typedef struct { + unsigned char control __attribute__((packed)); + unsigned char input0 __attribute__((packed)); + unsigned char volume0 __attribute__((packed)); + unsigned char input1 __attribute__((packed)); + unsigned char volume1 __attribute__((packed)); + unsigned char input2 __attribute__((packed)); + unsigned char volume2 __attribute__((packed)); + unsigned char input3 __attribute__((packed)); + unsigned char volume3 __attribute__((packed)); +} VolumeRequest; + +typedef struct { + unsigned char control __attribute__((packed)); + unsigned char fn __attribute__((packed)); +} LockRequest; + +typedef struct { + unsigned char control __attribute__((packed)); + unsigned char mbyte __attribute__((packed)); +} MediaChangedRequest; + +typedef struct { + unsigned char control __attribute__((packed)); + unsigned long status __attribute__((packed)); +} StatusRequest; + +typedef struct { + unsigned char control __attribute__((packed)); + unsigned char mode __attribute__((packed)); + unsigned long loc __attribute__((packed)); +} PositionRequest; + +#pragma pack() + +char *bcd_error(void) +{ + static char retstr[132]; + char *errorcodes[] = { "Write-protect violation", + "Unknown unit", + "Drive not ready", + "Unknown command", + "CRC error", + "Bad drive request structure length", + "Seek error", + "Unknown media", + "Sector not found", + "Printer out of paper: world coming to an end",/* I mean really, on a CD? */ + "Write fault", + "Read fault", + "General failure", + "Reserved", + "Reserved", + "Invalid disk change" }; + *retstr = 0; + + if (_error != 0) + { + strcat(retstr, "Device error: "); + if (_error_code < 0 || _error_code > 0xf) + strcat(retstr, "Invalid error"); + else + strcat(retstr, errorcodes[_error_code]); + strcat(retstr, " "); + } + if (_bcd_error != NULL) + { + if (*retstr) strcat(retstr, ", "); + strcat(retstr, "BCD error: "); + strcat(retstr, _bcd_error); + } + return retstr; +} + +/* DOS IOCTL w/ command block */ +static void bcd_ioctl(IOCTLI *ioctli, void *command, int len) { + int ioctli_len = sizeof(IOCTLI); + unsigned long command_address = dos_mem_segment << 4; + __dpmi_regs regs; + + memset(®s, 0, sizeof regs); + regs.x.es = (__tb >> 4) & 0xffff; + regs.x.ax = 0x1510; + regs.x.bx = __tb & 0xf; + regs.x.cx = first_drive; + ioctli->address = dos_mem_segment << 16; + ioctli->len = len; + dosmemput(ioctli, ioctli_len, __tb); /* put ioctl into dos area */ + dosmemput(command, len, command_address); /* and command too */ + if (__dpmi_int(0x2f, ®s) == -1) { + _bcd_error = "__dpmi_int() failed"; + return; + } + dosmemget(__tb, ioctli_len, ioctli); /* retrieve results */ + dosmemget(command_address, len, command); + _status = ioctli->request_header.status; + if (_status & ERROR_BIT) { + _error = TRUE; + _error_code = _status & 0xff; + } else { + _error = FALSE; + _error_code = 0; + } +} + +/* no command block */ +static void bcd_ioctl2(void *cmd, int len) { + __dpmi_regs regs; + memset(®s, 0, sizeof regs); + regs.x.es = (__tb >> 4) & 0xffff; + regs.x.ax = 0x1510; + regs.x.bx = __tb & 0xf; + regs.x.cx = first_drive; + dosmemput(cmd, len, __tb); /* put ioctl block in dos arena */ + if (__dpmi_int(0x2f, ®s) == -1) { + _bcd_error = "__dpmi_int() failed"; + return; + } + /* I hate to have no error capability for ioctl2 but the command block + doesn't necessarily have a status field */ + RESET_ERROR; +} + +static int red2hsg(char *r) { + return r[0] + r[1]*75 + r[2]*4500 - 150; +} + +int bcd_now_playing(void) { + int i, loc = bcd_audio_position(); + _bcd_error = NULL; + if (!bcd_audio_busy()) { + _bcd_error = "Audio not playing"; + return 0; + } + if (tracks == NULL && !bcd_get_audio_info()) + return 0; + for (i = lowest_track; i <= highest_track; i++) { + if (loc >= tracks[i].start && loc <= tracks[i].end) return i; + } + /* some bizarre location? */ + _bcd_error = "Head outside of bounds"; + return 0; +} + +/* handles the setup for CD-ROM audio interface */ +int bcd_open(void) { + __dpmi_regs regs; + _bcd_error = NULL; + + /* disk I/O wouldn't work anyway if you set sizeof tb this low, but... */ + if (_go32_info_block.size_of_transfer_buffer < 4096) { + _bcd_error = "Transfer buffer too small"; + return 0; + } + + memset(®s, 0, sizeof regs); + regs.x.ax = 0x1500; + regs.x.bx = 0x0; + __dpmi_int(0x2f, ®s); + if (regs.x.bx == 0) { /* abba no longer lives */ + _bcd_error = "MSCDEX not found"; + return 0; + } + + first_drive = regs.x.cx; /* use the first drive */ + + /* check for mscdex at least 2.0 */ + memset(®s, 0, sizeof regs); + regs.x.ax = 0x150C; + __dpmi_int(0x2f, ®s); + if (regs.x.bx == 0) { + _bcd_error = "MSCDEX version < 2.0"; + return 0; + } + mscdex_version = regs.x.bx; + + /* allocate 256 bytes of dos memory for the command blocks */ + if ((dos_mem_segment = __dpmi_allocate_dos_memory(16, &dos_mem_selector))<0) { + _bcd_error = "Could not allocate 256 bytes of DOS memory"; + return 0; + } + + atexit( (void(*)()) bcd_close ); + return mscdex_version; +} + +/* Shuts down CD-ROM audio interface */ +int bcd_close(void) { + _bcd_error = NULL; + if (dos_mem_selector != -1) { + __dpmi_free_dos_memory(dos_mem_selector); + dos_mem_selector = -1; + } +#ifndef STATIC_TRACKS + if (tracks) free(tracks); + tracks = NULL; +#endif + RESET_ERROR; + return 1; +} + +int bcd_open_door(void) { + IOCTLI ioctli; + char eject = 0; + _bcd_error = NULL; + memset(&ioctli, 0, sizeof ioctli); + ioctli.request_header.len = sizeof ioctli; + ioctli.request_header.command = 12; + ioctli.len = 1; + bcd_ioctl(&ioctli, &eject, sizeof eject); + if (_error) return 0; + return 1; +} + +int bcd_close_door(void) { + IOCTLI ioctli; + char closeit = 5; + _bcd_error = NULL; + memset(&ioctli, 0, sizeof ioctli); + ioctli.request_header.len = sizeof ioctli; + ioctli.request_header.command = 12; + ioctli.len = 1; + bcd_ioctl(&ioctli, &closeit, sizeof closeit); + if (_error) return 0; + return 1; +} + +int bcd_lock(int fn) { + IOCTLI ioctli; + LockRequest req; + _bcd_error = NULL; + memset(&ioctli, 0, sizeof ioctli); + memset(&req, 0, sizeof req); + ioctli.request_header.len = sizeof ioctli; + ioctli.request_header.command = 12; + ioctli.len = sizeof req; + req.control = 1; + req.fn = fn ? 1 : 0; + bcd_ioctl(&ioctli, &req, sizeof req); + if (_error) return 0; + return 1; +} + + +int bcd_disc_changed(void) { + IOCTLI ioctli; + MediaChangedRequest req; + _bcd_error = NULL; + memset(&ioctli, 0, sizeof ioctli); + memset(&req, 0, sizeof req); + ioctli.request_header.len = sizeof ioctli; + ioctli.request_header.command = 3; + ioctli.len = sizeof req; + req.control = 9; + bcd_ioctl(&ioctli, &req, sizeof req); + return req.mbyte; +} + +int bcd_reset(void) { + IOCTLI ioctli; + char reset = 2; + _bcd_error = NULL; + + memset(&ioctli, 0, sizeof ioctli); + ioctli.request_header.len = sizeof ioctli; + ioctli.request_header.command = 12; + ioctli.len = 1; + bcd_ioctl(&ioctli, &reset, sizeof reset); + if (_error) return 0; + return 1; +} + +int bcd_device_status(void) { + IOCTLI ioctli; + StatusRequest req; + _bcd_error = NULL; + memset(&ioctli, 0, sizeof ioctli); + memset(&req, 0, sizeof req); + ioctli.request_header.len = sizeof ioctli; // ok + ioctli.request_header.command = 3; + ioctli.len = sizeof req; + req.control = 6; + bcd_ioctl(&ioctli, &req, sizeof req); + return req.status; +} + +static int bcd_get_status_word(void) { + IOCTLI ioctli; + DiskInfo disk_info; + + /* get cd info as an excuse to get a look at the status word */ + memset(&disk_info, 0, sizeof disk_info); + memset(&ioctli, 0, sizeof ioctli); + + ioctli.request_header.len = 26; + ioctli.request_header.command = 3; + ioctli.len = 7; + disk_info.control = 10; + bcd_ioctl(&ioctli, &disk_info, sizeof disk_info); + return _status; +} + +int bcd_audio_busy(void) { + _bcd_error = NULL; + /* If the door is open, then the head is busy, and so the busy bit is + on. It is not, however, playing audio. */ + if (bcd_device_status() & BCD_DOOR_OPEN) + return 0; + + bcd_get_status_word(); + if (_error) return -1; + return (_status & BUSY_BIT) ? 1 : 0; +} + +int bcd_audio_position(void) { + IOCTLI ioctli; + PositionRequest req; + _bcd_error = NULL; + memset(&ioctli, 0, sizeof ioctli); + memset(&req, 0, sizeof req); + ioctli.request_header.len = sizeof ioctli; + ioctli.request_header.command = 3; + ioctli.len = sizeof req; + req.control = 1; + bcd_ioctl(&ioctli, &req, sizeof req); + return req.loc; +} + +/* Internal function to get track info */ +static void bcd_get_track_info(int n, Track *t) { + IOCTLI ioctli; + TrackInfo info; + + memset(&ioctli, 0, sizeof ioctli); + memset(&info, 0, sizeof info); + ioctli.request_header.len = sizeof ioctli; + ioctli.request_header.command = 3; + info.control = 11; + info.track_number = n; + bcd_ioctl(&ioctli, &info, sizeof info); + t->start = red2hsg(info.start); + if (info.info & 64) + t->is_audio = 0; + else + t->is_audio = 1; +} + +int bcd_get_audio_info(void) { + IOCTLI ioctli; + DiskInfo disk_info; + int i; + + + _bcd_error = NULL; + + if (tracks) free(tracks); + tracks = NULL; + + memset(&disk_info, 0, sizeof disk_info); + memset(&ioctli, 0, sizeof ioctli); + + ioctli.request_header.len = 26; + ioctli.request_header.command = 3; + ioctli.len = 7; + disk_info.control = 10; + bcd_ioctl(&ioctli, &disk_info, sizeof disk_info); + if (_error) return 0; + + lowest_track = disk_info.lowest; + highest_track = disk_info.highest; + if(lowest_track > highest_track) + lowest_track = 1; + num_tracks = highest_track - lowest_track + 1; + + /* alloc max space in order to attempt to avoid possible overrun bug */ + tracks = calloc(highest_track+1, sizeof(Track)); + if (tracks == NULL) { + _bcd_error = "Out of memory allocating tracks\n"; + return 0; + } + + /* get track starts */ + for (i = lowest_track; i <= highest_track; i++) + bcd_get_track_info(i, tracks+i); + + /* figure out track ends */ + for (i = lowest_track; i < highest_track; i++) + tracks[i].end = tracks[i+1].start-1; + audio_length = red2hsg(disk_info.total); + tracks[i].end = audio_length; + for (i = lowest_track; i <= highest_track; i++) + tracks[i].len = tracks[i].end - tracks[i].start; + + return num_tracks; +} + +int bcd_get_track_address(int trackno, int *start, int *len) { + _bcd_error = NULL; + //if (trackno >= num_tracks+1 || trackno <= 0) { + if (trackno < lowest_track || trackno > highest_track) { + _bcd_error = "Track out of range"; + *start = *len = 0; + return 0; + } + *start = tracks[trackno].start; + *len = tracks[trackno].len; + return 1; +} + +int bcd_track_is_audio(int trackno) { + //if (trackno >= num_tracks+1 || trackno <= 0) { + if (trackno < lowest_track || trackno > highest_track) { + _bcd_error = "Track out of range"; + return 0; + } + return tracks[trackno].is_audio; +} + +int bcd_set_volume(int volume) { + IOCTLI ioctli; + VolumeRequest v; + + _bcd_error = NULL; + if (volume > 255) volume = 255; + else if (volume < 0) volume = 0; + memset(&ioctli, 0, sizeof ioctli); + ioctli.request_header.len = sizeof ioctli; + ioctli.request_header.command = 12; + ioctli.len = sizeof v; + v.control = 3; + v.volume0 = volume; + v.input0 = 0; + v.volume1 = volume; + v.input1 = 1; + v.volume2 = volume; + v.input2 = 2; + v.volume3 = volume; + v.input3 = 3; + + bcd_ioctl(&ioctli, &v, sizeof v); + if (_error) return 0; + return 1; +} + +int bcd_play(int location, int frames) { + PlayRequest cmd; + memset(&cmd, 0, sizeof cmd); + + _bcd_error = NULL; + /* the following should be in user code, but it'll fail otherwise */ + if (bcd_audio_busy()) + bcd_stop(); + + cmd.request.len = sizeof cmd; + cmd.request.command = 132; + cmd.start = location; + cmd.len = frames; + bcd_ioctl2(&cmd, sizeof cmd); + if (_error) return 0; + return 1; +} + +int bcd_play_track(int *trackno) { + _bcd_error = NULL; + if (!bcd_get_audio_info()) return 0; + + if (*trackno < lowest_track) + *trackno = highest_track; + else if (*trackno > highest_track) + *trackno = lowest_track; + + if (! tracks[*trackno].is_audio) + { + _bcd_error = "Not an audio track"; + return 0; + } + + return bcd_play(tracks[*trackno].start, tracks[*trackno].len); +} + +int bcd_stop(void) { + StopRequest cmd; + _bcd_error = NULL; + memset(&cmd, 0, sizeof cmd); + cmd.request.len = sizeof cmd; + cmd.request.command = 133; + bcd_ioctl2(&cmd, sizeof cmd); + if (_error) return 0; + return 1; +} + +int bcd_resume(void) { + ResumeRequest cmd; + _bcd_error = NULL; + memset(&cmd, 0, sizeof cmd); + cmd.request.len = sizeof cmd; + cmd.request.command = 136; + bcd_ioctl2(&cmd, sizeof cmd); + if (_error) return 0; + return 1; +} + +#ifdef __cplusplus +} +#endif + +#ifdef STANDALONE +static char *card(int c) { + return c == 1 ? "" : "s"; +} + +static void print_hsg(int hsg) { + int hours, minutes, seconds; + seconds = hsg / 75; + minutes = seconds / 60; + seconds %= 60; + hours = minutes / 60; + minutes %= 60; + printf("%2d:%02d:%02d", hours, minutes, seconds); +} + +static void print_binary(int v, int len) { + for (;len;len--) + printf("%d", (v & (1 << len)) ? 1 : 0); +} + +int main(int argc, char *argv[]) { + int i, n1, n2, t; + + if (!bcd_open()) { + fprintf(stderr, "Couldn't open CD-ROM drive. %s\n", bcd_error()); + exit(0); + } + + for (i = 1; i < argc; i++) { + if (*argv[i] == '-') strcpy(argv[i], argv[i]+1); + if (!strcmp(argv[i], "open") || !strcmp(argv[i], "eject")) { + bcd_open_door(); + } else if (!strcmp(argv[i], "close")) { + bcd_close_door(); + } else if (!strcmp(argv[i], "sleep")) { + if (++i >= argc) break; + sleep(atoi(argv[i])); + } else if (!strcmp(argv[i], "list")) { + int nd = 0, na = 0, audio_time = 0; + if (!bcd_get_audio_info()) { + printf("Error getting audio info\n"); + } else if (lowest_track == 0) { + printf("No audio tracks\n"); + } else { + for (t = lowest_track; t <= highest_track; t++) { + printf("Track %2d: ", t); + print_hsg(tracks[t].start); + printf(" -> "); + print_hsg(tracks[t].end); + printf(" ("); + print_hsg(tracks[t].len); + if (tracks[t].is_audio) { + na++; + printf(") audio"); + audio_time += tracks[t].len; + } else { + nd++; + printf(") data "); + } + printf(" (HSG: %06d->%06d)\n", tracks[t].start, tracks[t].end); + } + printf("%d audio track%s, %d data track%s\n", na, card(na), nd, card(nd)); + if (audio_time) { + printf("Audio time: "); + print_hsg(audio_time); + printf("\n"); + } + } + } else if (!strcmp(argv[i], "lock")) { + bcd_lock(1); + } else if (!strcmp(argv[i], "pladdr")) { + if (++i >= argc) break; + n1 = atoi(argv[i]); + if (++i >= argc) break; + n2 = atoi(argv[i]); + printf("Playing frame %d to frame %d\n", n1, n2); + bcd_play(n1, n2-n1); + } else if (!strcmp(argv[i], "play")) { + if (++i >= argc) break; + if (bcd_audio_busy()) { + bcd_stop(); + delay(1000); + } + n1 = atoi(argv[i]); + printf("Playing track %d\n", n1); + bcd_play_track(n1); + } else if (!strcmp(argv[i], "reset")) { + bcd_reset(); + } else if (!strcmp(argv[i], "resume")) { + bcd_resume(); + } else if (!strcmp(argv[i], "status")) { + int s; + s = bcd_device_status(); + printf("MSCDEX version %d.%d\n", mscdex_version >> 8, + mscdex_version & 0xff); + printf("Device status word '"); + print_binary(s, 16); + printf("'\nDoor is %sopen\n", s & BCD_DOOR_OPEN ? "" : "not "); + printf("Door is %slocked\n", s & BCD_DOOR_UNLOCKED ? "not " : ""); + printf("Audio is %sbusy\n", bcd_audio_busy() ? "" : "not "); + s = bcd_disc_changed(); + if (s == BCD_DISC_UNKNOWN) printf("Media change status unknown\n"); + else printf("Media has %schanged\n", + (s == BCD_DISC_CHANGED) ? "" : "not "); + } else if (!strcmp(argv[i], "stop")) { + bcd_stop(); + } else if (!strcmp(argv[i], "unlock")) { + bcd_lock(0); + } else if (!strcmp(argv[i], "volume")) { + bcd_set_volume(atoi(argv[++i])); + } else if (!strcmp(argv[i], "wait")) { + while (bcd_audio_busy()) { + int n = bcd_now_playing(); + if (n == 0) break; + printf("%2d: ", n); + print_hsg(bcd_audio_position() - tracks[n].start); + printf("\r"); + fflush(stdout); + delay(100); + if (kbhit() && getch() == 27) break; + } + printf("\n"); + } else if (!strcmp(argv[i], "help") || !strcmp(argv[i], "usage") || + !strcmp(argv[i], "?") || !strcmp(argv[i], "/?") ) { + printf("BCD version %x.%x\n" \ + "Usage: BCD {commands}\n" \ + "Valid commands:\n" \ + "\tclose - close door/tray\n" \ + "\tdelay {n} - delay {n} seconds\n" \ + "\tlist - list track info\n" \ + "\tlock - lock door/tray\n" \ + "\topen - open door/tray\n" \ + "\tpladdr {n1} {n2}- play frame {n1} to {n2}\n" \ + "\tplay {n} - play track {n}\n" \ + "\treset - reset the drive\n" \ + "\tresume - resume from last stop\n" \ + "\tstatus - show drive status\n" \ + "\tstop - stop audio playback\n" \ + "\tunlock - unlock door/tray\n" \ + "\tvolume {n} - set volume to {n} where 0 <= {n} <= 255\n", + BCD_VERSION >> 8, BCD_VERSION & 0xff); + } else + printf("Unknown command '%s'\n", argv[i]); + if (_error || _bcd_error) printf("%s\n", bcd_error()); + } + bcd_close(); + exit(0); +} +#endif diff --git a/arch/dos/comm/commlib.c b/arch/dos/comm/commlib.c new file mode 100644 index 00000000..0b7181b6 --- /dev/null +++ b/arch/dos/comm/commlib.c @@ -0,0 +1,300 @@ +#include +#include +#include +#include "fix.h" +#include "timer.h" +#include "mono.h" +#include "commlib.h" + +#define F_1_1000 (F1_0/1000) // 1/1000 + +struct portparam { int base,irq; }; +struct portparam portparams[4] = {{0x3f8, 4}, {0x2f8, 3}, {0x3e8, 4}, {0x2e8, 3}}; + +/* return Data Carrier Detect status */ +int comm_get_dcd(comm_port *port) { + return (inportb(port->MSR) & MSR_DCD) != 0; +} + +void comm_printf(PORT *port, char *msg, ...) { + char buf[1024]; + va_list vp; + + va_start(vp, msg); + vsprintf(buf, msg, vp); + va_end(vp); +mprintf((0, "comm_printf: writing \"%s\"\n", buf)); + WriteBuffer(port, buf, strlen(buf)); +} + +PORT * PortOpenGreenleafFast(int port, int baud, char parity, int databits, int stopbits) +{ + PORT *com; + static int did_init = 0; + + if (!did_init) { + dzcomm_init(); + did_init = 1; + } + + if (!(com = comm_port_init(port))) { + mprintf((1,"comm_port_init: %s\n", szDZCommErr)); + return NULL; + } + com->nBaud = baud; + com->nPort = portparams[port].base; + com->nIRQ = portparams[port].irq; + switch (parity) { + case 'N': com->nParity = NO_PARITY; break; + case 'E': com->nParity = EVEN_PARITY; break; + case 'O': com->nParity = ODD_PARITY; break; + } + switch (databits) { + case 5: com->nData = BITS_5; break; + case 6: com->nData = BITS_6; break; + case 7: com->nData = BITS_7; break; + case 8: com->nData = BITS_8; break; + } + switch (stopbits) { + case 1: com->nStop = STOP_1; break; + case 2: com->nStop = STOP_2; break; + } + com->control_type = NO_CONTROL; + if (!comm_port_install_handler(com)) { + mprintf((1,"comm_port_install: %s\n", szDZCommErr)); + comm_port_delete(com); + return NULL; + } + return com; +} + +void SetDtr(PORT *port,int state) +{ + return; +} + +void SetRts(PORT *port,int state) +{ + return; +} + +void UseRtsCts(PORT *port,int state) +{ + #if 0 /* disabled for now */ + if (state && port->control_type != RTS_CTS) { + port->cts=CTS_ON; + port->rts=RTS_ON; + if (!queue_empty(port->OutBuf)) + outportb(port->MCR,inportb(port->MCR)|0x02); //setting RTS + port->control_type = RTS_CTS; + } else if (!state && port->control_type == RTS_CTS) { + port->control_type = NO_CONTROL; + if (!queue_empty(port->OutBuf)) + interrupt_on(port, THREINT); + } + #endif + return; +} + +void WriteChar(PORT *port, char ch) +{ + //mprintf((0, "(%d,%d)", port->OutBuf->head, port->OutBuf->tail)); + //mprintf((0, ">%02x ", (unsigned char)ch)); + comm_port_out(port, ch); + return; +} + +void ClearRXBuffer(PORT *port) +{ + queue_reset(port->InBuf); +} + +int ReadBufferTimed(PORT *port, char *buf, int length, int timeout) +{ + fix stop = timer_get_fixed_seconds() + timeout * F_1_1000; + int c; + + if (!length) + return 1; // ok + while (stop >= timer_get_fixed_seconds()) { + if ((c = comm_port_test(port)) >= 0) { + mprintf((0, "<%02x ", c)); + *(buf++) = c; + if (!(--length)) + return 1; // ok + } + + } + return 0; // timeout +} + +int Change8259Priority(int irq) +{ + return ASSUCCESS; +} + +int FastSetPortHardware(int port, int IRQ, int baseaddr) +{ + portparams[port].irq = IRQ; + portparams[port].base = baseaddr; + return 0; +} + +int FastGetPortHardware(int port, int *IRQ, int *baseaddr) +{ + *IRQ = portparams[port].irq; + *baseaddr = portparams[port].base; + return 0; +} + +void FastSet16550TriggerLevel(int level) +{ + return; +} +void FastSet16550UseTXFifos(int on) +{ + return; +} + +void FastSavePortParameters(int port) +{ +} + +int PortClose(PORT *port) +{ + comm_port_delete(port); + return 0; +} + +void FastRestorePortParameters(int port) +{ +} + +int GetCd(PORT *port) +{ + return comm_get_dcd(port); +} + +int ReadCharTimed(PORT *port, int timeout) +{ + fix stop = timer_get_fixed_seconds() + timeout * F_1_1000; + int c = -1; + + while (stop >= timer_get_fixed_seconds() && (c = comm_port_test(port)) < 0) + ; + if (c >= 0) + mprintf((0, "<%02x ", c)); + return c; +} + +int ReadChar(PORT *port) +{ + int c = comm_port_test(port); + //if (c >= 0) + // mprintf((0, "<%02x ", c)); + return c; +} + +void ClearLineStatus(PORT *port) +{ +} + +void WriteBuffer(PORT *port, char *pbuff, int len) +{ + mprintf((0, ">x%d ", len)); + while (len--) + comm_port_out(port, *(pbuff++)); +} + + +int HMInputLine(PORT *port, int timeout, char *buf, int bufsize) +{ + fix stop = timer_get_fixed_seconds() + timeout * F_1_1000; + int c; + char *p = buf; + int bufleft = bufsize; + +mprintf((1, "port->InBuf->head=%d, port->InBuf->tail=%d\n", port->InBuf->head, + port->InBuf->tail)); + while (stop >= timer_get_fixed_seconds()) { + if ((c = comm_port_test(port)) >= 0) { +mprintf((0,"got char %d (%c)", c, c >= 32 ? c : '.')); + if (c == '\n' && p > buf) { + *p = 0; + mprintf((0,"got line \"%s\"", buf)); + if (p - buf >= 2 && !strncmp(buf, "AT", 2)) { /* assume AT... response is echo */ + p = buf; + bufleft = bufsize; + } else { + *p = 0; + return 1; // ok + } + } + if (c != '\r' && c != '\n') { + if (!bufleft) + return -1; // buffer overflow + *(p++) = c; + bufleft--; + } + } + } +mprintf((0,"hminputline: timeout\n")); + return 0; // timeout +} + +void HMWaitForOK(int timeout, char *buf) +{ + /* what is this supposed to do without a port handle? */ +} + +void HMSendStringNoWait(PORT *port, char *pbuf, int a) +{ + comm_printf(port, "%s\r", pbuf); +} + +int HMSendString(PORT *port, char *msg) +{ +// char buf[80]; + + HMSendStringNoWait(port, msg, -2); +// HMInputLine(port, 5000, buf, sizeof(buf) - 1); /* 5 sec timeout */ +// if (!strncmp(buf, "OK", 2)) +// return 0; // Ok +// return -1; // Error + if(HMInputLine(port, 5000, msg, sizeof(msg) - 1) >= 0) + return 0; + return -1; +} +//added on 11/5/98 by Victor Rachels to wait less +int HMSendStringWait(PORT *port, char *msg, int wait) +{ + HMSendStringNoWait(port, msg, -2); + if(HMInputLine(port, wait, msg, sizeof(msg) - 1) >= 0) + return 0; + return -1; +} +//end this section addition - VR + +void HMReset(PORT *port) +{ +} + +void HMDial(PORT *port, char *pPhoneNum) +{ + comm_printf(port, "ATD%s\r", pPhoneNum); +} + +void HMAnswer(PORT *port) +{ + comm_printf(port, "ATA\r"); +} + +void ClearTXBuffer(PORT *port) +{ + queue_reset(port->OutBuf); +} + +int GetLineStatus(PORT *port) +{ + return 0; +} diff --git a/arch/dos/comm/dzcomm.c b/arch/dos/comm/dzcomm.c new file mode 100644 index 00000000..d3924496 --- /dev/null +++ b/arch/dos/comm/dzcomm.c @@ -0,0 +1,889 @@ +/* + * DZcomm : serial communication add-on for Allegro. + * version : 0.6 + * Copyright (c) 1997 Dim Zegebart, Moscow Russia. + * zager@post.comstar.ru + * file : dzcomm.c + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "dzcomm.h" +#include "allegro.h" + +typedef unsigned int uint; +typedef unsigned short int usint; +typedef unsigned char byte; + +#define com_(N) comm_port *com##N + +com_(1); +com_(2); +com_(3); +com_(4); +com_(5); +com_(6); +com_(7); +com_(8); + +#define com_wrapper_(N) static int com##N##_wrapper(void) \ + { DISABLE(); /* adb -- why this? */ \ + dz_comm_port_interrupt_handler(com##N##); \ + return(0); \ + } \ + END_OF_FUNCTION(com##N##_wrapper); + +com_wrapper_(1); +com_wrapper_(2); +com_wrapper_(3); +com_wrapper_(4); +com_wrapper_(5); +com_wrapper_(6); +com_wrapper_(7); +com_wrapper_(8); + +static comm_port *irq_bot_com_port[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +static int (*com_wrapper[8])(); +static comm_port **com_port[8]; + +char szDZCommErr[50]; +inline void dz_make_comm_err(char *szErr) {strcpy(szDZCommErr,szErr);} +//comm port functions +static inline void comm_port_rdr(comm_port *port); +static inline void comm_port_trx(comm_port *port); +static inline void interrupt_on(comm_port *port,byte _interrupt_); +static inline void interrupt_off(comm_port *port,byte _interrupt_); +extern void lock_queue_functions(void); +void comm_port_fifo_init(comm_port *port); +inline void comm_port_rtmout(comm_port *port); +void comm_port_uninstall(comm_port *port); + +//const byte THREOFF=0xfd; +const byte THREINT=0x02; +const byte RDAINT=0x04; + +//-------------------------- PRINT BIN -------------------------- + +void print_bin_s(int c,char *s) +{ int i,j; + int mask=0x01; + sprintf (s,"%c : ",c); + for (i=0;i<4;i++) + { for(j=0;j<8;j++) + if (c&(mask<<(j+i*8))) strcat(s,"1"); + else strcat(s,"0"); + strcat(s,"."); + } +} + +//------------------------- INTERRUPT ON ----------------------------- + +static inline void interrupt_on(comm_port *port,byte _interrupt_) +{ byte i; + i=inportb(port->IER); + if (!(i&_interrupt_)) outportb(port->IER,i|_interrupt_); +} +END_OF_FUNCTION(interrupt_on); + +//------------------------- INTERRUPT OFF ----------------------------- + +static inline void interrupt_off(comm_port *port,byte _interrupt_) +{ byte i; + i=inportb(port->IER); + if (i&_interrupt_) outportb(port->IER,i&~_interrupt_); +} +END_OF_FUNCTION(interrupt_off); + +//------------------------- COMM PORT INIT -------------------------- + +comm_port *comm_port_init(comm com) +{ comm_port *port=(comm_port*)malloc(sizeof(comm_port)); + + szDZCommErr[0]=0; + + if (port==NULL) + { dz_make_comm_err("Out of memory !"); + return(NULL); + } + + if ((port->InBuf=queue_new_(4096,1))==NULL) + { dz_make_comm_err("Out of memory !"); + return(NULL); + } + if ((port->OutBuf=queue_new_(4096,1))==NULL) + { dz_make_comm_err("Out of memory !"); + queue_delete(port->InBuf); + return(NULL); + } + + port->nPort=0; + //getting comport base address + //0x400+com*2 - memory address where stored default comm base address + dosmemget(0x400+com*2,2,&port->nPort); + if (port->nPort==0) //probably you have notebook or some brand named PC + { if (com==_com1||com==_com3||com==_com5||com==_com7) port->nPort=0x3f8; //default I/O address for com1 or com3 + else port->nPort=0x2f8; //com2 or com4 + } + +//set default values (user may change it later) + + if (com==_com1||com==_com3||com==_com5||com==_com7) port->nIRQ=4; + else port->nIRQ=3; //com2 or com4 + + strcpy(port->szName,"COM "); + port->szName[3]=com+49; + port->installed=NO; + port->nComm=com; + port->nBaud=_2400; + port->nData=BITS_8; + port->nStop=STOP_1; + port->nParity=NO_PARITY; + port->comm_handler=com_wrapper[com]; + port->control_type=XON_XOFF; + port->msr_handler=NULL; //#d#pointer to modem status register handler. + port->lsr_handler=NULL; //#d#pointer to line status register handler. + + _go32_dpmi_lock_data(port,sizeof(comm_port)); + *(com_port[com])=port; + + return(port); +} + +//-------------------- COMM_PORT_FIFO_INIT ---------------------- + +void comm_port_fifo_init(comm_port *port) +{ +//setting up FIFO if possible + int c=inportb(port->SCR); + outportb(port->SCR,0x55); + port->fifo = 0; + if(inportb(port->SCR)==0x55) // greater then 8250 + { outportb(port->SCR,c); + outportb(port->FCR,0x87);//try to enable FIFO with 8 byte trigger level + if ((c=inportb(port->IIR)&0xc0)!=0xc0) //If not 16550A + outportb(port->FCR,c&0xfe); //Disable FIFO + else port->fifo = 1; +// else printf("\nFIFO OK\n"); + } + +} + +//----------------------- COMM PORT INSTALL HANDLER ------------------ +//modifyed by Neil Townsend to support IRQ sharing +int comm_port_install_handler(comm_port *port) +{ + if (port==NULL) + { dz_make_comm_err("Set up comm parametrs first ! Call comm_port_new() first."); + return(0); + } + if (port->installed==YES) + { dz_make_comm_err("Comm already installed !"); + return(0); + } + if (port->nIRQ>15) + { dz_make_comm_err("IRQ number out of range ! Must be 0 ... 15 ."); + return(0); + } + if (port->comm_handler==NULL) + { dz_make_comm_err("Specify comm's handler (see 'comm_handler' member's description) !"); + return(0); + } + if (port->nBaud==0) + { dz_make_comm_err("Invalid baud rate !"); + return(0); + } + + switch(port->control_type) + { case XON_XOFF : + port->xon=0; + port->xoff=0; + port->xonxoff_rcvd=XON_RCVD; + port->xonxoff_send=XON_SENT; + break; + case RTS_CTS : + port->cts=CTS_ON; + port->rts=RTS_ON; //fixed by SET (was RTS_OFF) + break; + default : + break; + } + + port->THR=port->nPort; + port->RDR=port->nPort; + port->BRDL=port->nPort; + port->BRDH=1+port->nPort; + port->IER=1+port->nPort; + port->IIR=2+port->nPort; + port->FCR=2+port->nPort; + port->LCR=3+port->nPort; + port->MCR=4+port->nPort; + port->LSR=5+port->nPort; + port->MSR=6+port->nPort; + port->SCR=7+port->nPort; + { byte i; + for(i=0;i<8;i++) outportb(port->RDR+i,0); + } + + comm_port_fifo_init(port); + + { unsigned char temp; + do + { temp=inportb(port->RDR); + temp=inportb(port->LSR); + temp=inportb(port->MSR); + temp=inportb(port->IIR); + } + while(!(temp & 1)); + } + + +//set communication parametrs +//MOVED forwards so done before interupts enabled + { int divisor=115200/port->nBaud; + byte divlow,divhigh; + byte comm_param=port->nData|(port->nStop<<2)|(port->nParity<<3); + // Set Port Toggle to BRDL/BRDH registers + outportb(port->LCR,comm_param|0x80); + divlow=divisor&0x000000ff; + divhigh=(divisor>>8)&0x000000ff; + outportb(port->BRDL,divlow); // Set Baud Rate + outportb(port->BRDH,divhigh); + outportb(port->LCR,comm_param&0x7F); // Set LCR and Port Toggle + } + +//set interrupt parametrs + { const byte IMR_8259_0=0x21; + const byte IMR_8259_1=0xa1; + const byte ISR_8259_0=0x20; + const byte ISR_8259_1=0xa0; + const byte IERALL = 0x0f; //mask for all communications interrupts + const byte MCRALL = 0x0f; //DTR,RTS,OUT1=OUT2=1 is ON + //calculating mask for 8259 controller's IMR + //and number of interrupt hadler for given irq level + if (port->nIRQ<=7) //if 0<=irq<=7 first IMR address used + { port->interrupt_enable_mask=~(0x01<nIRQ); + port->nIRQVector=port->nIRQ+8; + port->IMR_8259=IMR_8259_0; + port->ISR_8259=ISR_8259_0; + } + else + { port->interrupt_enable_mask=~(0x01<<(port->nIRQ%8)); + port->nIRQVector=0x70+(port->nIRQ-8); + port->IMR_8259=IMR_8259_1; + port->ISR_8259=ISR_8259_1; + } + + port->next_port = NULL; + port->last_port = irq_bot_com_port[port->nIRQ]; + if (irq_bot_com_port[port->nIRQ] != NULL) irq_bot_com_port[port->nIRQ]->next_port = port; + irq_bot_com_port[port->nIRQ] = port; + DISABLE(); + if (port->last_port == NULL) + { // DZ orig lines in here + _install_irq(port->nIRQVector,port->comm_handler); + //enable interrupt port->nIRQ level + outportb(port->IMR_8259,inportb(port->IMR_8259)& + port->interrupt_enable_mask); + } + + // DZ again: + outportb(port->MCR,MCRALL); //setup modem + outportb(port->IER,IERALL); //enable all communication's interrupts + // to here + ENABLE(); + } + + port->installed=YES; + return(1); +} + +//------------------ DZ COMM PORT INTERRUPT HANDLER --------------- +// always return zero +inline int dz_comm_port_interrupt_handler(comm_port *port) +{ int int_id; + int c; +// putch('1'); + + while (1) //loop while !end of all interrupts + { int_id=inportb(port->IIR); //get interrupt id + //next loop added by Neil Townsend + while ((int_id&0x01)==1) //no interrupts (left) to handle on this port + { if (port->next_port==NULL) + { outportb(0x20,0x20); + if (port->nIRQ>7) //Thanks for SET for this fix + outportb(0xA0,0x20); //now IRQ8-IRQ15 handled properly. + + return(0); + } + port=(comm_port*)port->next_port; + int_id=inportb(port->IIR); + } + + switch (int_id) + { + case 0xcc: //Character Timeout Indication N.Lohmann 6.3.98 + // only possible if FiFo's are enabled. + comm_port_rtmout(port); + break; + case 0xc6: //FiFo LSINT + case 0x06: //LSINT: + c=inportb(port->LSR); + if (port->lsr_handler!=NULL) port->lsr_handler(c); + break; + case 0xc4: //FiFo RDAINT + case 0x04: //RDAINT + comm_port_rdr(port); + break; + case 0xc2: //FiFo THREINT + case 0x02: //THREINT : + comm_port_trx(port); + break; + case 0xc0: //FiFo MSINT + case 0x00: //MSINT : + c=inportb(port->MSR); + if (port->msr_handler!=NULL) port->msr_handler(c); + + if (port->control_type==RTS_CTS) + { if (port->cts==CTS_OFF && c&0x10) + { port->cts=CTS_ON; + if (port->rts==RTS_ON) + interrupt_on(port,THREINT); + } + else + if (port->cts==CTS_ON && !c&0x10) + { port->cts=CTS_OFF; + interrupt_off(port,THREINT); + } + } + break; + }//end case + } //end while 1 + + return(0); +} +END_OF_FUNCTION(dz_comm_port_interrupt_handler); + +//----------------------- COMM PORT RTMOUT ------------------------ +//Nils Lohmann 8.3.98 +//Time Out Indication, service routine triggered after 4 Char-times +//if there is at least one Byte in FiFo and no read-Cykle happened. + +inline void comm_port_rtmout(comm_port *port) +{ + comm_port_rdr(port); +} +END_OF_FUNCTION(comm_port_rtmout); + +//----------------------- COMM PORT DELETE ------------------------ + +void comm_port_delete(comm_port *port) +{ + if (port->installed==NO) return; + + comm_port_uninstall(port); + + free(port); +} + +//------------------------- COMM PORT OUT ----------------------------- + +inline void comm_port_out(comm_port *port,byte c) +{ + + queue_put_(port->OutBuf,&c); + switch (port->control_type) + { case NO_CONTROL : + interrupt_on(port,THREINT); + break; + case XON_XOFF : // XON/XOFF + if (port->xonxoff_rcvd!=XOFF_RCVD) + { interrupt_on(port,THREINT); + } + case RTS_CTS : // RTS_CTR + if (port->cts==CTS_ON) //modem is 'clear to send' + { if (port->rts==RTS_ON) //Fixed by SET (was RTS_OFF) + { interrupt_on(port,THREINT); + } + } + break; + default: + break; + } +} + +//------------------------- COMM PORT TEST ----------------------------- + +inline int comm_port_test(comm_port *port) +{ byte c; + + switch (port->control_type) + { case NO_CONTROL : + break; + case XON_XOFF : // XON/XOFF + if (((port->InBuf)->tail<(port->InBuf)->fill_level)&&(port->xonxoff_send!=XON_SENT)) + { port->xon=1; + interrupt_on(port,THREINT); + } + break; + case RTS_CTS : + if (((port->InBuf)->tail<(port->InBuf)->fill_level)&&(port->rts==RTS_OFF)) + { outportb(port->MCR,inportb(port->MCR)|0x02); //setting RTS + port->rts=RTS_ON; + interrupt_on(port,THREINT); + } + break; + default: + break; + } + if (queue_empty(port->InBuf)) + { return(-1); + } + queue_get_(port->InBuf, &c); + return(c); +} + +//----------------------- COMM PORT STRING SEND ------------------------- + +void comm_port_string_send(comm_port *port,char *s) +{ + int i; + + if (s==NULL) return; + for (i=0;s[i]!=0;i++) comm_port_out(port,s[i]); +} + +//---------------------- COMM PORT COMMAND SEND ------------------------- + +void comm_port_command_send(comm_port *port,char *s) +{ + int i; + + if (s==NULL) return; + for (i=0;s[i]!=0;i++)comm_port_out(port,s[i]); + comm_port_out(port,'\r'); +} + +//------------------- MODEM HANG UP ----------------- + +void modem_hangup(comm_port *port) +{ + comm_port_out(port,2); + delay(3000); + comm_port_string_send(port,"+++"); + delay(3000); + comm_port_string_send(port,"ATH0\r"); +} + +//---------------------- COMM PORT HAND --------------------------- + +void comm_port_hand(comm_port *port,int m) +{ int c; + c=inportb(port->MCR); + outportb(port->MCR,c&m); +} + +inline int comm_port_send_xoff(comm_port *port) +{ + if (port->xonxoff_send!=XOFF_SENT) + { port->xoff=1; + interrupt_on(port,THREINT); + } + return(1); +} + +inline int comm_port_send_xon(comm_port *port) +{ + if (port->xonxoff_send!=XON_SENT) + { port->xon=1; + interrupt_on(port,THREINT); + } + return(1); +} + +//-------------------- COMM PORT LOAD SETTINGS --------------------- + +#ifdef __DEVICE__ +int comm_port_load_settings(device *dev,char *ini_name) +#else +int comm_port_load_settings(comm_port *port,char *ini_name) +#endif +{ + #ifdef __DEVICE__ + comm_port *port=dev->device_user_data; + #endif + FILE *ini; + int l,i; + char *buf,*buf_end,*s,v[64]; + comm com=port->nComm; + char com_name[7]={'[','c','o','m',com+49,']',0}; + char com_end[11]={'[','c','o','m',com+49,' ','e','n','d',']',0}; + + if ((ini=fopen(ini_name,"rt"))==NULL) return(0); + l=filelength(fileno(ini)); + if ((buf=(char*)alloca(l))==NULL) + { fclose(ini); + return(0); + } + + l=fread(buf,1,l,ini); + fclose(ini); + buf[l]=0; + strlwr(buf); + + s=strstr(buf,com_name); + buf_end=strstr(buf,com_end); + + if (s==NULL||buf_end==NULL) return(-1); + *buf_end=0; + + //get baud rate + if ((s=strstr(buf,"baud"))!=NULL) + { if (not_commented(s)&&(s=strchr(s,'='))!=NULL) + { s++;i=0; + while ((*s!=';')&&(*s!='\n')&&(*s!=0)&&(i<9)) + if (!isspace(*s)) v[i++]=*s++; + + v[i]=0; + if ((i=atoi(v))!=0) port->nBaud=i; + } + } + + //get irq number + if ((s=strstr(buf,"irq"))!=NULL) + { if (not_commented(s)&&(s=strchr(s,'='))!=NULL) + { s++;i=0; + while ((*s!=';')&&(*s!='\n')&&(*s!=0)&&(i<9)) + if (!isspace(*s)) v[i++]=*s++; + + v[i]=0; + if ((i=atoi(v))!=0) port->nIRQ=i; + } + } + + //get comm address + if ((s=strstr(buf,"address"))!=NULL) + { if (not_commented(s)&&(s=strchr(s,'='))!=NULL) + { s++;i=0; + while ((*s!=';')&&(*s!='\n')&&(*s!=0)&&(i<9)) + if (!isspace(*s)) v[i++]=*s++; + + v[i]=0; + if ((i=strtol(v,NULL,0))!=0) port->nPort=strtol(v,NULL,0); + } + } + + //get data bits + if ((s=strstr(buf,"data"))!=NULL) + { if (not_commented(s)&&(s=strchr(s,'='))!=NULL) + { s++;i=0; + while ((*s!=';')&&(*s!='\n')&&(*s!=0)&&(i<9)) + if (!isspace(*s)) v[i++]=*s++; + + v[i]=0; + if ((i=atoi(v))!=0) + switch (i) + { case 8 : + port->nData=BITS_8; + break; + case 7 : + port->nData=BITS_7; + break; + case 6 : + port->nData=BITS_6; + break; + case 5 : + port->nData=BITS_5; + break; + } + } + } + + //get parity bits + if ((s=strstr(buf,"parity"))!=NULL) + { if (not_commented(s)&&(s=strchr(s,'='))!=NULL) + { s++;i=0; + while ((*s!=';')&&(*s!='\n')&&(*s!=0)&&(i<9)) + if (!isspace(*s)) v[i++]=*s++; + v[i]=0; + + if (strcmp(v,"even")==0) port->nParity=EVEN_PARITY; + else + if (strcmp(v,"odd")==0) port->nParity=ODD_PARITY; + else + if (strcmp(v,"no")==0||strcmp(v,"none")==0) port->nParity=NO_PARITY; + } + } + + //get control type + if ((s=strstr(buf,"control"))!=NULL) + { if (not_commented(s)&&(s=strchr(s,'='))!=NULL) + { s++;i=0; + while ((*s!=';')&&(*s!='\n')&&(*s!=0)&&(i<9)) + if (!isspace(*s)) v[i++]=*s++; + v[i]=0; + + if (strcmp(v,"xon_xoff")==0||strcmp(v,"xon/xoff")==0) port->control_type=XON_XOFF; + else + if (strcmp(v,"no")==0||strcmp(v,"none")==0) port->control_type=NO_CONTROL; + else + if (strcmp(v,"rts_cts")==0||strcmp(v,"rts/cts")==0) port->control_type=RTS_CTS; + } + } + + if ((s=strstr(buf,"stop"))!=NULL) //get stop bits + { if (not_commented(s)&&(s=strchr(s,'='))!=NULL) + { s++;i=0; + while ((*s!=';')&&(*s!='\n')&&(*s!=0)&&(i<9)) + if (!isspace(*s)) v[i++]=*s++; + + v[i]=0; + if ((i=atoi(v))!=0) + switch (i) + { case 1 : + port->nStop=STOP_1; + break; + case 2 : + port->nStop=STOP_2; + break; + } + } + } + + if ((s=strstr(buf,"name"))!=NULL) + { if (not_commented(s)&&(s=strchr(s,'='))!=NULL) + { s++;i=0; + while ((*s!=';')&&(*s!='\n')&&(*s!=0)&&(i<64)) + v[i++]=*s++; + + v[i]=0; + strcpy(port->szName,v); + } + } + + return(1); +} + + +//----------------------- COMM PORT RDR ------------------------ + +static inline void comm_port_rdr(comm_port *port) +{ byte c; + int n; + + do { + c = inportb(port->RDR); + switch (port->control_type) + { case NO_CONTROL : + queue_put_(port->InBuf,&c); + port->in_cnt++; + break; + case XON_XOFF : // XON/XOFF + if (c==XON_ASCII) + { port->xonxoff_rcvd=XON_RCVD; + interrupt_on(port,THREINT); + return; + } + if (c==XOFF_ASCII) + { port->xonxoff_rcvd=XOFF_RCVD; + interrupt_off(port,THREINT); + return; + } + n=queue_put_(port->InBuf,&c); + port->in_cnt++; + if (n) //buffer is near full + { if (port->xonxoff_send!=XOFF_SENT) + { port->xoff=1; + interrupt_on(port,THREINT); + } + } + break; + case RTS_CTS: + n=queue_put_(port->InBuf,&c); + port->in_cnt++; + if (n) //buffer is near full + { outportb(port->MCR,inportb(port->MCR)&(~0x02)); //dropping RTS + port->rts=RTS_OFF; + } + break; + default : + break; + } + c =inportb(port->LSR); + } while (c & 1); + // these lines are a cure for the well-known problem of TX interrupt + // lock-ups when receiving and transmitting at the same time + if (c & 0x40) + comm_port_trx(port); +} +static END_OF_FUNCTION(comm_port_rdr) + +//----------------------- COMM PORT TRX ------------------------ + +static inline void comm_port_trx(comm_port *port) +{ byte c; + int i, count = port->fifo ? 16 : 1; + + for (i = count; i--; ) { + switch (port->control_type) + { case NO_CONTROL : + if (queue_empty(port->OutBuf))//queue empty, nothig to send + { interrupt_off(port,THREINT); + return; + } + queue_get_(port->OutBuf, &c); + port->out_cnt++; + outportb(port->THR,c); + break; + case XON_XOFF : // XON/XOFF + if (port->xoff==1) + { outportb(port->THR,XOFF_ASCII); + port->xoff=0; + port->xonxoff_send=XOFF_SENT; + } + else if (port->xon==1) + { outportb(port->THR,XON_ASCII); + port->xon=0; + port->xonxoff_send=XON_SENT; + return; + } + if (queue_empty(port->OutBuf))//queue empty, nothig to send + { interrupt_off(port,THREINT); + return; + } + queue_get_(port->OutBuf, &c); + outportb(port->THR,c); + port->out_cnt++; + break; + case RTS_CTS: + if (port->cts==CTS_OFF) + { return; + } + if (port->rts==RTS_OFF) + { port->rts=RTS_ON; + outportb(port->MCR,inportb(port->MCR)|0x02); //setting RTS + } + if (queue_empty(port->OutBuf))//queue empty, nothig to send + { outportb(port->MCR,inportb(port->MCR)&(~0x02)); //dropping RTS + port->rts=RTS_OFF; + interrupt_off(port,THREINT); + return; + } + queue_get_(port->OutBuf, &c); + outportb(port->THR,c); + port->out_cnt++; + break; + default : + break; + } + } +} +static END_OF_FUNCTION(comm_port_trx); + +//------------------------- COMM PORT INIT ----------------------------- + +void dzcomm_init(void) +{ + LOCK_FUNCTION(dz_comm_port_interrupt_handler); + LOCK_FUNCTION(comm_port_rdr); + LOCK_FUNCTION(comm_port_trx); + LOCK_FUNCTION(interrupt_on); + LOCK_FUNCTION(interrupt_off); + LOCK_FUNCTION(com1_wrapper); + LOCK_FUNCTION(com2_wrapper); + LOCK_FUNCTION(com3_wrapper); + LOCK_FUNCTION(com4_wrapper); + LOCK_FUNCTION(com5_wrapper); + LOCK_FUNCTION(com6_wrapper); + LOCK_FUNCTION(com7_wrapper); + LOCK_FUNCTION(com8_wrapper); + LOCK_VARIABLE(com1); + LOCK_VARIABLE(com2); + LOCK_VARIABLE(com3); + LOCK_VARIABLE(com4); + LOCK_VARIABLE(com5); + LOCK_VARIABLE(com6); + LOCK_VARIABLE(com7); + LOCK_VARIABLE(com8); + com1=NULL; + com2=NULL; + com3=NULL; + com4=NULL; + com5=NULL; + com6=NULL; + com7=NULL; + com8=NULL; + com_wrapper[0]=com1_wrapper; + com_wrapper[1]=com2_wrapper; + com_wrapper[2]=com3_wrapper; + com_wrapper[3]=com4_wrapper; + com_wrapper[4]=com5_wrapper; + com_wrapper[5]=com6_wrapper; + com_wrapper[6]=com7_wrapper; + com_wrapper[7]=com8_wrapper; + com_port[0]=&com1; + com_port[1]=&com2; + com_port[2]=&com3; + com_port[3]=&com4; + com_port[4]=&com5; + com_port[5]=&com6; + com_port[6]=&com7; + com_port[7]=&com8; + +} + +//----------------------- COMM PORT UNINSTALL --------------------- +// New routine to allow uninstalling without deleting +// and to simplyfy _delete and _reinstall +// by Neil Townsend +void comm_port_uninstall(comm_port *port) +{ comm_port *i_port; + + if (port->installed==NO) return; + i_port = irq_bot_com_port[port->nIRQ]; + + DISABLE(); + if (i_port == port) + { irq_bot_com_port[port->nIRQ] = (comm_port *) port->last_port; + if (irq_bot_com_port[port->nIRQ]) irq_bot_com_port[port->nIRQ]->next_port = NULL; + i_port = NULL; + } + else i_port = (comm_port *) i_port->last_port; + while (i_port) + { if (i_port == port) + { if (i_port->last_port) ((comm_port *)i_port->last_port)->next_port = i_port->next_port; + if (i_port->next_port) ((comm_port *)i_port->next_port)->last_port = i_port->last_port; + i_port = NULL; + } + if (i_port) i_port = i_port->last_port; + } + + if (irq_bot_com_port[port->nIRQ] == NULL) _remove_irq(port->nIRQVector); + + { const byte IEROFF=0x00; + const byte MCROFF=0x00; + outportb(port->IER,IEROFF); + outportb(port->MCR,MCROFF); + outportb(port->IMR_8259,inportb(port->IMR_8259)&~(port->interrupt_enable_mask)); + } + ENABLE(); + port->installed = NO; + +} + + +//----------------------- COMM PORT REINSTALL --------------------------- + +int comm_port_reinstall(comm_port *port) +{ + if (port->installed==NO) return(0); + + comm_port_uninstall(port); + return (comm_port_install_handler(port)); +} diff --git a/arch/dos/comm/dzqueue.c b/arch/dos/comm/dzqueue.c new file mode 100644 index 00000000..c48975ea --- /dev/null +++ b/arch/dos/comm/dzqueue.c @@ -0,0 +1,168 @@ +/* + * This file is part of DZComm. + * Version : 0.6 + * General purpose FIFO queue functions set. + * Copyright (c) 1997 Dim Zegebart, Moscow Russia. + * zager@post.comstar.ru + * http://www.geocities.com/siliconvalley/pines/7817 + * file : queue.c + */ + +#include /* NULL */ +#include "dzcomm.h" +#include "internal.h" + +typedef unsigned int uint; +typedef unsigned short int usint; +typedef unsigned char byte; + +#define QH(q) q->queue+q->head +#define QT(q) q->queue+q->tail + +//------------------------- FIFO QUEUE ----------------------------- +// 'first in first out' queue functions + +inline void queue_reset(fifo_queue *q) +{ q->tail=0; + q->head=0; +} +END_OF_FUNCTION(queue_reset); + + +int queue_resize(fifo_queue *q,uint new_size) +{ int *tmp; + if ((tmp=(int*)realloc(q->queue,sizeof(int)*new_size))==NULL) return(0); + + if (new_size>q->size) q->resize_counter++; + else if (new_size<=q->initial_size) q->resize_counter=0; + else q->resize_counter--; + + q->queue=tmp; + q->size=new_size; + q->fill_level=3*(q->size>>2); // 3/4 + return(1); +} + +//-------------------- QUEUE_DELETE -------------------------- + +void queue_delete(fifo_queue *q) +{ if (q==NULL) return; + free(q->queue); + free(q); +} + +//--------------------- QUEUE_PUT ------------------------------ + +inline int queue_put(fifo_queue *q,int c) +{ return(queue_put_(q,&c)); +} +END_OF_FUNCTION(queue_put); + +int queue_put_(fifo_queue *q,void *c) +{ int n=0; + + if (!q) return(0); + + DISABLE(); + memcpy(QT(q),c,q->dsize); + q->tail+=q->dsize; + if (q->tail==q->head) + { q->head+=q->dsize; + if (q->head>(q->size-q->dsize)) q->head=0; + } + + if(q->tail>(q->size-q->dsize)) q->tail=0; + + n=0; + if (q->headtail) {if ((q->tail-q->head)>=q->fill_level) n=1;} + else + if ((q->head-q->tail)<=q->size-q->fill_level) n=1; + + ENABLE(); + + return(n); +} +END_OF_FUNCTION(queue_put_); + +//---------------------- QUEUE GET --------------------------- + +inline int queue_get(fifo_queue *q) +{ int c; + queue_get_(q,&c); + return(c); +} +END_OF_FUNCTION(queue_get); + +int queue_get_(fifo_queue *q,void *c) +{ + int n; + + DISABLE(); + memcpy(c,QH(q),q->dsize); + q->head+=q->dsize; + + if (q->head>(q->size-q->dsize)) q->head=0; + if (q->head==q->tail) queue_reset(q); + + n=0; + if (q->headtail) {if ((q->tail-q->head)>=q->fill_level) n=1;} + else + if ((q->head-q->tail)<=q->size-q->fill_level) n=1; + + ENABLE(); + return(n); +} +END_OF_FUNCTION(queue_get_); +//---------------------- QUEUE EMPTY --------------------------- + +inline int queue_empty(fifo_queue *q) +{ if (q==NULL) return(1); + if (q->head==q->tail) + { if (q->empty_handler!=NULL) return(-1); + return(1); + } + return(0); +} +END_OF_FUNCTION(queue_empty); + + +//------------------------------- QUEUE NEW -------------------------- + +fifo_queue* queue_new(uint size) +{ + return(queue_new_(size,4)); +} + +//------------------------- QUEUE_NEW_ -------------------------- + +fifo_queue* queue_new_(uint size,uint dsize) +{ fifo_queue *q=NULL; + + if (dsize<=0||dsize>4) return(NULL); + if ((q=(fifo_queue*)malloc(sizeof(fifo_queue)))==NULL) return(NULL); + + if (!size) size=1024; //if illegal size, turn it to default size + if ((q->queue=malloc(sizeof(int)*size*dsize))==NULL) return(NULL); + + q->dsize=dsize; + q->size=size*dsize; + q->initial_size=size*dsize;//size; + q->resize_counter=0; + q->fill_level=3*q->size/4; // 3/4 + q->empty_handler=NULL; + queue_reset(q); + _go32_dpmi_lock_data(q->queue,sizeof(int)*size*dsize); + _go32_dpmi_lock_data(q,sizeof(fifo_queue)); + + return(q); +} + +void lock_queue_functions(void) +{ + LOCK_FUNCTION(queue_empty); + LOCK_FUNCTION(queue_put); + LOCK_FUNCTION(queue_get); + LOCK_FUNCTION(queue_put_); + LOCK_FUNCTION(queue_get_); + LOCK_FUNCTION(queue_reset); +} diff --git a/arch/dos/comm/include/allegro.h b/arch/dos/comm/include/allegro.h new file mode 100644 index 00000000..0a82cf2d --- /dev/null +++ b/arch/dos/comm/include/allegro.h @@ -0,0 +1,45 @@ +#ifndef _ALLEGRO_H +#define _ALLEGRO_H + +// nothing +#include +#include +#define allegro_init() +#define install_keyboard() +#define keypressed() kbhit() +#define readkey() getkey() + +#ifdef DJGPP + +/* for djgpp */ +#define END_OF_FUNCTION(x) void x##_end() { } +#define LOCK_VARIABLE(x) _go32_dpmi_lock_data((void *)&x, sizeof(x)) +#define LOCK_FUNCTION(x) _go32_dpmi_lock_code(x, (long)x##_end - (long)x) + +#else + +/* for linux */ +#define END_OF_FUNCTION(x) +#define LOCK_VARIABLE(x) +#define LOCK_FUNCTION(x) + +#endif + +#define DISABLE() __asm__ __volatile__("cli"); +#define ENABLE() __asm__ __volatile__("sti"); + + +int _install_irq(int num, int (*handler)()); +void _remove_irq(int num); +#define FALSE 0 +#define TRUE (!FALSE) + +#include +typedef struct _IRQ_HANDLER +{ + int (*handler)(); /* our C handler */ + int number; /* irq number */ + __dpmi_paddr old_vector; /* original protected mode vector */ +} _IRQ_HANDLER; + +#endif diff --git a/arch/dos/comm/include/asmdef.inc b/arch/dos/comm/include/asmdef.inc new file mode 100644 index 00000000..b1a3a894 --- /dev/null +++ b/arch/dos/comm/include/asmdef.inc @@ -0,0 +1,15 @@ +/* automatically generated structure offsets for use by asm code */ + +#define IRQ_SIZE 16 +#define IRQ_HANDLER 0 +#define IRQ_NUMBER 4 +#define IRQ_OLDVEC 8 + +#define DPMI_AX 28 +#define DPMI_BX 16 +#define DPMI_CX 24 +#define DPMI_DX 20 +#define DPMI_SP 46 +#define DPMI_SS 48 +#define DPMI_FLAGS 32 + diff --git a/arch/dos/comm/include/asmdefs.inc b/arch/dos/comm/include/asmdefs.inc new file mode 100644 index 00000000..bcd1269c --- /dev/null +++ b/arch/dos/comm/include/asmdefs.inc @@ -0,0 +1,8 @@ +/* How many stacks to allocate for the irq wrappers. This can't be in the + * main headers, because it is used by both C and asm code. You could + * probably get away with fewer of these, if you want to save memory and + * you are feeling brave... + */ +#define IRQ_STACKS 8 + +#include "asmdef.inc" diff --git a/arch/dos/comm/include/commlib.h b/arch/dos/comm/include/commlib.h new file mode 100644 index 00000000..4df33e0b --- /dev/null +++ b/arch/dos/comm/include/commlib.h @@ -0,0 +1,58 @@ +#ifndef _COMLIB_H +#define _COMLIB_H +#include "dzcomm.h" +typedef comm_port PORT; + +#define COM1 0 +#define COM2 1 +#define COM3 2 +#define COM4 3 + +#define IRQ2 2 +#define IRQ3 3 +#define IRQ4 4 +#define IRQ7 7 +#define IRQ15 15 + +#define ASSUCCESS 1 +#define ASBUFREMPTY -1 +#define TRIGGER_04 4 + +#define ON 1 +#define OFF 0 + + +PORT * PortOpenGreenleafFast(int port, int baud,char parity,int databits, int stopbits); +void SetDtr(PORT *port,int state); +void SetRts(PORT *port,int state); +void UseRtsCts(PORT *port,int state); +void WriteChar(PORT *port,char ch); +void ClearRXBuffer(PORT *port); +int ReadBufferTimed(PORT *port, char *buf, int length, int timeout); +int Change8259Priority(int a); +int FastSetPortHardware(int comport,int IRQ, int baseaddr); +int FastGetPortHardware(int comport,int *IRQ, int *baseaddr); +void FastSet16550TriggerLevel(int a); +void FastSet16550UseTXFifos(int a); +void FastSavePortParameters(int comport); +int PortClose(PORT *port); +void FastRestorePortParameters(int num); +int GetCd(PORT *port); +int ReadCharTimed(PORT *port, int blah); +int ReadChar(PORT *port); +void ClearLineStatus(PORT *port); +int HMInputLine(PORT *port, int a, char *buf, int b); +void HMWaitForOK(int a, char *b); +int HMSendString(PORT *port, char *msg); +int HMSendStringWait(PORT *port, char *msg, int wait); +void HMReset(PORT *port); +void HMDial(PORT *port, char *pPhoneNum); +void HMSendStringNoWait(PORT *port, char *pbuf,int a); +void HMAnswer(PORT *port); +void ClearTXBuffer(PORT *port); +void WriteBuffer(PORT *port, char *pbuff, int len); + +int GetLineStatus(PORT *port); +void ClearLineStatus(PORT *port); + +#endif diff --git a/arch/dos/comm/include/internal.h b/arch/dos/comm/include/internal.h new file mode 100644 index 00000000..8424b0db --- /dev/null +++ b/arch/dos/comm/include/internal.h @@ -0,0 +1 @@ +#include "allegro.h" diff --git a/arch/dos/comm/irq.c b/arch/dos/comm/irq.c new file mode 100644 index 00000000..595a849d --- /dev/null +++ b/arch/dos/comm/irq.c @@ -0,0 +1,157 @@ +/* + * This file is part of DZComm. + * Version : 0.6 + * Minor changes by Dim Zegebart (zager@post.comstar.ru) to run with Palantir + */ + +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * By Shawn Hargreaves, + * 1 Salisbury Road, + * Market Drayton, + * Shropshire, + * England, TF9 1AJ. + * + * Hardware interrupt wrapper functions. Unlike the _go32_dpmi_* + * functions, these can deal with reentrant interrupts. + * + * See readme.txt for copyright information. + */ + + +#ifndef DJGPP +#error This file should only be used by the djgpp version of Allegro +#endif + +#include +#include +#include +#include + +#include "allegro.h" +#include "internal.h" +#include "asmdefs.inc" + + +#define MAX_IRQS 16 +#define STACK_SIZE 8*1024 /* 8k stack should be plenty */ + + +static int irq_virgin = TRUE; + +_IRQ_HANDLER _irq_handler[MAX_IRQS]; + +unsigned char *_irq_stack[IRQ_STACKS]; + +extern void _irq_wrapper_0(), _irq_wrapper_1(), + _irq_wrapper_2(), _irq_wrapper_3(), + _irq_wrapper_4(), _irq_wrapper_5(), + _irq_wrapper_6(), _irq_wrapper_7(), + _irq_wrapper_8(), _irq_wrapper_9(), + _irq_wrapper_10(), _irq_wrapper_11(), + _irq_wrapper_12(), _irq_wrapper_13(), + _irq_wrapper_14(), _irq_wrapper_15(), + _irq_wrapper_0_end(); + + + +/* _install_irq: + * Installs a hardware interrupt handler for the specified irq, allocating + * an asm wrapper function which will save registers and handle the stack + * switching. The C function should return zero to exit the interrupt with + * an iret instruction, and non-zero to chain to the old handler. + */ +int _install_irq(int num, int (*handler)()) +{ + int c; + __dpmi_paddr addr; + + if (irq_virgin) { /* first time we've been called? */ + LOCK_VARIABLE(_irq_handler); + LOCK_VARIABLE(_irq_stack); + LOCK_FUNCTION(_irq_wrapper_0); + + for (c=0; c +#include +#include +#include +#include +#include + +#include "fix.h" +#include "object.h" +#include "mono.h" +#include "timer.h" +#include "joy.h" +#include "digi.h" +#include "sounds.h" +#include "args.h" +#include "key.h" +#include "newdemo.h" +#include "game.h" +#include "u_dpmi.h" +#include "error.h" +#include "wall.h" +#include "cfile.h" +#include "piggy.h" +#include "text.h" +#include "midiallg.h" + +#include "kconfig.h" + +#define _DIGI_MAX_VOLUME 128 // set lower to have difference with > F1_0 sounds + +#define MIN_VOLUME 10 // minimal volume to be played (in 0-F1_0(?) range) + +// patch files +#define _MELODIC_PATCH "melodic.bnk" +#define _DRUM_PATCH "drum.bnk" +#define _DIGDRUM_PATCH "drum32.dig" + + +static int Digi_initialized = 0; +static int digi_atexit_called = 0; // Set to 1 if atexit(digi_close) was called + +int digi_driver_board = 0; +int digi_driver_port = 0; +int digi_driver_irq = 0; +int digi_driver_dma = 0; +//int digi_midi_type = 0; // Midi driver type +//int digi_midi_port = 0; // Midi driver port +static int digi_max_channels = 8; +//static int digi_driver_rate = 11025; // rate to use driver at +//static int digi_dma_buffersize = 4096; // size of the dma buffer to use (4k) +int digi_timer_rate = 9943; // rate for the timer to go off to handle the driver system (120 Hz) +int digi_lomem = 0; +static int digi_volume = _DIGI_MAX_VOLUME; // Max volume +//static int midi_volume = 128/2; // Max volume +//static int midi_system_initialized = 0; +//static int digi_system_initialized = 0; +static int timer_system_initialized = 0; +static int digi_sound_locks[MAX_SOUNDS]; +//char digi_last_midi_song[16] = ""; +//char digi_last_melodic_bank[16] = ""; +//char digi_last_drum_bank[16] = ""; +char *digi_driver_path = NULL; + +extern int midi_volume; + +//static void * lpInstruments = NULL; // pointer to the instrument file +//static int InstrumentSize = 0; +//static void * lpDrums = NULL; // pointer to the drum file +//static int DrumSize = 0; + +// handle for the initialized MIDI song +//MIDI *SongHandle = NULL; + +#define SOF_USED 1 // Set if this sample is used +#define SOF_PLAYING 2 // Set if this sample is playing on a channel +#define SOF_LINK_TO_OBJ 4 // Sound is linked to a moving object. If object dies, then finishes play and quits. +#define SOF_LINK_TO_POS 8 // Sound is linked to segment, pos +#define SOF_PLAY_FOREVER 16 // Play forever (or until level is stopped), otherwise plays once + +typedef int WORD; + +typedef struct sound_object { + short signature; // A unique signature to this sound + ubyte flags; // Used to tell if this slot is used and/or currently playing, and how long. + fix max_volume; // Max volume that this sound is playing at + fix max_distance; // The max distance that this sound can be heard at... + int volume; // Volume that this sound is playing at + int pan; // Pan value that this sound is playing at + WORD handle; // What handle this sound is playing on. Valid only if SOF_PLAYING is set. + short soundnum; // The sound number that is playing + union { + struct { + short segnum; // Used if SOF_LINK_TO_POS field is used + short sidenum; + vms_vector position; + }pos; + struct { + short objnum; // Used if SOF_LINK_TO_OBJ field is used + short objsignature; + }obj; + }link; +} sound_object; +#define lp_segnum link.pos.segnum +#define lp_sidenum link.pos.sidenum +#define lp_position link.pos.position + +#define lo_objnum link.obj.objnum +#define lo_objsignature link.obj.objsignature + +#define MAX_SOUND_OBJECTS 16 +sound_object SoundObjects[MAX_SOUND_OBJECTS]; +short next_signature=0; + +int digi_sounds_initialized=0; + + +// a channel (voice) id is an int in Allegro +typedef int CHANNEL; +#define VALID_CHANNEL(ch) (ch >= 0) +#define INVALID_CHANNEL -1 + +#define DIGI_SLOTS DIGI_VOICES + +// next_handle is a Descent internal number (hereafter reffered to as slot), +// which indexes into SampleHandles, SoundNums and SoundVolumes. +// only digi_max_channels entries are used. +// SampleHandles points to sounddriver handles (voices) +static int next_handle = 0; +static CHANNEL SampleHandles[DIGI_SLOTS] = { + INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, + INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, + INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, + INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, + INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, + INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, + INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, + INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL }; +static int SoundNums[DIGI_SLOTS] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 }; +static uint SoundVolumes[DIGI_SLOTS] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 }; + +void digi_reset_digi_sounds(); +int verify_channel_not_used_by_soundobjects( int channel ); + +int digi_xlat_sound(int soundno) +{ + if ( soundno < 0 ) return -1; + + if ( digi_lomem ) { + soundno = AltSounds[soundno]; + if ( soundno == 255 ) return -1; + } + return Sounds[soundno]; +} + +void digi_close() { + if (!Digi_initialized) return; + + remove_sound(); + Digi_initialized = 0; + + if ( timer_system_initialized ) { + // Remove timer... + timer_set_function( NULL ); + } + timer_system_initialized = 0; +} + +/* initialize sound system. 0=ok, 1=error */ +int digi_init() { + int i; + + if (!timer_system_initialized) + { + allg_snd_init(); + timer_system_initialized = 1; + } + if (!Digi_initialized) { + // amount of voices we need + // 16 for normal sounds and 16 for SoundObjects (fan, boss) + // for DIGMID we sacrify some sounds (32 is the max). +// reserve_voices(allegro_using_digmid() ? 16 : 32, -1); + if (install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL)) + return 1; + set_volume(255, -1); + digi_driver_board = digi_card; // only for 0, !=0 + digi_midi_type = midi_card; // only for 0, !=0 + } + Digi_initialized = 1; + + + if (!digi_atexit_called) { + atexit( digi_close ); + digi_atexit_called = 1; + } + + digi_init_sounds(); + digi_set_midi_volume( midi_volume ); + + for (i=0; i 0 ); + + if ( digi_sound_locks[soundnum] == 1 ) { + digi_total_locks--; + //mprintf(( 0, "Total sound locks = %d\n", digi_total_locks )); + i = dpmi_unlock_region( GameSounds[soundnum].data, GameSounds[soundnum].len ); + if ( !i ) Error( "Error unlocking sound %d\n", soundnum ); + } + digi_sound_locks[soundnum]--; +} + + +void digi_reset_digi_sounds() { + int i; + + for (i = 0; i < DIGI_SLOTS; i++) { + if (VALID_CHANNEL(SampleHandles[i])) { + deallocate_voice(SampleHandles[i]); + SampleHandles[i] = INVALID_CHANNEL; + } + if (SoundNums[i] != -1) { + digi_unlock_sound_data(SoundNums[i]); + SoundNums[i] = -1; + } + } + for (i=0; i DIGI_VOICES) + digi_max_channels = DIGI_VOICES; +} + +int digi_get_max_channels() +{ + return digi_max_channels; +} + +int get_free_slot() { + int ntries = 0; + int ret_slot; + +TryNextChannel: + // sound playing on slot ? + if ( (VALID_CHANNEL(SampleHandles[next_handle])) && + (voice_check(SampleHandles[next_handle])) ) { + // don't use this slot if loud sound + if ( (SoundVolumes[next_handle] > digi_volume) && + (ntries= digi_max_channels ) + next_handle = 0; + ntries++; + goto TryNextChannel; + } + //mprintf(( 0, "[SS:%d]", next_handle )); + if (voice_check(next_handle)) + mprintf((0,"Sound: deallocating used voice %d sound %d vol %d pos %d/%d\n", next_handle, SoundNums[next_handle], SoundVolumes[next_handle], voice_get_position(next_handle), GameSounds[SoundNums[next_handle]].len)); + deallocate_voice(SampleHandles[next_handle]); + SampleHandles[next_handle] = INVALID_CHANNEL; + } + + if ( SoundNums[next_handle] != -1 ) { + digi_unlock_sound_data(SoundNums[next_handle]); + SoundNums[next_handle] = -1; + } + ret_slot = next_handle; + next_handle++; + if ( next_handle >= digi_max_channels ) + next_handle = 0; + return ret_slot; +} + +CHANNEL digi_start_sound(int soundnum, int volume, int pan) { + int i; + int channel; + int slot; + + volume = fixmul(volume, digi_volume); + slot = get_free_slot(); + + digi_lock_sound_data(soundnum); + channel = play_sample(&GameSounds[soundnum], volume, pan >> 8, 1000, 0); + if (channel < 0) { + mprintf(( 1, "NOT ENOUGH SOUND SLOTS!!!\n" )); + digi_unlock_sound_data(soundnum); + return -1; + } + release_voice(channel); + + //mprintf(( 0, "Starting sound on channel %d\n", channel )); + #ifndef NDEBUG + verify_channel_not_used_by_soundobjects(channel); + #endif + + // find slots pointing to just allocated channel and kill sounds on it + // (because they can't be playing right now) + for (i=0; i 127 ) +//-killed- midi_volume = 127; +//-killed- else if ( mvolume < 0 ) +//-killed- midi_volume = 0; +//-killed- else +//-killed- midi_volume = mvolume; +//-killed- +//-killed- if ( (digi_midi_type > 0) ) { +//-killed- if ( (old_volume < 1) && ( midi_volume > 1 ) ) { +//-killed- if (SongHandle == NULL ) +//-killed- digi_play_midi_song( digi_last_midi_song, digi_last_melodic_bank, digi_last_drum_bank, 1 ); +//-killed- } +//-killed- set_volume(-1, midi_volume * 2 + (midi_volume & 1)); +//-killed- } +//-killed- } + +void digi_set_digi_volume( int dvolume ) +{ + dvolume = fixmuldiv( dvolume, _DIGI_MAX_VOLUME, 0x7fff); + if ( dvolume > _DIGI_MAX_VOLUME ) + digi_volume = _DIGI_MAX_VOLUME; + else if ( dvolume < 0 ) + digi_volume = 0; + else + digi_volume = dvolume; + + if ( !Digi_initialized ) return; + if ( digi_driver_board <= 0 ) return; + + digi_sync_sounds(); +} + +// 0-0x7FFF +void digi_set_volume( int dvolume, int mvolume ) +{ + digi_set_midi_volume( mvolume ); + digi_set_digi_volume( dvolume ); +// mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume )); +} + +//-killed- void digi_stop_current_song() +//-killed- { +//-killed- if (SongHandle) { +//-killed- destroy_midi(SongHandle); +//-killed- SongHandle = NULL; +//-killed- } +//-killed- } +//-killed- +//-killed- void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) +//-killed- { +//-killed- //char fname[128]; +//-killed- +//-killed- if (!Digi_initialized) return; +//-killed- if ( digi_midi_type <= 0 ) return; +//-killed- +//-killed- digi_stop_current_song(); +//-killed- +//-killed- if ( filename == NULL ) return; +//-killed- +//-killed- strcpy( digi_last_midi_song, filename ); +//-killed- strcpy( digi_last_melodic_bank, melodic_bank ); +//-killed- strcpy( digi_last_drum_bank, drum_bank ); +//-killed- +//-killed- if ( midi_volume < 1 ) +//-killed- +//-killed- SongHandle = NULL; +//-killed- +//-killed- #if 0 /* needs bank loading to sound right */ +//-killed- if (midi_card <= 4) { /* FM cards */ +//-killed- int sl; +//-killed- sl = strlen( filename ); +//-killed- strcpy( fname, filename ); +//-killed- fname[sl-1] = 'q'; +//-killed- SongHandle = load_hmp(fname); +//-killed- } +//-killed- #endif +//-killed- +//-killed- if ( !SongHandle ) +//-killed- SongHandle = load_hmp(filename); +//-killed- +//-killed- if (SongHandle) { +//-killed- if (play_midi(SongHandle, loop)) { +//-killed- destroy_midi(SongHandle); +//-killed- SongHandle = NULL; +//-killed- } +//-killed- } +//-killed- if (!SongHandle) { +//-killed- mprintf( (1, "\nAllegro Error : %s", allegro_error )); +//-killed- } +//-killed- } + +void digi_get_sound_loc( vms_matrix * listener, vms_vector * listener_pos, int listener_seg, vms_vector * sound_pos, int sound_seg, fix max_volume, int *volume, int *pan, fix max_distance ) +{ + vms_vector vector_to_sound; + fix angle_from_ear, cosang,sinang; + fix distance; + fix path_distance; + + *volume = 0; + *pan = 0; + + max_distance = (max_distance*5)/4; // Make all sounds travel 1.25 times as far. + + // Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation. + distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos ); + + if (distance < max_distance ) { + int num_search_segs = f2i(max_distance/20); + if ( num_search_segs < 1 ) num_search_segs = 1; + + path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG ); + if ( path_distance > -1 ) { + *volume = max_volume - fixdiv(path_distance,max_distance); + //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume )); + if (*volume > 0 ) { + angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec); + fix_sincos(angle_from_ear,&sinang,&cosang); + //mprintf( (0, "volume is %.2f\n", f2fl(*volume) )); + if (Config_channels_reversed) cosang *= -1; + *pan = (cosang + F1_0)/2; + } else { + *volume = 0; + } + } + } +} + +void digi_init_sounds() +{ + int i; + + if (!Digi_initialized) return; + if (digi_driver_board<1) return; + + digi_reset_digi_sounds(); + + for (i=0; i> 8, /* 0-255 */ + 1000, + (SoundObjects[i].flags & SOF_PLAY_FOREVER) ? 1 : 0 + ); + if (SoundObjects[i].handle < 0) { + mprintf(( 1, "NOT ENOUGH SOUND SLOTS!!! (SoundObject)\n" )); + //digi_unlock_sound(SoundObjects[i].soundnum); //never unlocked... + } else { + SoundObjects[i].flags |= SOF_PLAYING; + reset_slots_on_channel( SoundObjects[i].handle ); + } +} + +int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance ) +{ + int i,volume,pan; + object * objp; + int soundnum; + + soundnum = digi_xlat_sound(org_soundnum); + + if ( max_volume < 0 ) return -1; +// if ( max_volume > F1_0 ) max_volume = F1_0; + + if (!Digi_initialized) return -1; + if (soundnum < 0 ) return -1; + if (GameSounds[soundnum].data==NULL) { + Int3(); + return -1; + } + if ((objnum<0)||(objnum>Highest_object_index)) + return -1; + if (digi_driver_board<1) return -1; + + if ( !forever ) { + // Hack to keep sounds from building up... + digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance ); + digi_play_sample_3d( org_soundnum, pan, volume, 0 ); + return -1; + } + + for (i=0; iorient, &Viewer->pos, Viewer->segnum, + &objp->pos, objp->segnum, SoundObjects[i].max_volume, + &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); + + if (!forever || SoundObjects[i].volume >= MIN_VOLUME) + digi_start_sound_object(i); + + return SoundObjects[i].signature; +} + +int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume ) +{ // 10 segs away + return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0 ); +} + +int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance ) +{ + int i, volume, pan; + int soundnum; + + soundnum = digi_xlat_sound(org_soundnum); + + if ( max_volume < 0 ) return -1; +// if ( max_volume > F1_0 ) max_volume = F1_0; + + if (!Digi_initialized) return -1; + if (soundnum < 0 ) return -1; + if (GameSounds[soundnum].data==NULL) { + Int3(); + return -1; + } + if (digi_driver_board<1) return -1; + + if ((segnum<0)||(segnum>Highest_segment_index)) + return -1; + + if ( !forever ) { + // Hack to keep sounds from building up... + digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance ); + digi_play_sample_3d( org_soundnum, pan, volume, 0 ); + return -1; + } + + for (i=0; iorient, &Viewer->pos, Viewer->segnum, + &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum, + SoundObjects[i].max_volume, + &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); + + if (!forever || SoundObjects[i].volume >= MIN_VOLUME) + digi_start_sound_object(i); + + return SoundObjects[i].signature; +} + +int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume ) +{ + return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 ); +} + +void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum ) +{ + int i,killed; + + soundnum = digi_xlat_sound(soundnum); + + if (!Digi_initialized) return; + if (digi_driver_board<1) return; + + killed = 0; + + for (i=0; i 1 ) { + mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum )); + } +} + +void digi_kill_sound_linked_to_object( int objnum ) +{ + int i,killed; + + if (!Digi_initialized) return; + if (digi_driver_board<1) return; + + killed = 0; + + for (i=0; i 1 ) { + mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum )); + } +} + +void digi_sync_sounds() +{ + int i; + int oldvolume, oldpan; + + if (!Digi_initialized) return; + if (digi_driver_board<1) return; + + for (i=0; iorient, &Viewer->pos, Viewer->segnum, + &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum, + SoundObjects[i].max_volume, + &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); + + } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) { + object * objp; + + objp = &Objects[SoundObjects[i].lo_objnum]; + + if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) { + // The object that this is linked to is dead, so just end this sound if it is looping. + if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) { + deallocate_voice(SoundObjects[i].handle); + } + SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound + continue; // Go on to next sound... + } else { + digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, + &objp->pos, objp->segnum, SoundObjects[i].max_volume, + &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); + } + } + + if (oldvolume != SoundObjects[i].volume) { + if ( SoundObjects[i].volume < MIN_VOLUME ) { + // Sound is too far away, so stop it from playing. + if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) { + deallocate_voice(SoundObjects[i].handle); + SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing + } + } else { + if (!(SoundObjects[i].flags & SOF_PLAYING)) { + digi_start_sound_object(i); + } else { + voice_set_volume(SoundObjects[i].handle, fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0)); + } + } + } + + if (oldpan != SoundObjects[i].pan) { + if (SoundObjects[i].flags & SOF_PLAYING) + voice_set_pan(SoundObjects[i].handle, SoundObjects[i].pan >> 8); + } + } + } +} + +int sound_paused = 0; + +void digi_pause_all() +{ + int i; + + if (!Digi_initialized) return; + + if (sound_paused==0) { +// if ( digi_midi_type > 0 ) { +// if (SongHandle) +// midi_pause(); +// } + digi_midi_pause(); + if (digi_driver_board>0) { + for (i=0; i 0 ); + + if (sound_paused==1) { + // resume sound here +// if ( digi_midi_type > 0 ) { +// if (SongHandle) +// midi_resume(); +// } + digi_midi_resume(); + } + sound_paused--; +} + +void digi_stop_all() +{ + int i; + + if (!Digi_initialized) return; + +// if ( digi_midi_type > 0 ) { +// if (SongHandle) { +// destroy_midi(SongHandle); +// SongHandle = NULL; +// } +// } + digi_midi_stop(); + + if (digi_driver_board>0) { + for (i=0; i0) { + for (i=0; ivoices, digi_max_channels, digi_total_locks, + active_slots,done_slots,allg_used, next_handle); +} +#endif diff --git a/arch/dos/digimm.c b/arch/dos/digimm.c new file mode 100644 index 00000000..34087a7a --- /dev/null +++ b/arch/dos/digimm.c @@ -0,0 +1,996 @@ +// SDL digital audio support + +#include +#include +#include + +#include "mm_drv.h" +#include "timer.h" + +//#include "SDL.h" +//#include "SDL_audio.h" + +#include "error.h" +#include "mono.h" +#include "fix.h" +#include "vecmat.h" +#include "gr.h" // needed for piggy.h +#include "piggy.h" +#include "digi.h" +#include "sounds.h" +#include "wall.h" +#include "newdemo.h" +#include "kconfig.h" +#include "midiallg.h" + +int digi_driver_board = 0; +int digi_driver_port = 0; +int digi_driver_irq = 0; +int digi_driver_dma = 0; +//int digi_midi_type = 0; // Midi driver type +//int digi_midi_port = 0; // Midi driver port +int digi_timer_rate = 9943; // rate for the timer to go off to handle the driver system (120 Hz) + +#ifndef ALLG_MIDI +/* stub vars/functions for midi */ +int digi_midi_type = 0; +int digi_midi_port = 0; + +void digi_set_midi_volume( int mvolume ) {} +void digi_play_midi_song( char * filename, char * melodic_bank, +char * drum_bank, int loop ) {} +void digi_midi_pause() {} +void digi_midi_resume() {} +void digi_midi_stop() {} +#endif + + +//added on 980905 by adb to add inline fixmul for mixer on i386 +#ifdef __i386__ +#define do_fixmul(x,y) \ +({ \ + int _ax, _dx; \ + asm("imull %2\n\tshrdl %3,%1,%0" \ + : "=a"(_ax), "=d"(_dx) \ + : "rm"(y), "i"(16), "0"(x)); \ + _ax; \ +}) +extern inline fix fixmul(fix x, fix y) { return do_fixmul(x,y); } +#endif +//end edit by adb + +//changed on 980905 by adb to increase number of concurrent sounds +#define MAX_SOUND_SLOTS 32 +//end changes by adb +#define SOUND_BUFFER_SIZE 512 + +#define MIN_VOLUME 10 + +/* This table is used to add two sound values together and pin + * the value to avoid overflow. (used with permission from ARDI) + * DPH: Taken from SDL/src/SDL_mixer.c. + */ +static const unsigned char mix8[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, + 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, + 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, + 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, + 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, + 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, + 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, + 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, + 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, + 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, + 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, + 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, + 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, + 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +}; + +#define SOF_USED 1 // Set if this sample is used +#define SOF_PLAYING 2 // Set if this sample is playing on a channel +#define SOF_LINK_TO_OBJ 4 // Sound is linked to a moving object. If object dies, then finishes play and quits. +#define SOF_LINK_TO_POS 8 // Sound is linked to segment, pos +#define SOF_PLAY_FOREVER 16 // Play forever (or until level is stopped), otherwise plays once + +typedef struct sound_object { + short signature; // A unique signature to this sound + ubyte flags; // Used to tell if this slot is used and/or currently playing, and how long. + fix max_volume; // Max volume that this sound is playing at + fix max_distance; // The max distance that this sound can be heard at... + int volume; // Volume that this sound is playing at + int pan; // Pan value that this sound is playing at + int handle; // What handle this sound is playing on. Valid only if SOF_PLAYING is set. + short soundnum; // The sound number that is playing + union { + struct { + short segnum; // Used if SOF_LINK_TO_POS field is used + short sidenum; + vms_vector position; + }pos; + struct { + short objnum; // Used if SOF_LINK_TO_OBJ field is used + short objsignature; + }obj; + }link; +} sound_object; +#define lp_segnum link.pos.segnum +#define lp_sidenum link.pos.sidenum +#define lp_position link.pos.position + +#define lo_objnum link.obj.objnum +#define lo_objsignature link.obj.objsignature + +#define MAX_SOUND_OBJECTS 16 +sound_object SoundObjects[MAX_SOUND_OBJECTS]; +short next_signature=0; + +//added/changed on 980905 by adb to make sfx volume work +#define SOUND_MAX_VOLUME (F1_0/2) // don't use real max like in original +int digi_volume = SOUND_MAX_VOLUME; +//end edit by adb + +int digi_lomem = 0; + +static int digi_initialised = 0; +static int timer_system_initialized = 0; + +struct sound_slot { + int soundno; + int playing; // Is there a sample playing on this channel? + int looped; // Play this sample looped? + fix pan; // 0 = far left, 1 = far right + fix volume; // 0 = nothing, 1 = fully on + //changed on 980905 by adb from char * to unsigned char * + unsigned char *samples; + //end changes by adb + unsigned int length; // Length of the sample + unsigned int position; // Position we are at at the moment. +} SoundSlots[MAX_SOUND_SLOTS]; + +//static SDL_AudioSpec WaveSpec; +static int digi_sounds_initialized = 0; + +//added on 980905 by adb to add rotating/volume based sound kill system +static int digi_max_channels = 16; +static int next_handle = 0; +int SampleHandles[32]; +void reset_sounds_on_channel(int channel); +//end edit by adb + +void digi_reset_digi_sounds(void); + +/* Audio mixing callback */ +//changed on 980905 by adb to cleanup, add pan support and optimize mixer +ULONG VC_WriteBytes(SBYTE *stream, ULONG len) +{ + unsigned char *streamend; + struct sound_slot *sl; + +// if (grd_curscreen) +// grd_curscreen->sc_canvas.cv_bitmap.bm_data[8]++; + len &= ~1; /* stereo -> always write 2 byte pairs */ + streamend = stream + len; + +#if 0 +{ + static int n = 0; + while(stream < streamend) { + *(stream++) = (n & 256) ? 256 - (n & 255) : (n & 255); + n++; + } + return len; +} +#endif + + memset(stream, 0x80, len); + + for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++) + { + if (sl->playing) + { + unsigned char *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length; + unsigned char *sp = stream; + signed char v; + fix vl, vr; + int x; + + if ((x = sl->pan) & 0x8000) + { + vl = 0x20000 - x * 2; + vr = 0x10000; + } + else + { + vl = 0x10000; + vr = x * 2; + } + vl = fixmul(vl, (x = sl->volume)); + vr = fixmul(vr, x); + while (sp < streamend) + { + if (sldata == slend) + { + if (!sl->looped) + { + sl->playing = 0; + break; + } + sldata = sl->samples; + } + v = *(sldata++) - 0x80; + *(sp++) = mix8[ *sp + fixmul(v, vl) + 0x80 ]; + *(sp++) = mix8[ *sp + fixmul(v, vr) + 0x80 ]; + } + sl->position = sldata - sl->samples; + } + } + return len; +} +//end changes by adb + +extern MDRIVER drv_sb; +MDRIVER *drv = &drv_sb; +char allegro_error[128]; + +int md_mode = DMODE_STEREO; +int md_mixfreq = 11025; +int md_dmabufsize = 1024; + +void install_int_ex(void (*)(), long speed); +void remove_int(void(*)()); + +void mm_timer() { + drv->Update(); +// if (grd_curscreen) +// (*grd_curscreen->sc_canvas.cv_bitmap.bm_data)++; +} + +/* Initialise audio devices. */ +int digi_init() +{ + //added on 980905 by adb to init sound kill system + memset(SampleHandles, 255, sizeof(SampleHandles)); + //end edit by adb + + #if 0 + WaveSpec.freq = 11025; + WaveSpec.format = AUDIO_U8 | AUDIO_STEREO; + WaveSpec.samples = SOUND_BUFFER_SIZE; + WaveSpec.callback = audio_mixcallback; + + if ( SDL_OpenAudio(&WaveSpec, NULL) < 0 ) { + printf("Couldn't open audio: %s\n", SDL_GetError()); + exit(2); + } + SDL_PauseAudio(0); +#endif + if (!drv->Init()) { + printf("Couldn't open audio: %s", myerr); + return -1; + } + drv->PlayStart(); + + if (!timer_system_initialized) + { + #ifdef ALLG_MIDI + install_int_ex(mm_timer, digi_timer_rate); + #else + timer_set_function(mm_timer); + #endif + timer_system_initialized = 1; + } + + #ifdef ALLG_MIDI + digi_midi_init(); + #endif + + atexit(digi_close); + digi_initialised = 1; + return 0; +} + +/* Toggle audio */ +void digi_reset() { } + +/* Shut down audio */ +void digi_close() +{ + if (!digi_initialised) return; + digi_initialised = 0; + drv->PlayStop(); + drv->Exit(); + if (timer_system_initialized) + { + #ifdef ALLG_MIDI + remove_int(mm_timer); + #else + timer_set_function(NULL); + #endif + timer_system_initialized = 0; + } + #ifdef ALLG_MIDI + digi_midi_close(); + #endif +} + +/* Find the sound which actually equates to a sound number */ +int digi_xlat_sound(int soundno) +{ + if ( soundno < 0 ) return -1; + + if ( digi_lomem ) { + soundno = AltSounds[soundno]; + if ( soundno == 255 ) return -1; + } + return Sounds[soundno]; +} + +static int get_free_slot() +{ + int i; + for (i=0; i= 0) && (SoundSlots[SampleHandles[next_handle]].playing) ) + { + if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries= digi_max_channels ) + next_handle = 0; + ntries++; + goto TryNextChannel; + } + //mprintf(( 0, "[SS:%d]", next_handle )); + SoundSlots[SampleHandles[next_handle]].playing = 0; + SampleHandles[next_handle] = -1; + } + //end edit by adb + + slot = get_free_slot(); + if (slot<0) return -1; + + if (volume > F2_0) + volume = F2_0; + SoundSlots[slot].soundno = soundnum; + SoundSlots[slot].samples = GameSounds[soundnum].data; + SoundSlots[slot].length = GameSounds[soundnum].length; + SoundSlots[slot].volume = fixmul(digi_volume, volume); + SoundSlots[slot].pan = pan; + SoundSlots[slot].position = 0; + SoundSlots[slot].looped = 0; + SoundSlots[slot].playing = 1; + + //added on 980905 by adb to add sound kill system from original sos digi.c + reset_sounds_on_channel(slot); + SampleHandles[next_handle] = slot; + next_handle++; + if ( next_handle >= digi_max_channels ) + next_handle = 0; + //end edit by adb + + return slot; +} + + //added on 980905 by adb to add sound kill system from original sos digi.c +void reset_sounds_on_channel( int channel ) +{ + int i; + + for (i=0; i -1 ) { + *volume = max_volume - fixdiv(path_distance,max_distance); + //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume )); + if (*volume > 0 ) { + angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec); + fix_sincos(angle_from_ear,&sinang,&cosang); + //mprintf( (0, "volume is %.2f\n", f2fl(*volume) )); + if (Config_channels_reversed) cosang *= -1; + *pan = (cosang + F1_0)/2; + } else { + *volume = 0; + } + } + } +} + +int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance ) +{ + int i,volume,pan; + object * objp; + int soundnum; + + soundnum = digi_xlat_sound(org_soundnum); + + if ( max_volume < 0 ) return -1; +// if ( max_volume > F1_0 ) max_volume = F1_0; + + if (!digi_initialised) return -1; + if (soundnum < 0 ) return -1; + if (GameSounds[soundnum].data==NULL) { + Int3(); + return -1; + } + if ((objnum<0)||(objnum>Highest_object_index)) + return -1; + + if ( !forever ) { + // Hack to keep sounds from building up... + digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance ); + digi_play_sample_3d( org_soundnum, pan, volume, 0 ); + return -1; + } + + for (i=0; iorient, &Viewer->pos, Viewer->segnum, + &objp->pos, objp->segnum, SoundObjects[i].max_volume, + &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); + + if (!forever || SoundObjects[i].volume >= MIN_VOLUME) + digi_start_sound_object(i); + + return SoundObjects[i].signature; +} + +int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume ) +{ return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); } + +int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance ) +{ + int i, volume, pan; + int soundnum; + + soundnum = digi_xlat_sound(org_soundnum); + + if ( max_volume < 0 ) return -1; +// if ( max_volume > F1_0 ) max_volume = F1_0; + + if (!digi_initialised) return -1; + if (soundnum < 0 ) return -1; + if (GameSounds[soundnum].data==NULL) { + Int3(); + return -1; + } + + if ((segnum<0)||(segnum>Highest_segment_index)) + return -1; + + if ( !forever ) { + // Hack to keep sounds from building up... + digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance ); + digi_play_sample_3d( org_soundnum, pan, volume, 0 ); + return -1; + } + + for (i=0; iorient, &Viewer->pos, Viewer->segnum, + &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum, + SoundObjects[i].max_volume, + &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); + + if (!forever || SoundObjects[i].volume >= MIN_VOLUME) + digi_start_sound_object(i); + + return SoundObjects[i].signature; +} + +int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume ) +{ + return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 ); +} + +void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum ) +{ + int i,killed; + + soundnum = digi_xlat_sound(soundnum); + + if (!digi_initialised) return; + + killed = 0; + + for (i=0; i 1 ) { + mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum )); + } +} + +void digi_kill_sound_linked_to_object( int objnum ) +{ + int i,killed; + + if (!digi_initialised) return; + + killed = 0; + + for (i=0; i 1 ) { + mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum )); + } +} + +void digi_sync_sounds() +{ + int i; + int oldvolume, oldpan; + + if (!digi_initialised) return; + + for (i=0; iorient, &Viewer->pos, Viewer->segnum, + &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum, + SoundObjects[i].max_volume, + &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); + + } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) { + object * objp; + + objp = &Objects[SoundObjects[i].lo_objnum]; + + if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) { + // The object that this is linked to is dead, so just end this sound if it is looping. + if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) { + SoundSlots[SoundObjects[i].handle].playing = 0; + } + SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound + continue; // Go on to next sound... + } else { + digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, + &objp->pos, objp->segnum, SoundObjects[i].max_volume, + &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); + } + } + + if (oldvolume != SoundObjects[i].volume) { + if ( SoundObjects[i].volume < MIN_VOLUME ) { + // Sound is too far away, so stop it from playing. + if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) { + SoundSlots[SoundObjects[i].handle].playing = 0; + SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing + } + } else { + if (!(SoundObjects[i].flags & SOF_PLAYING)) { + digi_start_sound_object(i); + } else { + SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0); + } + } + } + + if (oldpan != SoundObjects[i].pan) { + if (SoundObjects[i].flags & SOF_PLAYING) + SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan; + } + } + } +} + +void digi_stop_soundobjects() { + int i; + + for (i=0; i SOUND_MAX_VOLUME ) + digi_volume = SOUND_MAX_VOLUME; + else if ( dvolume < 0 ) + digi_volume = 0; + else + digi_volume = dvolume; + + if ( !digi_initialised ) return; + + digi_sync_sounds(); +} +//end edit by adb + +//void digi_set_volume( int dvolume, int mvolume ) {} +void digi_set_volume( int dvolume, int mvolume ) +{ + digi_set_midi_volume(mvolume); + digi_set_digi_volume(dvolume); +} + + +int digi_is_sound_playing(int soundno) +{ + int i; + + soundno = digi_xlat_sound(soundno); + + for (i = 0; i < MAX_SOUND_SLOTS; i++) + //changed on 980905 by adb: added SoundSlots[i].playing && + if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno) + //end changes by adb + return 1; + return 0; +} + + +//void digi_pause_all() { } +//void digi_resume_all() { } +//void digi_stop_all() { } + + //added on 980905 by adb to make sound channel setting work +void digi_set_max_channels(int n) { + digi_max_channels = n; + + if ( digi_max_channels < 1 ) + digi_max_channels = 1; + if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) ) + digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS); + + if ( !digi_initialised ) return; + + digi_reset_digi_sounds(); +} + +int digi_get_max_channels() { + return digi_max_channels; +} +// end edit by adb + +void digi_reset_digi_sounds() +{ + int i; + + for (i=0; i< MAX_SOUND_SLOTS; i++) + SoundSlots[i].playing=0; + + //added on 980905 by adb to reset sound kill system + memset(SampleHandles, 255, sizeof(SampleHandles)); + next_handle = 0; + //end edit by adb +} + +int sound_paused = 0; + +void digi_pause_all() +{ + if (!digi_initialised) return; + if (sound_paused==0) { + digi_midi_pause(); + digi_stop_soundobjects(); + } + sound_paused++; +} + +void digi_resume_all() +{ + if (!digi_initialised) return; + + Assert( sound_paused > 0 ); + + if (sound_paused==1) { + digi_midi_resume(); + } + sound_paused--; +} + +void digi_stop_all() +{ + if (!digi_initialised) return; + + digi_midi_stop(); + + digi_stop_soundobjects(); +} + +// mikmod stubs... +BOOL VC_Init(void) { return 1; } +void VC_Exit(void) { } +BOOL VC_SetNumVoices(void) { return 0; } +ULONG VC_SampleSpace(int type) { return 0; } +ULONG VC_SampleLength(int type, SAMPLE *s) { return 0; } + +BOOL VC_PlayStart(void) { return 0; } +void VC_PlayStop(void) { } + +#if 0 +SWORD VC_SampleLoad(SAMPLOAD *sload, int type, FILE *fp) { return 0; } +#else +SWORD VC_SampleLoad(FILE *fp,ULONG size,ULONG reppos,ULONG repend,UWORD flags) { return 0; } +#endif +void VC_SampleUnload(SWORD handle) { } + +void VC_WriteSamples(SBYTE *buf,ULONG todo) { } +void VC_SilenceBytes(SBYTE *buf,ULONG todo) { } + +#if 0 +void VC_VoiceSetVolume(UBYTE voice, UWORD vol) { } +void VC_VoiceSetPanning(UBYTE voice, ULONG pan) { } +#else +void VC_VoiceSetVolume(UBYTE voice, UBYTE vol) { } +void VC_VoiceSetPanning(UBYTE voice, UBYTE pan) { } +#endif +void VC_VoiceSetFrequency(UBYTE voice, ULONG frq) { } +void VC_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags) { } + +void VC_VoiceStop(UBYTE voice) { } +BOOL VC_VoiceStopped(UBYTE voice) { return 0; } +void VC_VoiceReleaseSustain(UBYTE voice) { } +SLONG VC_VoiceGetPosition(UBYTE voice) { return 0; } +ULONG VC_VoiceRealVolume(UBYTE voice) { return 0; } +char *myerr; diff --git a/arch/dos/disk.c b/arch/dos/disk.c new file mode 100644 index 00000000..13088eb6 --- /dev/null +++ b/arch/dos/disk.c @@ -0,0 +1,17 @@ +#include +#include +#include "types.h" +#include "error.h" + +unsigned long getdiskfree() { + struct diskfree_t dfree; + unsigned drive; + + _dos_getdrive(&drive); + if (!_dos_getdiskfree(drive, &dfree)) + return dfree.avail_clusters * dfree.sectors_per_cluster * dfree.bytes_per_sector; + else { + Int3(); // get MARK A!!!!! + return ULONG_MAX; // make be biggest it can be + } +} diff --git a/arch/dos/dosgr.c b/arch/dos/dosgr.c new file mode 100644 index 00000000..3d7fec02 --- /dev/null +++ b/arch/dos/dosgr.c @@ -0,0 +1,721 @@ +// Graphics functions for DOS. + +#include +#include +#include +#include +#include +#include "gr.h" +#include "grdef.h" +#include "palette.h" +#include "maths.h" +#include "u_mem.h" +#include "u_dpmi.h" +#include "vesa.h" +#include "modex.h" +#include "error.h" + +#include "gamefont.h" + +#ifdef __DJGPP__ +#include +#endif + +static int last_r=0, last_g=0, last_b=0; + +/* old gr.c stuff */ +unsigned char * gr_video_memory = (unsigned char *)0xa0000; + +char gr_pal_default[768]; + +int gr_installed = 0; + +volatile ubyte * pVideoMode = (volatile ubyte *)0x449; +volatile ushort * pNumColumns = (volatile ushort *)0x44a; +volatile ubyte * pNumRows = (volatile ubyte *)0x484; +volatile ushort * pCharHeight = (volatile ushort *)0x485; +volatile ushort * pCursorPos = (volatile ushort *)0x450; +volatile ushort * pCursorType = (volatile ushort *)0x460; +volatile ushort * pTextMemory = (volatile ushort *)0xb8000; + +typedef struct screen_save { + ubyte video_mode; + ubyte is_graphics; + ushort char_height; + ubyte width; + ubyte height; + ubyte cursor_x, cursor_y; + ubyte cursor_sline, cursor_eline; + ushort * video_memory; +} screen_save; + +screen_save gr_saved_screen; + +int gr_show_screen_info = 0; + +void gr_set_cellheight( ubyte height ) +{ + ubyte temp; + + outp( 0x3d4, 9 ); + temp = inp( 0x3d5 ); + temp &= 0xE0; + temp |= height; + outp( 0x3d5, temp ); +} + +void gr_set_linear() +{ + outpw( 0x3c4, 0xE04 ); // enable chain4 mode + outpw( 0x3d4, 0x4014 ); // turn on dword mode + outpw( 0x3d4, 0xa317 ); // turn off byte mode +} + +void gr_16_to_256() +{ + outpw( 0x3ce, 0x4005 ); // set Shift reg to 1 + + inp( 0x3da ); // dummy input + + outp( 0x3c0, 0x30 ); + outp( 0x3c0, 0x61 ); // turns on PCS & PCC + + inp( 0x3da ); // dummy input + + outp( 0x3c0, 0x33 ); + outp( 0x3c0, 0 ); +} + +void gr_turn_screen_off() +{ + ubyte temp; + temp = inp( 0x3da ); + outp( 0x3c0, 0 ); +} + +void gr_turn_screen_on() +{ + ubyte temp; + temp = inp( 0x3da ); + outp( 0x3c0, 0x20 ); +} + +void gr_set_misc_mode( uint mode ) +{ + union REGS regs; + + memset( ®s, 0, sizeof(regs) ); + regs.w.ax = mode; + int386( 0x10, ®s, ®s ); + +} + +void gr_set_3dbios_mode( uint mode ) +{ + union REGS regs; + memset( ®s, 0, sizeof(regs) ); + regs.w.ax = 0x4fd0; + regs.w.bx = 0x3d00 | (mode & 0xff); + int386( 0x10, ®s, ®s ); +} + + + +void gr_set_text_25() +{ + union REGS regs; + + regs.w.ax = 3; + int386( 0x10, ®s, ®s ); + +} + +void gr_set_text_43() +{ + union REGS regs; + + regs.w.ax = 0x1201; + regs.w.bx = 0x30; + int386( 0x10, ®s, ®s ); + + regs.w.ax = 3; + int386( 0x10, ®s, ®s ); + + regs.w.ax = 0x1112; + regs.w.bx = 0x0; + int386( 0x10, ®s, ®s ); +} + +void gr_set_text_50() +{ + union REGS regs; + + regs.w.ax = 0x1202; + regs.w.bx = 0x30; + int386( 0x10, ®s, ®s ); + + regs.w.ax = 3; + int386( 0x10, ®s, ®s ); + + regs.w.ax = 0x1112; + regs.w.bx = 0x0; + int386( 0x10, ®s, ®s ); +} + +ubyte is_graphics_mode() +{ + byte tmp; + tmp = inp( 0x3DA ); // Reset flip-flip + outp( 0x3C0, 0x30 ); // Select attr register 10 + tmp = inp( 0x3C1 ); // Get graphics/text bit + return tmp & 1; +} + +void gr_setcursor(ubyte x, ubyte y, ubyte sline, ubyte eline) +{ + union REGS regs; + + memset( ®s, 0, sizeof(regs) ); + regs.w.ax = 0x0200; + regs.w.bx = 0; + regs.h.dh = y; + regs.h.dl = x; + int386( 0x10, ®s, ®s ); + + memset( ®s, 0, sizeof(regs) ); + regs.w.ax = 0x0100; + regs.h.ch = sline & 0xf; + regs.h.cl = eline & 0xf; + int386( 0x10, ®s, ®s ); +} + +void gr_getcursor(ubyte *x, ubyte *y, ubyte * sline, ubyte * eline) +{ + union REGS regs; + + memset( ®s, 0, sizeof(regs) ); + regs.w.ax = 0x0300; + regs.w.bx = 0; + int386( 0x10, ®s, ®s ); + *y = regs.h.dh; + *x = regs.h.dl; + *sline = regs.h.ch; + *eline = regs.h.cl; +} + + +int gr_save_mode() +{ + int i; + + gr_saved_screen.is_graphics = is_graphics_mode(); + gr_saved_screen.video_mode = *pVideoMode; + + if (!gr_saved_screen.is_graphics) { + gr_saved_screen.width = *pNumColumns; + gr_saved_screen.height = *pNumRows+1; + gr_saved_screen.char_height = *pCharHeight; + gr_getcursor(&gr_saved_screen.cursor_x, &gr_saved_screen.cursor_y, &gr_saved_screen.cursor_sline, &gr_saved_screen.cursor_eline ); + MALLOC(gr_saved_screen.video_memory,ushort, gr_saved_screen.width*gr_saved_screen.height ); + for (i=0; i < gr_saved_screen.width*gr_saved_screen.height; i++ ) + gr_saved_screen.video_memory[i] = pTextMemory[i]; + } + + if (gr_show_screen_info ) { + printf( "Current video mode 0x%x:\n", gr_saved_screen.video_mode ); + if (gr_saved_screen.is_graphics) + printf( "Graphics mode\n" ); + else { + printf( "Text mode\n" ); + printf( "( %d columns by %d rows)\n", gr_saved_screen.width, gr_saved_screen.height ); + printf( "Char height is %d pixel rows\n", gr_saved_screen.char_height ); + printf( "Cursor of type 0x%x,0x%x is at (%d, %d)\n", gr_saved_screen.cursor_sline, gr_saved_screen.cursor_eline,gr_saved_screen.cursor_x, gr_saved_screen.cursor_y ); + } + } + + return 0; +} + +int isvga() +{ + union REGS regs; + + memset( ®s, 0, sizeof(regs) ); + regs.w.ax = 0x1a00; + int386( 0x10, ®s, ®s ); + + if ( regs.h.al == 0x1a ) + return 1; + + return 0; +} + +void gr_restore_mode() +{ + int i; + + //gr_set_text_25(); + +#ifndef NOGRAPH + gr_palette_fade_out( gr_palette, 32, 0 ); + gr_palette_set_gamma(0); + if ( gr_saved_screen.video_mode == 3 ) { + switch( gr_saved_screen.height ) { + case 43: gr_set_text_43(); break; + case 50: gr_set_text_50(); break; + default: gr_set_text_25(); break; + } + } else { + gr_set_misc_mode(gr_saved_screen.video_mode); + } + if (gr_saved_screen.is_graphics==0) { + gr_sync_display(); + gr_sync_display(); + gr_palette_read( gr_pal_default ); + gr_palette_clear(); + for (i=0; i < gr_saved_screen.width*gr_saved_screen.height; i++ ) + pTextMemory[i]=gr_saved_screen.video_memory[i]; + gr_setcursor( gr_saved_screen.cursor_x, gr_saved_screen.cursor_y, gr_saved_screen.cursor_sline, gr_saved_screen.cursor_eline ); + gr_palette_faded_out = 1; + gr_palette_fade_in( gr_pal_default, 32, 0 ); + } +#endif + +} + +void gr_close() +{ + if (gr_installed==1) + { + gr_installed = 0; + gr_restore_mode(); + free(grd_curscreen); + if( gr_saved_screen.video_memory ) { + free(gr_saved_screen.video_memory); + gr_saved_screen.video_memory = NULL; + } + } +} + +#ifndef __DJGPP__ +int gr_vesa_setmode( int mode ) +{ + int retcode; + + retcode=gr_vesa_checkmode( mode ); + if ( retcode ) return retcode; + + return gr_vesa_setmodea( mode ); +} +#endif + + +int gr_set_mode(u_int32_t mode) +{ + int retcode; + unsigned int w,h,t,data, r; + + //JOHNgr_disable_default_palette_loading(); +#ifdef NOGRAPH +return 0; +#endif + switch(mode) + { + case SM_ORIGINAL: + return 0; + case SM(320,200)://0: + if (!isvga()) return 1; + gr_set_misc_mode(0x13); + w = 320; r = 320; h = 200; t=BM_LINEAR; data = (int)gr_video_memory; + break; + case SM(640,400)://SM_640x400V: + retcode = gr_vesa_setmode( 0x100 ); + if (retcode !=0 ) return retcode; + w = 640; r = 640; h = 400; t=BM_SVGA; data = 0; + break; + case SM(640,480)://SM_640x480V: + retcode = gr_vesa_setmode( 0x101 ); + if (retcode !=0 ) return retcode; + w = 640; r = 640; h = 480; t=BM_SVGA; data = 0; + break; + case SM(800,600)://SM_800x600V: + retcode = gr_vesa_setmode( 0x103 ); + if (retcode !=0 ) return retcode; + w = 800; r = 800; h = 600; t=BM_SVGA; data = 0; + break; + case SM(1024,768)://SM_1024x768V: + retcode = gr_vesa_setmode( 0x105 ); + if (retcode !=0 ) return retcode; + w = 1024; r = 1024; h = 768; t=BM_SVGA; data = 0; + break; +/* case SM_640x480V15: + retcode = gr_vesa_setmode( 0x110 ); + if (retcode !=0 ) return retcode; + w = 640; r = 640*2; h=480; t=BM_SVGA15; data = 0; + break; + case SM_800x600V15: + retcode = gr_vesa_setmode( 0x113 ); + if (retcode !=0 ) return retcode; + w = 800; r = 800*2; h=600; t=BM_SVGA15; data = 0; + break;*/ +// case 19: + case SM(320,100): + if (!isvga()) return 1; + gr_set_misc_mode(0x13); +// { +// ubyte x; +// x = inp( 0x3c5 ); +// x |= 8; +// outp( 0x3c5, x ); +// } + gr_set_cellheight( 3 ); + + w = 320; r = 320; h = 100; t=BM_LINEAR; data = (int)gr_video_memory; + break; +/* case 20: + retcode = gr_vesa_setmode( 0x102 ); + //gr_enable_default_palette_loading(); + if (retcode !=0 ) return retcode; + gr_16_to_256(); + gr_set_linear(); + //gr_set_cellheight( 1 ); + gr_vesa_setlogical( 400 ); + w = 400; r = 400; h = 600; t=BM_SVGA; data = 0; + break; + case 21: + if (!isvga()) return 1; + gr_set_misc_mode(0xd); + gr_16_to_256(); + gr_set_linear(); + gr_set_cellheight( 3 ); + w = 160; r = 160; h = 100; t=BM_LINEAR; data = (int)gr_video_memory; + break; + case //22: // 3dmax 320x400 + if (!isvga()) return 1; + gr_set_3dbios_mode(0x31); + //w = 320; r = 320/4; h = 400; t=BM_MODEX; data = 0; + w = 320; r = 320; h = 400; t=BM_SVGA; data = 0; + break;*/ + default: + if (!isvga()) return 1; + if (mode==SM(320,240)) + w = gr_modex_setmode( 2 ); + else if (mode==SM(320,400)) + w = gr_modex_setmode( 6 ); + else + Error("unhandled vid mode\n"); + //gr_enable_default_palette_loading(); + h = w & 0xffff; w = w >> 16; r = w / 4;t = BM_MODEX; data = 0; + break; + } + gr_palette_clear(); + + memset( grd_curscreen, 0, sizeof(grs_screen)); + grd_curscreen->sc_mode = mode; + grd_curscreen->sc_w = w; + grd_curscreen->sc_h = h; + grd_curscreen->sc_aspect = fixdiv(grd_curscreen->sc_w*3,grd_curscreen->sc_h*4); + grd_curscreen->sc_canvas.cv_bitmap.bm_x = 0; + grd_curscreen->sc_canvas.cv_bitmap.bm_y = 0; + grd_curscreen->sc_canvas.cv_bitmap.bm_w = w; + grd_curscreen->sc_canvas.cv_bitmap.bm_h = h; + grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize = r; + grd_curscreen->sc_canvas.cv_bitmap.bm_type = t; + grd_curscreen->sc_canvas.cv_bitmap.bm_data = (unsigned char *)data; + gr_set_current_canvas(NULL); + + //gr_enable_default_palette_loading(); + gamefont_choose_game_font(w,h); + + return 0; +} + +int gr_init(int mode) +{ + int org_gamma; + int retcode; + + // Only do this function once! + if (gr_installed==1) + return 1; + +#ifdef __DJGPP__ + if (!__djgpp_nearptr_enable()) { + printf("nearptr enable=%x\n", __dpmi_error); + return 10; + } +#ifndef SAVEGR + gr_video_memory = (unsigned char *)(__djgpp_conventional_base + 0xa0000); +#else + gr_video_memory=(unsigned char *)-1; +#endif + pVideoMode = (volatile ubyte *)(__djgpp_conventional_base+0x449); + pNumColumns = (volatile ushort *)(__djgpp_conventional_base+0x44a); + pNumRows = (volatile ubyte *)(__djgpp_conventional_base+0x484); + pCharHeight = (volatile ushort *)(__djgpp_conventional_base+0x485); + pCursorPos = (volatile ushort *)(__djgpp_conventional_base+0x450); + pCursorType = (volatile ushort *)(__djgpp_conventional_base+0x460); + pTextMemory = (volatile ushort *)(__djgpp_conventional_base+0xb8000); +#endif +#ifndef __DJGPP__ + if (gr_init_A0000()) + return 10; +#endif + + // Save the current text screen mode + if (gr_save_mode()==1) + return 1; + +#ifndef NOGRAPH + // Save the current palette, and fade it out to black. + gr_palette_read( gr_pal_default ); + gr_palette_faded_out = 0; + org_gamma = gr_palette_get_gamma(); + gr_palette_set_gamma( 0 ); + gr_palette_fade_out( gr_pal_default, 32, 0 ); + gr_palette_clear(); + gr_palette_set_gamma( org_gamma ); + gr_sync_display(); + gr_sync_display(); +#endif + +#ifdef __DJGPP__ +#ifdef SAVEGR + __djgpp_nearptr_disable(); +#endif +#endif + + MALLOC( grd_curscreen,grs_screen,1 ); + memset( grd_curscreen, 0, sizeof(grs_screen)); + + // Set the mode. + if ((retcode=gr_set_mode(mode))) + { + gr_restore_mode(); + return retcode; + } + //JOHNgr_disable_default_palette_loading(); + + // Set all the screen, canvas, and bitmap variables that + // aren't set by the gr_set_mode call: + grd_curscreen->sc_canvas.cv_color = 0; + grd_curscreen->sc_canvas.cv_drawmode = 0; + grd_curscreen->sc_canvas.cv_font = NULL; + grd_curscreen->sc_canvas.cv_font_fg_color = 0; + grd_curscreen->sc_canvas.cv_font_bg_color = 0; + gr_set_current_canvas( &grd_curscreen->sc_canvas ); + +#if 0 + if (!dpmi_allocate_selector( &gr_fade_table, 256*GR_FADE_LEVELS, &gr_fade_table_selector )) + Error( "Error allocating fade table selector!" ); + + if (!dpmi_allocate_selector( &gr_palette, 256*3, &gr_palette_selector )) + Error( "Error allocating palette selector!" ); +#endif + +// if (!dpmi_allocate_selector( &gr_inverse_table, 32*32*32, &gr_inverse_table_selector )) +// Error( "Error allocating inverse table selector!" ); + + + // Set flags indicating that this is installed. + gr_installed = 1; +#ifdef __GNUC__ + + atexit((void (*)) gr_close); +#else + atexit(gr_close); +#endif + return 0; +} + +int gr_mode13_checkmode() +{ + if (isvga()) + return 0; + else + return 1; +} + +// 0=Mode set OK +// 1=No VGA adapter installed +// 2=Program doesn't support this VESA granularity +// 3=Monitor doesn't support that VESA mode.: +// 4=Video card doesn't support that VESA mode. +// 5=No VESA driver found. +// 6=Bad Status after VESA call/ +// 7=Not enough DOS memory to call VESA functions. +// 8=Error using DPMI. +// 9=Error setting logical line width. +// 10=Error allocating selector for A0000h +// 11=Not a valid mode support by gr.lib + +int gr_check_mode(u_int32_t mode) +{ + switch(mode) + { + case SM(320,100)://19: + case SM(320,200): + case SM(320,240): + case SM(360,200): + case SM(360,240): + case SM(376,282): + case SM(320,400): + case SM(320,480): + case SM(360,400): + case SM(360,480): + case SM(360,360): + case SM(376,308): + case SM(376,564): return gr_mode13_checkmode(); + case SM(640,400): return gr_vesa_checkmode( 0x100 ); + case SM(640,480): return gr_vesa_checkmode( 0x101 ); + case SM(800,600): return gr_vesa_checkmode( 0x103 ); + case SM(1024,768): return gr_vesa_setmode( 0x105 ); +// case SM_640x480V15: return gr_vesa_setmode( 0x110 ); +// case SM_800x600V15: return gr_vesa_setmode( 0x113 ); + } + return 11; +} + +/* Palette Stuff Starts Here... */ + +void gr_palette_step_up( int r, int g, int b ) +{ + int i; + ubyte *p; + int temp; + + if (gr_palette_faded_out) return; + + if ( (r==last_r) && (g==last_g) && (b==last_b) ) return; + + last_r = r; last_g = g; last_b = b; + + outp( 0x3c6, 0xff ); + outp( 0x3c8, 0 ); + p=gr_palette; + + for (i=0; i<256; i++ ) { + temp = (int)(*p++) + r + gr_palette_gamma; + if (temp<0) temp=0; + else if (temp>63) temp=63; + outp( 0x3c9, temp ); + temp = (int)(*p++) + g + gr_palette_gamma; + if (temp<0) temp=0; + else if (temp>63) temp=63; + outp( 0x3c9, temp ); + temp = (int)(*p++) + b + gr_palette_gamma; + if (temp<0) temp=0; + else if (temp>63) temp=63; + outp( 0x3c9, temp ); + } +} + + +void gr_palette_clear() +{ + int i; + outp( 0x3c6, 0xff ); + outp( 0x3c8, 0 ); + for (i=0; i<768; i++ ) { + outp( 0x3c9, 0 ); + } + gr_palette_faded_out = 1; +} + +void gr_palette_load( ubyte * pal ) +{ + int i; + ubyte c; + outp( 0x3c6, 0xff ); + outp( 0x3c8, 0 ); + for (i=0; i<768; i++ ) { + c = pal[i] + gr_palette_gamma; + if ( c > 63 ) c = 63; + outp( 0x3c9,c); + gr_current_pal[i] = pal[i]; + } + gr_palette_faded_out = 0; + + init_computed_colors(); +} + + +int gr_palette_fade_out(ubyte *pal, int nsteps, int allow_keys ) +{ + ubyte c; + int i,j; + fix fade_palette[768]; + fix fade_palette_delta[768]; + + if (gr_palette_faded_out) return 0; + + if (!pal) + pal = gr_current_pal; + + for (i=0; i<768; i++ ) { + fade_palette[i] = i2f(pal[i]+gr_palette_gamma); + fade_palette_delta[i] = fade_palette[i] / nsteps; + } + + for (j=0; j 63 ) c = 63; + outp( 0x3c9, c ); + } + } + gr_palette_faded_out = 1; + return 0; +} + +int gr_palette_fade_in(ubyte *pal, int nsteps, int allow_keys) +{ + int i,j; + ubyte c; + fix fade_palette[768]; + fix fade_palette_delta[768]; + + + if (!gr_palette_faded_out) return 0; + + for (i=0; i<768; i++ ) { + gr_current_pal[i] = pal[i]; + fade_palette[i] = 0; + fade_palette_delta[i] = i2f(pal[i]+gr_palette_gamma) / nsteps; + } + + for (j=0; j i2f(pal[i]+gr_palette_gamma) ) + fade_palette[i] = i2f(pal[i]+gr_palette_gamma); + c = f2i(fade_palette[i]); + if ( c > 63 ) c = 63; + outp( 0x3c9, c ); + } + } + gr_palette_faded_out = 0; + return 0; +} + +void gr_palette_read(ubyte * palette) +{ + int i; + outp( 0x3c6, 0xff ); + outp( 0x3c7, 0 ); + for (i=0; i<768; i++ ) { + *palette++ = inp( 0x3c9 ); + } +} + +void gr_update(void) +{ } diff --git a/arch/dos/dpmi.c b/arch/dos/dpmi.c new file mode 100644 index 00000000..8cb2a2ff --- /dev/null +++ b/arch/dos/dpmi.c @@ -0,0 +1,473 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/arch/dos/dpmi.c,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:15 $ + * + * Routines that access DPMI services... + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 21:58:16 donut + * Import of d1x 1.37 source. + * + * Revision 1.19 1995/02/23 09:02:57 john + * Fixed bug with dos_selector. + * + * Revision 1.18 1995/02/02 11:10:22 john + * Made real mode calls have a 2K stack. + * + * Revision 1.17 1995/01/14 19:20:28 john + * Added function to set a selector's base address. + * + * Revision 1.16 1994/12/14 16:11:40 john + * Locked down the memory referenced by GETDS. + * + * Revision 1.15 1994/12/06 16:08:06 john + * MAde memory checking return better results. + * + * Revision 1.14 1994/12/05 23:34:54 john + * Made dpmi_init lock down GETDS and chain_intr. + * + * Revision 1.13 1994/11/28 21:19:02 john + * Made memory checking a bit better. + * + * Revision 1.12 1994/11/28 20:22:18 john + * Added some variables that return the amount of available + * memory. + * + * Revision 1.11 1994/11/15 18:27:21 john + * *** empty log message *** + * + * Revision 1.10 1994/11/15 18:26:45 john + * Added verbose flag. + * + * Revision 1.9 1994/10/27 19:54:37 john + * Added unlock region function,. + * + * Revision 1.8 1994/10/05 16:17:31 john + * Took out locked down message. + * + * Revision 1.7 1994/10/03 17:21:20 john + * Added the code that allocates a 1K DOS buffer. + * + * Revision 1.6 1994/09/29 18:29:40 john + * Shorted mem info printout + * + * Revision 1.5 1994/09/27 11:54:35 john + * Added DPMI init function. + * + * Revision 1.4 1994/09/19 14:50:43 john + * Took out mono debug. + * + * Revision 1.3 1994/09/19 14:41:23 john + * Fixed some bugs with allocating selectors. + * + * Revision 1.2 1994/08/24 18:53:51 john + * Made Cyberman read like normal mouse; added dpmi module; moved + * mouse from assembly to c. Made mouse buttons return time_down. + * + * Revision 1.1 1994/08/24 10:22:34 john + * Initial revision + * + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: dpmi.c,v 1.1.1.1 2001-01-19 03:30:15 bradleyb Exp $"; +#endif + +#ifdef __DJGPP__ +#define _BORLAND_DOS_REGS 1 +#define far +#include +#include +#include +#define FP_SEG(p) _my_ds() +#define FP_OFF(p) (int)p + int _crt0_startup_flags=_CRT0_FLAG_NONMOVE_SBRK+_CRT0_FLAG_FILL_SBRK_MEMORY+_CRT0_FLAG_FILL_DEADBEEF+_CRT0_FLAG_NEARPTR+_CRT0_FLAG_NO_LFN; +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "types.h" +#include "mono.h" +#include "error.h" +#include "u_dpmi.h" + +int dpmi_find_dos_memory() +{ + union REGS r; + + memset(&r,0,sizeof(r)); + r.x.eax = 0x0100; // DPMI allocate DOS memory + r.x.ebx = 0xffff; // Number of paragraphs requested + int386 (0x31, &r, &r); + //if ( (r.x.eax & 0xffff) == 0x08 ) + //if ( (r.x.eax & 0xffff) == 0x08 ) + if ( r.x.cflag ) + return ((r.x.ebx & 0xffff)*16); + else + return 640*1024; +} + +void *dpmi_real_malloc( int size, ushort *selector ) +{ + union REGS r; + + memset(&r,0,sizeof(r)); + r.x.eax = 0x0100; // DPMI allocate DOS memory + r.x.ebx = (size + 15) >> 4; // Number of paragraphs requested + int386 (0x31, &r, &r); + + if (r.x.cflag) // Failed + return ((uint) 0); + + if(selector!=NULL) + *selector = r.x.edx & 0xFFFF; + +#ifdef __DJGPP__ + return (void *) ((r.x.eax & 0xFFFF) << 4)+__djgpp_conventional_base; +#else + return (void *) ((r.x.eax & 0xFFFF) << 4); +#endif +} + +void dpmi_real_free( ushort selector ) +{ + union REGS r; + + memset(&r,0,sizeof(r)); + r.x.eax = 0x0101; // DPMI free DOS memory + r.x.ebx = selector; // Selector to free + int386 (0x31, &r, &r); +} + +int dos_stack_initialized = 0; +ubyte * dos_stack = NULL; +ubyte * dos_stack_top = NULL; +#define DOS_STACK_SIZE (4*1024) // A big ol' 4K stack!!! + +static void dpmi_setup_stack(dpmi_real_regs *rregs) { + ushort temp_selector; + + if ( !dos_stack_initialized ) { + dos_stack_initialized = 1; + dos_stack = dpmi_real_malloc( DOS_STACK_SIZE, &temp_selector ); + if ( dos_stack == NULL ) { + printf( "Error allocating real mode stack!\n" ); + dos_stack_top = NULL; + } else { + dos_stack_top = &dos_stack[DOS_STACK_SIZE]; + } + } + + // Give this puppy a stack!!! + if ( dos_stack_top ) { + rregs->ss = DPMI_real_segment(dos_stack_top); + rregs->sp = DPMI_real_offset(dos_stack_top); + } +} + + +void dpmi_real_int386x( ubyte intno, dpmi_real_regs * rregs ) +{ + union REGS regs; + struct SREGS sregs; + + /* Use DMPI call 300h to issue the DOS interrupt */ + + dpmi_setup_stack(rregs); + memset(®s,0,sizeof(regs)); + memset(&sregs,0,sizeof(sregs)); + regs.w.ax = 0x0300; + regs.h.bl = intno; + regs.h.bh = 0; + regs.w.cx = 0; + sregs.es = FP_SEG(rregs); + regs.x.edi = FP_OFF(rregs); + int386x( 0x31, ®s, ®s, &sregs ); +} + +void dpmi_real_call(dpmi_real_regs * rregs) +{ + union REGS regs; + struct SREGS sregs; + + dpmi_setup_stack(rregs); + + /* Use DMPI call 301h to call real mode procedure */ + memset(®s,0,sizeof(regs)); + memset(&sregs,0,sizeof(sregs)); + regs.w.ax = 0x0301; + regs.h.bh = 0; + regs.w.cx = 0; + sregs.es = FP_SEG(rregs); + regs.x.edi = FP_OFF(rregs); + int386x( 0x31, ®s, ®s, &sregs ); + if ( regs.x.cflag ) + exit(regs.w.ax); +} + +int total_bytes = 0; + +int dpmi_unlock_region(void *address, unsigned length) +{ + union REGS regs; + unsigned int linear; + + linear = (unsigned int) address; +#ifdef __DJGPP__ + linear += __djgpp_base_address; +#endif + + total_bytes -= length; + //mprintf( 1, "DPMI unlocked %d bytes\n", total_bytes ); + + memset(®s,0,sizeof(regs)); + regs.w.ax = 0x601; // DPMI Unlock Linear Region + regs.w.bx = (linear >> 16); // Linear address in BX:CX + regs.w.cx = (linear & 0xFFFF); + + regs.w.si = (length >> 16); // Length in SI:DI + regs.w.di = (length & 0xFFFF); + int386 (0x31, ®s, ®s); + return (! regs.w.cflag); // Return 0 if can't lock +} + +int dpmi_lock_region(void *address, unsigned length) +{ + union REGS regs; + unsigned int linear; + + linear = (unsigned int) address; +#ifdef __DJGPP__ + linear += __djgpp_base_address; +#endif + + total_bytes += length; + //mprintf( 1, "DPMI Locked down %d bytes\n", total_bytes ); + + memset(®s,0,sizeof(regs)); + regs.w.ax = 0x600; // DPMI Lock Linear Region + regs.w.bx = (linear >> 16); // Linear address in BX:CX + regs.w.cx = (linear & 0xFFFF); + + regs.w.si = (length >> 16); // Length in SI:DI + regs.w.di = (length & 0xFFFF); + int386 (0x31, ®s, ®s); + return (! regs.w.cflag); // Return 0 if can't lock +} + + +int dpmi_modify_selector_base( ushort selector, void * address ) +{ + union REGS regs; + unsigned int linear; + + linear = (unsigned int)address; +#ifdef __DJGPP__ + linear += __djgpp_base_address; +#endif + + memset(®s,0,sizeof(regs)); + regs.w.ax = 0x0007; // DPMI Change Selector Base Addres + regs.w.bx = selector; // Selector to change + regs.w.cx = (linear >> 16); // Base address + regs.w.dx = (linear & 0xFFFF); + int386 (0x31, ®s, ®s); // call dpmi + if (regs.w.cflag) + return 0; // Return 0 if error + + return 1; +} + + +int dpmi_modify_selector_limit( ushort selector, int size ) +{ + union REGS regs; + unsigned int segment_limit; + + segment_limit = (unsigned int) size; + + memset(®s,0,sizeof(regs)); + regs.w.ax = 0x0008; // DPMI Change Selector Limit + regs.w.bx = selector; // Selector to change + regs.w.cx = (segment_limit >> 16); // Size of selector + regs.w.dx = (segment_limit & 0xFFFF); + int386 (0x31, ®s, ®s); // call dpmi + if (regs.w.cflag) + return 0; // Return 0 if error + + return 1; +} + + +int dpmi_allocate_selector( void * address, int size, ushort * selector ) +{ + union REGS regs; + + + memset(®s,0,sizeof(regs)); + regs.w.ax = 0; // DPMI Allocate Selector + regs.w.cx = 1; // Allocate 1 selector + int386 (0x31, ®s, ®s); // call dpmi + if (regs.w.cflag) + return 0; // Return 0 if error + *selector = regs.w.ax; + + if ( !dpmi_modify_selector_base( *selector, address ) ) + return 0; + + if ( !dpmi_modify_selector_limit( *selector, size ) ) + return 0; + +// mprintf( 0, "Selector 0x%4x has base of 0x%8x, size %d bytes\n", *selector, linear,segment_limit); + + return 1; +} + +static void * dpmi_dos_buffer = NULL; +static ushort dpmi_dos_selector = 0; + +void dpmi_close() +{ + if (dpmi_dos_selector!=0) { + dpmi_dos_buffer = NULL; + dpmi_dos_selector = 0; + } +} + +typedef struct mem_data { + int largest_block_bytes; + int max_unlocked_page_allocation; + int largest_lockable_pages; + int total_pages; + int unlocked_pages; + int unused_physical_pages; + int total_physical_pages; + int free_linear_pages; + int paging_size_pages; + int reserved[3]; +} mem_data; + +unsigned int dpmi_virtual_memory=0; +unsigned int dpmi_available_memory=0; +unsigned int dpmi_physical_memory=0; +unsigned int dpmi_dos_memory = 0; + +#ifdef __WATCOMC__ +extern void cdecl _GETDS(); +extern void cdecl cstart_(); +#endif + +int dpmi_init(int verbose) +{ + union REGS regs; + struct SREGS sregs; + mem_data mi; + + dpmi_dos_memory = dpmi_find_dos_memory(); + + dpmi_dos_buffer = dpmi_real_malloc( 1024, &dpmi_dos_selector); + if (!dpmi_dos_buffer) { + dpmi_dos_selector = 0; + printf( "Error allocating 1K of DOS memory\n" ); + exit(1); + } + atexit(dpmi_close); + + // Check dpmi + memset(®s,0,sizeof(regs)); + regs.x.eax = 0x400; // DPMI Get Memory Info + int386( 0x31, ®s, ®s ); + if (!regs.w.cflag) { + if (verbose) printf( "V%d.%d, CPU:%d, VMM:", regs.h.ah, regs.h.al, regs.h.cl ); + if (regs.w.bx & 4) { + if (verbose) printf( "1" ); + dpmi_virtual_memory = 1; + } else { + if (verbose) printf( "0" ); + } + } + + //--------- Find available memory + memset(®s,0,sizeof(regs)); + memset(&sregs,0,sizeof(sregs)); + regs.x.eax = 0x500; // DPMI Get Memory Info + sregs.es = FP_SEG(&mi); + regs.x.edi = FP_OFF(&mi); + int386x( 0x31, ®s, ®s, &sregs ); + if (!regs.w.cflag) { + if (verbose) printf( ", P:%dK", mi.largest_lockable_pages*4 ); + if (dpmi_virtual_memory) + if (verbose) printf( ", A:%dK", mi.largest_block_bytes/1024 ); + //dpmi_physical_memory = mi.largest_lockable_pages*4096; + //dpmi_available_memory = mi.largest_block_bytes; + dpmi_physical_memory = mi.total_physical_pages*4096; + dpmi_available_memory = mi.total_pages * 4096; + } else { + if (verbose) printf( "MemInfo failed!" ); + dpmi_physical_memory = 16*1024*1024; // Assume 16 MB + dpmi_available_memory = 16*1024*1024; // Assume 16 MB + } + +#ifdef __WATCOMC__ + if (!dpmi_lock_region( _GETDS, 4096 )) { + printf( "Error locking _GETDS" ); + exit(1); + } + if (!dpmi_lock_region( cstart_, 4096 )) { + printf( "Error locking cstart" ); + exit(1); + } + if (!dpmi_lock_region( _chain_intr, 4096 )) { + printf( "Error locking _chain_intr" ); + exit(1); + } +#endif + return 1; +} + +void *dpmi_get_temp_low_buffer( int size ) +{ + if ( dpmi_dos_buffer == NULL ) return NULL; + if ( size > 1024 ) return NULL; + + return dpmi_dos_buffer; +} + +int dpmi_set_pm_handler(unsigned intnum, void far * isr ) +{ + union REGS regs; + + /* Use DMPI call 204h to get pm interrrupt */ + memset(®s,0,sizeof(regs)); + regs.w.ax = 0x0205; + regs.h.bl = intnum; + regs.w.cx = FP_SEG(isr); + regs.x.edx = FP_OFF(isr); + int386( 0x31, ®s, ®s ); + if (!regs.w.cflag) + return 0; + return 1; +} + diff --git a/arch/dos/include/commlib.h b/arch/dos/include/commlib.h new file mode 100644 index 00000000..741c2875 --- /dev/null +++ b/arch/dos/include/commlib.h @@ -0,0 +1,59 @@ +#ifndef _COMMLIB_H +#define _COMMLIB_H +#include "dzcomm.h" +typedef comm_port PORT; + +#define COM1 0 +#define COM2 1 +#define COM3 2 +#define COM4 3 + +#define IRQ2 2 +#define IRQ3 3 +#define IRQ4 4 +#define IRQ7 7 +#define IRQ15 15 + +#define ASSUCCESS 0 +#define ASBUFREMPTY -1 +#define TRIGGER_04 4 + +#define ON 1 +#define OFF 0 + + +PORT * PortOpenGreenleafFast(int port, int baud,char parity,int databits, int stopbits); +void SetDtr(PORT *port,int state); +void SetRts(PORT *port,int state); +void UseRtsCts(PORT *port,int state); +void WriteChar(PORT *port,char ch); +void ClearRXBuffer(PORT *port); +int ReadBufferTimed(PORT *port, char *buf, int length, int timeout); +int Change8259Priority(int a); +int FastSetPortHardware(int comport,int IRQ, int baseaddr); +int FastGetPortHardware(int comport,int *IRQ, int *baseaddr); +void FastSet16550TriggerLevel(int a); +void FastSet16550UseTXFifos(int a); +void FastSavePortParameters(int comport); +int PortClose(PORT *port); +void FastRestorePortParameters(int num); +int GetCd(PORT *port); +int ReadCharTimed(PORT *port, int blah); +int ReadChar(PORT *port); +void ClearLineStatus(PORT *port); +int HMInputLine(PORT *port, int a, char *buf, int b); +void HMWaitForOK(int a, char *b); +int HMSendString(PORT *port, char *msg); +int HMSendStringWait(PORT *port, char *msg, int wait); +void HMReset(PORT *port); +void HMDial(PORT *port, char *pPhoneNum); +void HMSendStringNoWait(PORT *port, char *pbuf,int a); +void HMAnswer(PORT *port); +void ClearTXBuffer(PORT *port); +void WriteBuffer(PORT *port, char *pbuff, int len); + +int GetLineStatus(PORT *port); +void ClearLineStatus(PORT *port); + +#endif + diff --git a/arch/dos/include/disk.h b/arch/dos/include/disk.h new file mode 100644 index 00000000..c983fce4 --- /dev/null +++ b/arch/dos/include/disk.h @@ -0,0 +1,6 @@ +#ifndef _DISK_H +#define _DISK_H + +unsigned long getdiskfree(); + +#endif diff --git a/arch/dos/include/dzcomm.h b/arch/dos/include/dzcomm.h new file mode 100644 index 00000000..b2880627 --- /dev/null +++ b/arch/dos/include/dzcomm.h @@ -0,0 +1,220 @@ +/* + * DZcomm : serial communication add-on for Allegro. + * Copyright (c) 1997 Dim Zegebart, Moscow Russia. + * zager@post.comstar.ru + * file : dzcomm.h + * version : 0.6 + */ + +//#x# are marks for automatic documentator and may be ignored by human reader. +//#d# function description +//#v# returned values +//#c# any comments, notes, etc. +//#n# exclude line from documentation +//#sb# begin structure. Type structure name (if any) after this tag. +//#ds# in structure description means what field maintained by system. +//#se# end structure +//#p# parameters list +//#dv# variable description + +#ifdef __cplusplus +extern "C" { +#endif + +#define not_commented(_s_) ((_s_)[-1]!='/'&&(_s_)[-2]!='/') + +//-------------------------- SOME DECODERS -------------------------- + +#define scan_(_key_) ({((_key_)>>8)&0xff;}) //#d#extract scan part +#define ascii_(_key_) ({(_key_)&0xff;})//#d#extract ascii part +#define key_shifts_(_key_) ({((_key_)>>16)&0xff;})//#d#extract shifts keys status + +#define data_(_comm_data_) ({(_comm_data_)&0xff;}) //#d#extract data unsigned char +#define q_reg_(_comm_data_) ({((_comm_data_)>>16)&0xff;}) //#d#extract status registers unsigned char + +//#d#Determine if Ctrl-... pressed +//#v# 1 - if yes. For example if(ctrl_,'C') {exit(1);} +//0 - if not +#define ctrl_(_key_,c)\ +({((key_shifts&KB_CTRL_FLAG)&&((ascii_(_key_)+'A'-1)==(c)));}) + +//----------------------------- FIFO QUEUE ------------------------ +//#sb# First In First Out queue +typedef struct +{ unsigned int size; //size of queue. Use queue_resize(new_size) to change queue size + unsigned int dsize; //size of data element (default 4 unsigned chars) + unsigned int initial_size; + unsigned int resize_counter; + unsigned int fill_level; + int (*empty_handler)(); + void *queue; //pointer to queue. Points to int[], where actual data stored. + unsigned int head,tail; //number of head and tail elements + //head points to the first element in queue + //tail points to the first element next to last + //element in queue. (For example : we have ten elements + //in queue, then head==0, tail==10 +} fifo_queue; +//#se# +fifo_queue* queue_new(unsigned int size); //#d#Allocate storage space for new fifo_queue. +fifo_queue* queue_new_(unsigned int size,unsigned int dsize); +//#v# NULL if failed +// pointer to newly created fifo_queue structure +void queue_delete(fifo_queue *q); //#d#Delete queue description and free occuped space. +inline void queue_reset(fifo_queue *q);//#d#Set head and tail to zero (data not lost). +int queue_resize(fifo_queue *q,unsigned int new_size); //#d#Increase(decrease) storage space +//for fifo queue. +//#v# 0 if failed +//1 if success +inline int queue_put(fifo_queue *q,int c); //#d#Put value into given queue. +inline int queue_get(fifo_queue *q); //#d#Get values from queue. +inline int queue_put_(fifo_queue *q,void *data); +inline int queue_get_(fifo_queue *q,void *data); + +//#v# Byte from queue's head +//#c# Use queue_empty befor calling queue_get. queue_get don't test +// queue's head and tail, just return queue[head]. +inline int queue_empty(fifo_queue *q);//#d#Test queue for emptyness. +//#v# 1 if empty (head==tail) +// 0 if not empty (head!=tail) +//#c# Call this function before any queue_get calling + +//---------------------------- COMM_PORT -------------------------- + +typedef enum {_com1,_com2,_com3,_com4,_com5,_com6,_com7,_com8} comm; +typedef enum {BITS_8=0x03,BITS_7=0x02,BITS_6=0x01,BITS_5=0x00} data_bits; +typedef enum {STOP_1=0x00,STOP_2=0x01} stop_bits; +typedef enum {EVEN_PARITY=0x03,ODD_PARITY=0x01,NO_PARITY=0x00} parity_bits; +typedef enum {_110=110,_150=150,_300=300,_600=600, + _1200=1200,_2400=2400,_4800=4800, + _9600=9600,_19200=19200,_38400=38400, + _57600=57600,_115200=115200} baud_bits; +//typedef enum {DTR_ON=0xFD,RTS_ON=0xFE,DTR_OFF=~0x1,RTS_OFF=~0x2} hand; +typedef enum {CTS_ON=0x01,CTS_OFF=0x0,RTS_ON=0x1,RTS_OFF=0x0} hand; +typedef enum {XON_RCVD=1,XON_SENT=1,XOFF_RCVD=0,XOFF_SENT=0} xon_xoff_status; +typedef enum {NO_CONTROL=1,XON_XOFF=2,RTS_CTS=3} flow_control_type; +typedef enum {XON_ASCII=0x11,XOFF_ASCII=0x13} control_char; + +extern char szDZCommErr[50]; + +typedef enum {DATA_BYTE=1,MSR_BYTE=2,LSR_BYTE=4} comm_status_byte; + +//#sb#Comm port. +typedef struct tag_comm_port +{ //general parametrs +//You may alter this six fields after comm_port_new() where defaults values are set. + char szName[255]; //#d#name of comm port. For example : MODEM + comm nComm; //#d#comm port number + unsigned short nPort; //#d#comm port address + unsigned char nIRQ; //#d#comm IRQ + unsigned short nIRQVector; //#d#number of software interrupt vector. + flow_control_type control_type; //default XON_XOFF + + unsigned char xon; + unsigned char xoff; + unsigned char xonxoff_send; + unsigned char xonxoff_rcvd; + unsigned char rts; + unsigned char cts; + + //next two fields are for unsigned char counting + unsigned int in_cnt; //counter for input data + unsigned int out_cnt; //counter for output data + + unsigned char interrupt_enable_mask; //#ds# + int (*comm_handler)(); //#d#pointer to short function see below + int (*msr_handler)(); //#d#pointer to modem status register handler. + int (*lsr_handler)(); //#d#pointer to line status register handler. +// template to comm's interrupt handler +//comm_port *your_comm,*your_comm1; //must be declared globaly +//int foo_comm_wrapper(void) +//{ dz_comm_interrupt_handler(ptr_your_comm); +// return(0); +//} + + enum {YES,NO} installed; //#ds# + + //communication parametrs + baud_bits nBaud; //#d#baud rate + data_bits nData; //#d#data length + stop_bits nStop; //#d#stop bits + parity_bits nParity; //#d#parity + + //input and output queue + fifo_queue *InBuf; //#ds#pointer to read buffer + fifo_queue *OutBuf; //#ds#pointer to write buffer + + unsigned short THR; //#ds# Transmitter Holding Register */ + unsigned short RDR; //#ds# Reciever Data Register */ + unsigned short BRDL; //#ds#Baud Rate Divisor, Low unsigned short */ + unsigned short BRDH; //#ds# Baud Rate Divisor, High Byte */ + unsigned short IER; //#ds# Interupt Enable Register */ + unsigned short IIR; //#ds# Interupt Identification Register */ + unsigned short FCR; //#ds# FIFO Control Register */ + unsigned short LCR; //#ds# Line Control Register */ + unsigned short MCR; //#ds# Modem Control Register */ + unsigned short LSR; //#ds# Line Status Register */ + unsigned short MSR; //#ds# Modem Status Register */ + unsigned short SCR; //#ds# SCR Register */ + unsigned short ISR_8259; //#ds#interrupt service register + unsigned short IMR_8259; //#ds#interrupt mask register + + int fifo; // 1 if 16550 FIFO enabled + + void *next_port; + void *last_port; +} comm_port; +#define cport_(_p_) ({(comm_port*)(_p_);}) +//#se# +extern char szDZCommErr[50]; +comm_port *comm_port_init(comm com); +int comm_port_install_handler(comm_port *port); +inline void comm_port_out(comm_port *port,unsigned char c); +inline int comm_port_test(comm_port *port); +inline int dz_comm_port_interrupt_handler(comm_port *port); +void comm_port_delete(comm_port *port); +void comm_port_string_send(comm_port *port,char *s); +void comm_port_command_send(comm_port *port,char *s); +void comm_port_break_send(comm_port *port); +void comm_port_hand(comm_port *port,int m); +int comm_port_load_settings(comm_port *port,char *ini_name); +inline int comm_port_send_xoff(comm_port *port); +inline int comm_port_send_xon(comm_port *port); +int comm_port_reinsatall(comm_port *port); +void modem_hangup(comm_port *port); +void dzcomm_init(void); +void print_bin_s(int c,char *s); + +extern comm_port *com1; +extern comm_port *com2; +extern comm_port *com3; +extern comm_port *com4; +extern comm_port *com5; +extern comm_port *com6; +extern comm_port *com7; +extern comm_port *com8; + +#define LSR_DATAREADY 1 +#define LSR_OVERRUN 2 +#define LSR_PARITYERR 4 +#define LSR_FRAMINGERR 8 +#define LSR_BREAK 16 +#define LSR_THRE 32 /* transmitter holding register empty */ +#define LSR_TSRE 64 /* transmitter shift register empty */ +#define LSR_FIFOERR 128 /* 16550 PE/FE/Break in FIFO queue, 0 for 8250 & 16450 */ + +#define MSR_DCTS 1 +#define MSR_DRTS 2 +#define MSR_DRI 4 +#define MSR_DDCD 8 +#define MSR_CTS 16 +#define MSR_RTS 32 +#define MSR_RI 64 +#define MSR_DCD 128 + + +#ifdef __cplusplus +} //end extern "C" +#endif + + + diff --git a/arch/dos/include/joy.h b/arch/dos/include/joy.h new file mode 100644 index 00000000..63a8ad94 --- /dev/null +++ b/arch/dos/include/joy.h @@ -0,0 +1,188 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/arch/dos/include/joy.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:15 $ + * + * Headers for joystick functions + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:00:11 donut + * Import of d1x 1.37 source. + * + * Revision 1.17 1995/10/07 13:22:30 john + * Added new method of reading joystick that allows higher-priority + * interrupts to go off. + * + * Revision 1.16 1995/02/14 11:17:13 john + * Added BIOS readings for stick. + * + * Revision 1.15 1995/02/14 10:09:58 john + * Added OS2 switch. + * + * Revision 1.14 1994/12/28 13:49:20 john + * Added function to set joystick for slow reading + * + * Revision 1.13 1994/10/13 11:36:06 john + * Made joy_down_time be kept track of in fixed seconds, + * not ticks. + * + * Revision 1.12 1994/10/12 17:03:16 john + * Added prototype for joy_get_scaled_reading. + * + * Revision 1.11 1994/10/12 16:57:55 john + * Added function to set a joystick button's state. + * + * Revision 1.10 1994/09/22 16:09:00 john + * Fixed some virtual memory lockdown problems with timer and + * joystick. + * + * Revision 1.9 1994/08/31 09:54:57 john + * *** empty log message *** + * + * Revision 1.8 1994/08/29 21:02:24 john + * Added joy_set_cal_values... + * + * Revision 1.7 1994/08/29 20:51:52 john + * Added better cyberman support; also, joystick calibration + * value return funcctiionn, + * + * Revision 1.6 1994/07/01 10:55:44 john + * Fixed some bugs... added support for 4 axis. + * + * Revision 1.5 1994/06/30 20:36:51 john + * Revamped joystick code. + * + * Revision 1.4 1994/04/22 12:52:10 john + * *** empty log message *** + * + * Revision 1.3 1994/01/18 13:53:39 john + * Made all joystick functions return int's instead of + * shorts. Also made the stick reading be CPU speed + * independant by using the timer_get_Stamp_64 + * function. + * + * Revision 1.2 1994/01/18 10:58:42 john + * *** empty log message *** + * + * Revision 1.1 1993/07/10 13:10:39 matt + * Initial revision + * + * + */ + +#ifndef _JOY_H +#define _JOY_H + +#include "types.h" +#include "fix.h" + +#define JOY_1_BUTTON_A 1 +#define JOY_1_BUTTON_B 2 +#define JOY_2_BUTTON_A 4 +#define JOY_2_BUTTON_B 8 +#define JOY_ALL_BUTTONS (1+2+4+8) + +#define JOY_1_X_AXIS 1 +#define JOY_1_Y_AXIS 2 +#define JOY_2_X_AXIS 4 +#define JOY_2_Y_AXIS 8 +#define JOY_ALL_AXIS (1+2+4+8) + +#define JOY_SLOW_READINGS 1 +#define JOY_POLLED_READINGS 2 +#define JOY_BIOS_READINGS 4 +#define JOY_FRIENDLY_READINGS 8 + +#define JOY_NUM_AXES 4 + +#define MAX_BUTTONS 20 +//========================================================================== +// This initializes the joy and does a "quick" calibration which +// assumes the stick is centered and sets the minimum value to 0 and +// the maximum value to 2 times the centered reading. Returns 0 if no +// joystick was detected, 1 if everything is ok. +// joy_init() is called. + +extern int joy_init(); +extern void joy_close(); + +extern char joy_installed; +extern char joy_present; + +//========================================================================== +// The following 3 routines can be used to zero in on better joy +// calibration factors. To use them, ask the user to hold the stick +// in either the upper left, lower right, or center and then have them +// press a key or button and then call the appropriate one of these +// routines, and it will read the stick and update the calibration factors. +// Usually, assuming that the stick was centered when joy_init was +// called, you really only need to call joy_set_lr, since the upper +// left position is usually always 0,0 on most joys. But, the safest +// bet is to do all three, or let the user choose which ones to set. + +extern void joy_set_ul(); +extern void joy_set_lr(); +extern void joy_set_cen(); + + +//========================================================================== +// This reads the joystick. X and Y will be between -128 and 127. +// Takes about 1 millisecond in the worst case when the stick +// is in the lower right hand corner. Always returns 0,0 if no stick +// is present. + +extern void joy_get_pos( int *x, int *y ); + +//========================================================================== +// This just reads the buttons and returns their status. When bit 0 +// is 1, button 1 is pressed, when bit 1 is 1, button 2 is pressed. +extern int joy_get_btns(); + +//========================================================================== +// This returns the number of times a button went either down or up since +// the last call to this function. +extern int joy_get_button_up_cnt( int btn ); +extern int joy_get_button_down_cnt( int btn ); + +//========================================================================== +// This returns how long (in approximate milliseconds) that each of the +// buttons has been held down since the last call to this function. +// It is the total time... say you pressed it down for 3 ticks, released +// it, and held it down for 6 more ticks. The time returned would be 9. +extern fix joy_get_button_down_time( int btn ); + +extern ubyte joy_read_raw_buttons(); +extern ubyte joystick_read_raw_axis( ubyte mask, int * axis ); +extern void joy_flush(); +extern ubyte joy_get_present_mask(); +extern void joy_set_timer_rate(int max_value ); +extern int joy_get_timer_rate(); + +extern int joy_get_button_state( int btn ); +extern void joy_set_cen_fake(int channel); +extern ubyte joy_read_stick( ubyte masks, int *axis ); +extern void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max); +extern void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max); +extern void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount ); +extern int joy_get_scaled_reading( int raw, int axn ); +extern void joy_set_slow_reading( int flag ); + + +extern int JOY_PORT; + +extern int joy_deadzone; +#endif + diff --git a/arch/dos/include/key.h b/arch/dos/include/key.h new file mode 100644 index 00000000..0f9daa4c --- /dev/null +++ b/arch/dos/include/key.h @@ -0,0 +1,270 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/arch/dos/include/key.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:15 $ + * + * Header for keyboard functions + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:00:12 donut + * Import of d1x 1.37 source. + * + * Revision 1.19 1994/10/24 13:58:12 john + * Hacked in support for pause key onto code 0x61. + * + * Revision 1.18 1994/10/21 15:17:10 john + * Added KEY_PRINT_SCREEN + * + * Revision 1.17 1994/08/31 12:22:13 john + * Added KEY_DEBUGGED + * + * Revision 1.16 1994/08/24 18:53:50 john + * Made Cyberman read like normal mouse; added dpmi module; moved + * mouse from assembly to c. Made mouse buttons return time_down. + * + * Revision 1.15 1994/08/18 14:56:16 john + * *** empty log message *** + * + * Revision 1.14 1994/08/08 10:43:24 john + * Recorded when a key was pressed for key_inkey_time. + * + * Revision 1.13 1994/06/17 17:17:28 john + * Added keyd_time_last_key_was_pressed or something like that. + * + * Revision 1.12 1994/04/29 12:14:19 john + * Locked all memory used during interrupts so that program + * won't hang when using virtual memory. + * + * Revision 1.11 1994/02/17 15:57:14 john + * Changed key libary to C. + * + * Revision 1.10 1994/01/31 08:34:09 john + * Fixed reversed lshift/rshift keys. + * + * Revision 1.9 1994/01/18 10:58:17 john + * *** empty log message *** + * + * Revision 1.8 1993/10/16 19:24:43 matt + * Added new function key_clear_times() & key_clear_counts() + * + * Revision 1.7 1993/10/15 10:17:09 john + * added keyd_last_key_pressed and released for use with recorder. + * + * Revision 1.6 1993/10/06 16:20:37 john + * fixed down arrow bug + * + * Revision 1.5 1993/10/04 13:26:42 john + * changed the #defines for scan codes. + * + * Revision 1.4 1993/09/28 11:35:20 john + * added key_peekkey + * + * Revision 1.3 1993/09/20 18:36:43 john + * *** empty log message *** + * + * Revision 1.1 1993/07/10 13:10:39 matt + * Initial revision + * + * + */ + +#ifndef _KEY_H +#define _KEY_H + +#include "fix.h" +#include "types.h" + +//========================================================================== +// This installs the int9 vector and initializes the keyboard in buffered +// ASCII mode. key_close simply undoes that. +extern void key_init(); +extern void key_close(); + +//========================================================================== +// These are configuration parameters to setup how the buffer works. +// set keyd_buffer_type to 0 for no key buffering. +// set it to 1 and it will buffer scancodes. +extern unsigned char keyd_buffer_type; +extern unsigned char keyd_repeat; // 1=allow repeating, 0=dont allow repeat + +// keyd_editor_mode... 0=game mode, 1=editor mode. +// Editor mode makes key_down_time always return 0 if modifiers are down. +extern unsigned char keyd_editor_mode; + +// Time in seconds when last key was pressed... +extern volatile int keyd_time_when_last_pressed; + +//========================================================================== +// These are the "buffered" keypress routines. Use them by setting the +// "keyd_buffer_type" variable. + +extern void key_flush(); // Clears the 256 char buffer +extern int key_checkch(); // Returns 1 if a char is waiting +extern int key_getch(); // Gets key if one waiting other waits for one. +extern int key_inkey(); // Gets key if one, other returns 0. +extern int key_inkey_time(fix *time); // Same as inkey, but returns the time the key was pressed down. +extern int key_peekkey(); // Same as inkey, but doesn't remove key from buffer. + +extern unsigned char key_to_ascii(int keycode ); + +extern void key_debug(); // Does an INT3 + +//========================================================================== +// These are the unbuffered routines. Index by the keyboard scancode. + +// Set to 1 if the key is currently down, else 0 +extern volatile unsigned char keyd_pressed[]; +extern volatile unsigned char keyd_last_pressed; +extern volatile unsigned char keyd_last_released; + +// Returns the seconds this key has been down since last call. +extern fix key_down_time(int scancode); + +// Returns number of times key has went from up to down since last call. +extern unsigned int key_down_count(int scancode); + +// Returns number of times key has went from down to up since last call. +extern unsigned int key_up_count(int scancode); + +// Clears the times & counts used by the above functions +// Took out... use key_flush(); +//void key_clear_times(); +//void key_clear_counts(); + +extern char * key_text[256]; + + +#define KEY_SHIFTED 0x100 +#define KEY_ALTED 0x200 +#define KEY_CTRLED 0x400 +#define KEY_DEBUGGED 0x800 + +#define KEY_0 0x0B +#define KEY_1 0x02 +#define KEY_2 0x03 +#define KEY_3 0x04 +#define KEY_4 0x05 +#define KEY_5 0x06 +#define KEY_6 0x07 +#define KEY_7 0x08 +#define KEY_8 0x09 +#define KEY_9 0x0A + +#define KEY_A 0x1E +#define KEY_B 0x30 +#define KEY_C 0x2E +#define KEY_D 0x20 +#define KEY_E 0x12 +#define KEY_F 0x21 +#define KEY_G 0x22 +#define KEY_H 0x23 +#define KEY_I 0x17 +#define KEY_J 0x24 +#define KEY_K 0x25 +#define KEY_L 0x26 +#define KEY_M 0x32 +#define KEY_N 0x31 +#define KEY_O 0x18 +#define KEY_P 0x19 +#define KEY_Q 0x10 +#define KEY_R 0x13 +#define KEY_S 0x1F +#define KEY_T 0x14 +#define KEY_U 0x16 +#define KEY_V 0x2F +#define KEY_W 0x11 +#define KEY_X 0x2D +#define KEY_Y 0x15 +#define KEY_Z 0x2C + +#define KEY_MINUS 0x0C +#define KEY_EQUAL 0x0D +#define KEY_DIVIDE 0x35 +#define KEY_SLASH 0x2B +#define KEY_COMMA 0x33 +#define KEY_PERIOD 0x34 +#define KEY_SEMICOL 0x27 + +#define KEY_LBRACKET 0x1A +#define KEY_RBRACKET 0x1B + +#define KEY_RAPOSTRO 0x28 +#define KEY_LAPOSTRO 0x29 + +#define KEY_ESC 0x01 +#define KEY_ENTER 0x1C +#define KEY_BACKSP 0x0E +#define KEY_TAB 0x0F +#define KEY_SPACEBAR 0x39 + +#define KEY_NUMLOCK 0x45 +#define KEY_SCROLLOCK 0x46 +#define KEY_CAPSLOCK 0x3A + +#define KEY_LSHIFT 0x2A +#define KEY_RSHIFT 0x36 + +#define KEY_LALT 0x38 +#define KEY_RALT 0xB8 + +#define KEY_LCTRL 0x1D +#define KEY_RCTRL 0x9D + +#define KEY_F1 0x3B +#define KEY_F2 0x3C +#define KEY_F3 0x3D +#define KEY_F4 0x3E +#define KEY_F5 0x3F +#define KEY_F6 0x40 +#define KEY_F7 0x41 +#define KEY_F8 0x42 +#define KEY_F9 0x43 +#define KEY_F10 0x44 +#define KEY_F11 0x57 +#define KEY_F12 0x58 + +#define KEY_PAD0 0x52 +#define KEY_PAD1 0x4F +#define KEY_PAD2 0x50 +#define KEY_PAD3 0x51 +#define KEY_PAD4 0x4B +#define KEY_PAD5 0x4C +#define KEY_PAD6 0x4D +#define KEY_PAD7 0x47 +#define KEY_PAD8 0x48 +#define KEY_PAD9 0x49 +#define KEY_PADMINUS 0x4A +#define KEY_PADPLUS 0x4E +#define KEY_PADPERIOD 0x53 +#define KEY_PADDIVIDE 0xB5 +#define KEY_PADMULTIPLY 0x37 +#define KEY_PADENTER 0x9C + +#define KEY_INSERT 0xD2 +#define KEY_HOME 0xC7 +#define KEY_PAGEUP 0xC9 +#define KEY_DELETE 0xD3 +#define KEY_END 0xCF +#define KEY_PAGEDOWN 0xD1 +#define KEY_UP 0xC8 +#define KEY_DOWN 0xD0 +#define KEY_LEFT 0xCB +#define KEY_RIGHT 0xCD + +#define KEY_PRINT_SCREEN 0xB7 +#define KEY_PAUSE 0x61 + +#endif diff --git a/arch/dos/include/midiallg.h b/arch/dos/include/midiallg.h new file mode 100644 index 00000000..c67a06a1 --- /dev/null +++ b/arch/dos/include/midiallg.h @@ -0,0 +1,12 @@ +#ifndef _MIDIALLG_H +#define _MIDIALLG_H + +void digi_midi_pause(); +void digi_midi_resume(); +void digi_midi_stop(); +#ifndef ALLEGRO +int digi_midi_init(); +void digi_midi_close(); +#endif + +#endif diff --git a/arch/dos/include/mouse.h b/arch/dos/include/mouse.h new file mode 100644 index 00000000..28a5cd0d --- /dev/null +++ b/arch/dos/include/mouse.h @@ -0,0 +1,132 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/arch/dos/include/mouse.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:15 $ + * + * Header for mouse functions + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:00:13 donut + * Import of d1x 1.37 source. + * + * Revision 1.10 1995/02/02 10:22:29 john + * Added cyberman init parameter. + * + * Revision 1.9 1994/11/18 23:18:09 john + * Changed some shorts to ints. + * + * Revision 1.8 1994/09/13 12:33:49 john + * Added functions to get down count and state. + * + * Revision 1.7 1994/08/29 20:52:20 john + * Added better cyberman support; also, joystick calibration + * value return funcctiionn, + * + * Revision 1.6 1994/08/24 17:54:35 john + * *** empty log message *** + * + * Revision 1.5 1994/08/24 17:51:43 john + * Added transparent cyberman support + * + * Revision 1.4 1993/07/27 09:32:22 john + * *** empty log message *** + * + * Revision 1.3 1993/07/26 10:46:44 john + * added definition for mouse_set_pos + * + * Revision 1.2 1993/07/22 13:07:59 john + * added header for mousesetlimts + * + * Revision 1.1 1993/07/10 13:10:40 matt + * Initial revision + * + * + */ + +#ifndef MOUSE_H +#define MOUSE_H + +#include "types.h" +#include "fix.h" + +#define MB_LEFT 0 +#define MB_RIGHT 1 +#define MB_MIDDLE 2 +#define MB_Z_UP 3 +#define MB_Z_DOWN 4 +#define MB_PITCH_BACKWARD 5 +#define MB_PITCH_FORWARD 6 +#define MB_BANK_LEFT 7 +#define MB_BANK_RIGHT 8 +#define MB_HEAD_LEFT 9 +#define MB_HEAD_RIGHT 10 + +#define MOUSE_LBTN 1 +#define MOUSE_RBTN 2 +#define MOUSE_MBTN 4 + +//#define NOMOUSE + +#ifndef NOMOUSE + +//======================================================================== +// Check for mouse driver, reset driver if installed. returns number of +// buttons if driver is present. + +extern int mouse_init(int enable_cyberman); +extern void mouse_set_limits( int x1, int y1, int x2, int y2 ); +extern void mouse_flush(); // clears all mice events... + +//======================================================================== +// Shutdowns mouse system. +extern void mouse_close(); + +//======================================================================== +extern void mouse_get_pos( int *x, int *y); +extern void mouse_get_delta( int *dx, int *dy ); +extern int mouse_get_btns(); +extern void mouse_set_pos( int x, int y); +extern void mouse_get_cyberman_pos( int *x, int *y ); + +// Returns how long this button has been down since last call. +extern fix mouse_button_down_time(int button); + +// Returns how many times this button has went down since last call. +extern int mouse_button_down_count(int button); + +// Returns 1 if this button is currently down +extern int mouse_button_state(int button); + + +#else +// NOMOUSE +#define mouse_init(a) -1 +#define mouse_set_limits(a,b,c,d) -1 +#define mouse_flush() +#define mouse_close() +#define mouse_get_pos(a,b) +#define mouse_get_delta(a,b) +#define mouse_get_btns() 0 +#define mouse_set_pos(a,b) +#define mouse_get_cyberman_pos(a,b) +#define mouse_button_down_time(a) 0 +#define mouse_button_down_count(a) 0 +#define mouse_button_state(a) 0 + +#endif + + +#endif diff --git a/arch/dos/include/serial.h b/arch/dos/include/serial.h new file mode 100644 index 00000000..3425b48b --- /dev/null +++ b/arch/dos/include/serial.h @@ -0,0 +1,2 @@ +#include "commlib.h" +extern int commlib_initialised; diff --git a/arch/dos/init.c b/arch/dos/init.c new file mode 100644 index 00000000..72748b0b --- /dev/null +++ b/arch/dos/init.c @@ -0,0 +1,366 @@ +#include +#include +#ifdef __DJGPP__ +#define _BORLAND_DOS_REGS 1 +#endif +#include + +#include "../../main/inferno.h" +#include "../../main/text.h" +#include "args.h" +#include "error.h" + +#include "joy.h" +#include "timer.h" +#include "key.h" +#include "mono.h" +#include "u_dpmi.h" +#include "mouse.h" + +//added on 9/15/98 by Victor Rachels to add cd controls +#include "bcd.h" +//end this section addition - Victor Rachels + +int WVIDEO_running=0; //debugger can set to 1 if running + +void install_int3_handler(void); + +#ifdef __WATCOMC__ +int __far descent_critical_error_handler( unsigned deverr, unsigned errcode, unsigned far * devhdr ); +#endif + +#ifndef NDEBUG +#ifdef __WATCOMC__ +void do_heap_check() +{ + int heap_status; + + heap_status = _heapset( 0xFF ); + switch( heap_status ) + { + case _HEAPBADBEGIN: + mprintf((1, "ERROR - heap is damaged\n")); + Int3(); + break; + case _HEAPBADNODE: + mprintf((1, "ERROR - bad node in heap\n" )); + Int3(); + break; + } +} +#endif +#endif + + + +#ifdef VR_DEVICES +int is_3dbios_installed() +{ + dpmi_real_regs rregs; + memset(&rregs,0,sizeof(dpmi_real_regs)); + rregs.eax = 0x4ed0; + //rregs.ebx = 0x3d10; + dpmi_real_int386x( 0x10, &rregs ); + if ( (rregs.edx & 0xFFFF) != 0x3344 ) + return 0; + else + return 1; +} +#endif + +// Returns 1 if ok, 0 if failed... +int init_gameport() +{ + union REGS regs; + + memset(®s,0,sizeof(regs)); + regs.x.eax = 0x8400; + regs.x.edx = 0xF0; + int386( 0x15, ®s, ®s ); + if ( ( regs.x.eax & 0xFFFF ) == 0x4753 /*'SG'*/ ) + return 1; + else + return 0; +} + +void check_dos_version() +{ + int major, minor; + union REGS regs; + + memset(®s,0,sizeof(regs)); + regs.x.eax = 0x3000; // Get MS-DOS Version Number + int386( 0x21, ®s, ®s ); + + major = regs.h.al; + minor = regs.h.ah; + + if ( major < 5 ) { + printf( "Using MS-DOS version %d.%d\nThis is not compatable with Descent.", major, minor); + exit(1); + } + //printf( "\nUsing MS-DOS %d.%d...\n", major, minor ); +} + +void dos_check_file_handles(int num_required) +{ + int i, n; + FILE * fp[16]; + + if ( num_required > 16 ) + num_required = 16; + + n = 0; + for (i=0; i<16; i++ ) + fp[i] = NULL; + for (i=0; i<16; i++ ) { + fp[i] = fopen( "nul", "wb" ); + if ( !fp[i] ) break; + } + n = i; + for (i=0; i<16; i++ ) { + if (fp[i]) + fclose(fp[i]); + } + if ( n < num_required ) { + printf( "\n%s\n", TXT_NOT_ENOUGH_HANDLES ); + printf( "------------------------\n" ); + printf( "%d/%d %s\n", n, num_required, TXT_HANDLES_1 ); + printf( "%s\n", TXT_HANDLES_2); + printf( "%s\n", TXT_HANDLES_3); + exit(1); + } +} + +#define NEEDED_DOS_MEMORY ( 300*1024) // 300 K +#define NEEDED_LINEAR_MEMORY (7680*1024) // 7.5 MB +#define LOW_PHYSICAL_MEMORY_CUTOFF (5*1024*1024) // 5.0 MB +#define NEEDED_PHYSICAL_MEMORY (2000*1024) // 2000 KB + +extern int piggy_low_memory; + +void mem_int_to_string( int number, char *dest ) +{ + int i,l,c; + char buffer[20],*p; + + sprintf( buffer, "%d", number ); + + l = strlen(buffer); + if (l<=3) { + // Don't bother with less than 3 digits + sprintf( dest, "%d", number ); + return; + } + + c = l % 3; + p=dest; + for (i=0; i dpmi_physical_memory ) { + mem_int_to_string( (dpmi_available_memory-dpmi_physical_memory)/1024, text ); + } else { + mem_int_to_string( 0, text ); + } + printf( "Virtual: %7s KB\n", text ); + printf( "\n" ); + + if ( dpmi_dos_memory < NEEDED_DOS_MEMORY ) { + printf( "%d %s\n", NEEDED_DOS_MEMORY - dpmi_dos_memory, TXT_MEMORY_CONFIG ); + exit(1); + } + + if ( dpmi_available_memory < NEEDED_LINEAR_MEMORY ) { + if ( dpmi_virtual_memory ) { + printf( "%d %s\n", NEEDED_LINEAR_MEMORY - dpmi_available_memory, TXT_RECONFIGURE_VMM ); + } else { + printf( "%d %s\n", NEEDED_LINEAR_MEMORY - dpmi_available_memory, TXT_MORE_MEMORY ); + printf( "%s\n", TXT_MORE_MEMORY_2); + } + exit(1); + } + + if ( dpmi_physical_memory < NEEDED_PHYSICAL_MEMORY ) { + printf( "%d %s\n", NEEDED_PHYSICAL_MEMORY - dpmi_physical_memory, TXT_PHYSICAL_MEMORY ); + if ( dpmi_virtual_memory ) { + printf( "%s\n", TXT_PHYSICAL_MEMORY_2); + } + exit(1); + } + + if ( dpmi_physical_memory < LOW_PHYSICAL_MEMORY_CUTOFF ) { + piggy_low_memory = 1; + } +} + +extern int Inferno_verbose; + +//NO_STACK_SIZE_CHECK uint * stack, *stack_ptr; +//NO_STACK_SIZE_CHECK int stack_size, unused_stack_space; +//NO_STACK_SIZE_CHECK int sil; +//NO_STACK_SIZE_CHECK +//NO_STACK_SIZE_CHECK int main(int argc,char **argv) +//NO_STACK_SIZE_CHECK { +//NO_STACK_SIZE_CHECK uint ret_value; +//NO_STACK_SIZE_CHECK +//NO_STACK_SIZE_CHECK unused_stack_space = 0; +//NO_STACK_SIZE_CHECK stack = &ret_value; +//NO_STACK_SIZE_CHECK stack_size = stackavail()/4; +//NO_STACK_SIZE_CHECK +//NO_STACK_SIZE_CHECK for ( sil=0; sil +#include +#include +#include +#include +#include +#include +#include + +#include "types.h" +#include "timer.h" +#include "ipx.h" +#include "error.h" +#include "u_dpmi.h" +#include "key.h" + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; + +typedef struct local_address { + ubyte address[6]; +} __pack__ local_address; + +typedef struct net_address { + BYTE network_id[4]; + local_address node_id; + WORD socket_id; +} __pack__ net_address; + +typedef struct ipx_header { + WORD checksum; + WORD length; + BYTE transport_control; + BYTE packet_type; + net_address destination; + net_address source; +} __pack__ ipx_header; + +typedef struct ecb_header { + WORD link[2]; + WORD esr_address[2]; + BYTE in_use; + BYTE completion_code; + WORD socket_id; + BYTE ipx_reserved[14]; + WORD connection_id; + local_address immediate_address; + WORD fragment_count; + WORD fragment_pointer[2]; + WORD fragment_size; +} __pack__ ecb_header; + +typedef struct packet_data { + int packetnum; + byte data[IPX_MAX_DATA_SIZE]; +} __pack__ packet_data; + +typedef struct ipx_packet { + ecb_header ecb; + ipx_header ipx; + packet_data pd; +} __pack__ ipx_packet; + +typedef struct user_address { + ubyte network[4]; + ubyte node[6]; + ubyte address[6]; +} __pack__ user_address; + +#define MAX_USERS 64 +int Ipx_num_users = 0; +user_address Ipx_users[MAX_USERS]; + +#define MAX_NETWORKS 64 +int Ipx_num_networks = 0; +uint Ipx_networks[MAX_NETWORKS]; + +int ipx_packetnum = 0; + +#define MAX_PACKETS 64 + +static packet_data packet_buffers[MAX_PACKETS]; +static short packet_free_list[MAX_PACKETS]; +static int num_packets = 0; +static int largest_packet_index = 0; +static short packet_size[MAX_PACKETS]; + +WORD ipx_socket=0; +ubyte ipx_installed=0; +WORD ipx_vector_segment; +WORD ipx_vector_offset; +ubyte ipx_socket_life = 0; // 0=closed at prog termination, 0xff=closed when requested. +DWORD ipx_network = 0; +local_address ipx_my_node; +WORD ipx_num_packets=32; // 32 Ipx packets +ipx_packet * packets; +int neterrors = 0; +ushort ipx_packets_selector; + +ecb_header * last_ecb=NULL; +int lastlen=0; + +void got_new_packet( ecb_header * ecb ); +void ipx_listen_for_packet(ecb_header * ecb ); + +void free_packet( int id ) +{ + packet_buffers[id].packetnum = -1; + packet_free_list[ --num_packets ] = id; + if (largest_packet_index==id) + while ((--largest_packet_index>0) && (packet_buffers[largest_packet_index].packetnum == -1 )); +} + +int ipx_get_packet_data( ubyte * data ) +{ + int i, n, best, best_id, size; + + for (i=1; i -1 ) { + n++; + if ( best == -1 || (packet_buffers[i].packetnum ", neterrors )); + + if ( best_id < 0 ) return 0; + + size = packet_size[best_id]; + memcpy( data, packet_buffers[best_id].data, size ); + free_packet(best_id); + + return size; +} + +#ifndef __GNUC__ +unsigned int swap_short( unsigned int short ) +#pragma aux swap_short parm [eax] = "xchg al,ah"; +#else +static inline unsigned int swap_short( unsigned int sshort ) { + int __retval; + asm("xchg %%ah,%%al" : "=a" (__retval) : "a" (sshort)); + return __retval; +} +#endif + +void got_new_packet( ecb_header * ecb ) +{ + ipx_packet * p; + int id; + unsigned short datasize; + + datasize = 0; + last_ecb = ecb; + p = (ipx_packet *)ecb; + + if ( p->ecb.in_use ) { neterrors++; return; } + if ( p->ecb.completion_code ) { neterrors++; return; } + + // Error( "Recieve error %d for completion code", p->ecb.completion_code ); + + if ( memcmp( &p->ipx.source.node_id, &ipx_my_node, 6 ) ) { + datasize=swap_short(p->ipx.length); + lastlen=datasize; + datasize -= sizeof(ipx_header); + // Find slot to put packet in... + if ( datasize > 0 && datasize <= sizeof(packet_data) ) { + if ( num_packets >= MAX_PACKETS ) { + //printf( 1, "IPX: Packet buffer overrun!!!\n" ); + neterrors++; + return; + } + id = packet_free_list[ num_packets++ ]; + if (id > largest_packet_index ) largest_packet_index = id; + packet_size[id] = datasize-sizeof(int); + packet_buffers[id].packetnum = p->pd.packetnum; + if ( packet_buffers[id].packetnum < 0 ) { neterrors++; return; } + memcpy( packet_buffers[id].data, p->pd.data, packet_size[id] ); + } else { + neterrors++; return; + } + } + // Repost the ecb + p->ecb.in_use = 0; + //ipx_listen_for_packet(&p->ecb); +} + +ubyte * ipx_get_my_local_address() +{ + return ipx_my_node.address; +} + +ubyte * ipx_get_my_server_address() +{ + return (ubyte *)&ipx_network; +} + +void ipx_listen_for_packet(ecb_header * ecb ) +{ + dpmi_real_regs rregs; + ecb->in_use = 0x1d; + memset(&rregs,0,sizeof(dpmi_real_regs)); + rregs.ebx = 4; // Listen For Packet function + rregs.esi = DPMI_real_offset(ecb); + rregs.es = DPMI_real_segment(ecb); + dpmi_real_int386x( 0x7A, &rregs ); +} + +void ipx_cancel_listen_for_packet(ecb_header * ecb ) +{ + dpmi_real_regs rregs; + memset(&rregs,0,sizeof(dpmi_real_regs)); + rregs.ebx = 6; // IPX Cancel event + rregs.esi = DPMI_real_offset(ecb); + rregs.es = DPMI_real_segment(ecb); + dpmi_real_int386x( 0x7A, &rregs ); +} + + +void ipx_send_packet(ecb_header * ecb ) +{ + dpmi_real_regs rregs; + memset(&rregs,0,sizeof(dpmi_real_regs)); + rregs.ebx = 3; // Send Packet function + rregs.esi = DPMI_real_offset(ecb); + rregs.es = DPMI_real_segment(ecb); + dpmi_real_int386x( 0x7A, &rregs ); +} + +typedef struct { + ubyte network[4]; + ubyte node[6]; + ubyte local_target[6]; +} __pack__ net_xlat_info; + +void ipx_get_local_target( ubyte * server, ubyte * node, ubyte * local_target ) +{ + net_xlat_info * info; + dpmi_real_regs rregs; + + // Get dos memory for call... + info = (net_xlat_info *)dpmi_get_temp_low_buffer( sizeof(net_xlat_info) ); + assert( info != NULL ); + memcpy( info->network, server, 4 ); + memcpy( info->node, node, 6 ); + + memset(&rregs,0,sizeof(dpmi_real_regs)); + + rregs.ebx = 2; // Get Local Target + rregs.es = DPMI_real_segment(info); + rregs.esi = DPMI_real_offset(info->network); + rregs.edi = DPMI_real_offset(info->local_target); + + dpmi_real_int386x( 0x7A, &rregs ); + + // Save the local target... + memcpy( local_target, info->local_target, 6 ); +} + +void ipx_close() +{ + dpmi_real_regs rregs; + if ( ipx_installed ) { + // When using VLM's instead of NETX, the sockets don't + // seem to automatically get closed, so we must explicitly + // close them at program termination. + ipx_installed = 0; + memset(&rregs,0,sizeof(dpmi_real_regs)); + rregs.edx = ipx_socket; + rregs.ebx = 1; // Close socket + dpmi_real_int386x( 0x7A, &rregs ); + } +} + + +//--------------------------------------------------------------- +// Initializes all IPX internals. +// If socket_number==0, then opens next available socket. +// Returns: 0 if successful. +// -1 if socket already open. +// -2 if socket table full. +// -3 if IPX not installed. +// -4 if couldn't allocate low dos memory +// -5 if error with getting internetwork address + +int ipx_init( int socket_number, int show_address ) +{ + dpmi_real_regs rregs; + ubyte *ipx_real_buffer; + int i; + + atexit(ipx_close); + + ipx_packetnum = 0; + + // init packet buffers. + for (i=0; i= IPX_MAX_DATA_SIZE ) { + printf( "Data too big\n" ); +//added/replaced on 11/8/98 by Victor Rachels to stop crappage + return; +// exit(1); +//end this section replacement - VR + } + + // Make sure no one is already sending something + while( packets[0].ecb.in_use ) + { + } + + if (packets[0].ecb.completion_code) { +// printf( "Send error %d for completion code\n", packets[0].ecb.completion_code ); +//added/replaced on 11/8/98 by Victor Rachels to stop crappage + return; + // exit(1); +//end this section replacement - VR + + } + + // Fill in destination address + if ( memcmp( network, &ipx_network, 4 ) ) + memcpy( packets[0].ipx.destination.network_id, network, 4 ); + else + memset( packets[0].ipx.destination.network_id, 0, 4 ); + memcpy( packets[0].ipx.destination.node_id.address, address, 6 ); + memcpy( packets[0].ecb.immediate_address.address, immediate_address, 6 ); + packets[0].pd.packetnum = ipx_packetnum++; + + // Fill in data to send + packets[0].ecb.fragment_size = sizeof(ipx_header) + sizeof(int) + datasize; + + assert( datasize > 1 ); + assert( packets[0].ecb.fragment_size <= 576 ); + + memcpy( packets[0].pd.data, data, datasize ); + + // Send it + ipx_send_packet( &packets[0].ecb ); + +} + +void ipx_send_broadcast_packet_data( ubyte * data, int datasize ) +{ + int i, j; + ubyte broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + ubyte local_address[6]; + + // Set to all networks besides mine + for (i=0; i= Ipx_num_networks ) { + memcpy( &Ipx_networks[Ipx_num_networks++], tmp.network, 4 ); + printf(" %02x%02x%02x%02x\n", tmp.network[0], tmp.network[1], tmp.network[2], tmp.network[3] ); + } + } else { + printf( "Too many networks in %s! (Limit of %d)\n", filename, MAX_NETWORKS ); + fclose(fp); + return; + } + } + fclose(fp); + +} + +//---typedef struct rip_entry { +//--- uint network; +//--- ushort nhops; +//--- ushort nticks; +//---} rip_entry; +//--- +//---typedef struct rip_packet { +//--- ushort operation; //1=request, 2=response +//--- rip_entry rip[50]; +//---} rip_packet; +//--- +//--- +//---void ipx_find_all_servers() +//---{ +//--- int i; +//--- rip_packet * rp; +//--- assert(ipx_installed); +//--- +//--- ipx_change_default_socket( 0x0453 ); +//--- // ipx_change_default_socket( 0x5304 ); +//--- +//--- // Make sure no one is already sending something +//--- while( packets[0].ecb.in_use ) +//--- { +//--- } +//--- +//--- if (packets[0].ecb.completion_code) { +//--- printf( "AAAA:Send error %d for completion code\n", packets[0].ecb.completion_code ); +//--- //exit(1); +//--- } +//--- +//--- rp = (rip_packet *)&packets[0].pd; +//--- +//--- // Fill in destination address +//--- { +//--- char mzero1[] = {0,0,0,1}; +//--- char mzero[] = {0,0,0,0,0,1}; +//--- char immediate[6]; +//--- //memcpy( packets[0].ipx.destination.network_id, &ipx_network, 4 ); +//--- //memcpy( packets[0].ipx.destination.node_id.address, ipx_my_node.address, 6 ); +//--- +//--- memcpy( packets[0].ipx.destination.network_id, mzero1, 4 ); +//--- memcpy( packets[0].ipx.destination.node_id.address, mzero, 6 ); +//--- +//--- memcpy( packets[0].ipx.destination.socket_id, &ipx_socket, 2 ); +//--- memcpy( packets[0].ipx.source.network_id, &ipx_network, 4 ); +//--- memcpy( packets[0].ipx.source.node_id.address, ipx_my_node.address, 6 ); +//--- memcpy( packets[0].ipx.source.socket_id, &ipx_socket, 2 ); +//--- //memcpy( packets[0].ecb.immediate_address.address, ipx_my_node.address, 6 ); +//--- //mzero1[3] = 1; +//--- //memcpy( packets[0].ipx.destination.network_id, mzero1, 4 ); +//--- //mzero[5] = 1; +//--- //memcpy( packets[0].ipx.destination.node_id.address, mzero, 6 ); +//--- //ipx_get_local_target( mzero1, mzero, immediate ); +//--- //memcpy( packets[0].ecb.immediate_address.address, mzero, 6 ); +//--- //memcpy( packets[0].ecb.immediate_address.address, immediate, 6 ); +//--- //mzero[5] = 0; +//--- } +//--- +//--- packets[0].ipx.packet_type = 1; // RIP packet +//--- +//--- // Fill in data to send +//--- packets[0].ecb.fragment_size = sizeof(ipx_header) + sizeof(rip_packet); +//--- assert( packets[0].ecb.fragment_size <= 576 ); +//--- +//--- rp->operation = 0; // Request +//--- for (i=0;i<50; i++) { +//--- rp->rip[i].network = 0xFFFFFFFF; +//--- rp->rip[i].nhops = 0; +//--- rp->rip[i].nticks = 0; +//--- } +//--- +//--- // Send it +//--- ipx_send_packet( &packets[0].ecb ); +//--- +//--- for (i=0;i<50; i++) { +//--- if ( rp->rip[i].network != 0xFFFFFFFF ) +//--- printf( "Network = %8x, Hops=%d, Ticks=%d\n", rp->rip[i].network, rp->rip[i].nhops, rp->rip[i].nticks ); +//--- } +//---} +//--- +//--- diff --git a/arch/dos/ipx.h b/arch/dos/ipx.h new file mode 100644 index 00000000..1b69c1aa --- /dev/null +++ b/arch/dos/ipx.h @@ -0,0 +1,147 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/arch/dos/ipx.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:15 $ + * + * Prototype for IPX communications. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 21:58:39 donut + * Import of d1x 1.37 source. + * + * Revision 2.6 1995/03/29 11:19:32 john + * Added broadcasting over a net. + * + * Revision 2.5 1995/03/28 20:04:43 john + * Took away alternate server stuff. + * + * Revision 2.4 1995/03/23 19:00:10 john + * Added user list capabitly. + * + * Revision 2.3 1995/03/23 12:26:57 john + * Move IPX into bios lib. + * + * Revision 2.2 1995/03/22 19:08:14 john + * Added code to fix sending packets over router... now + * we just need to make broadcasts go over router!! + * + * Revision 2.1 1995/03/21 08:39:56 john + * Ifdef'd out the NETWORK code. + * + * Revision 2.0 1995/02/27 11:30:16 john + * New version 2.0, which has no anonymous unions, builds with + * Watcom 10.0, and doesn't require parsing BITMAPS.TBL. + * + * Revision 1.16 1995/02/16 17:34:52 john + * Added code to allow dynamic socket changing. + * + * Revision 1.15 1995/01/04 21:43:27 rob + * Remove SPX size definition. + * + * Revision 1.14 1995/01/03 13:46:18 john + * Added code that should make ipx work over different servers, + * but ifdef'd it out with SHAREWARE in ipx.c. I haven't tested + * this, and I hope it doesn't introduce net bugs. + * + * Revision 1.13 1994/11/02 11:37:16 rob + * Changed default socket number to a higher regions. + * + * Revision 1.12 1994/11/01 15:56:51 rob + * Added defines for SPX socketsx. + * + * Revision 1.11 1994/10/31 19:23:31 rob + * Added a prototype for the new object send function. + * + * Revision 1.10 1994/09/07 13:37:25 john + * Changed default socket to 0x4000, because + * the ipx/spx book says that we can only use + * sockets 0x4000 - 0x7fff. + * + * Revision 1.9 1994/08/25 18:14:45 matt + * Changed socket because of packet change + * + * Revision 1.8 1994/08/12 22:42:24 john + * Took away Player_stats; added Players array. + * + * Revision 1.7 1994/08/09 19:31:47 john + * Networking changes. + * + * Revision 1.6 1994/08/05 16:11:46 john + * Psuedo working version of networking. + * + * Revision 1.5 1994/08/04 19:17:20 john + * Inbetween version of network stuff. + * + * Revision 1.4 1994/07/29 16:08:59 john + * *** empty log message *** + * + * Revision 1.3 1994/07/25 12:33:22 john + * Network "pinging" in. + * + * Revision 1.2 1994/07/20 15:58:29 john + * First installment of ipx stuff. + * + * Revision 1.1 1994/07/19 15:43:05 john + * Initial revision + * + * + */ + +#ifndef _IPX_H +#define _IPX_H + +// The default socket to use. +#define IPX_DEFAULT_SOCKET 0x5100 // 0x869d + +//--------------------------------------------------------------- +// Initializes all IPX internals. +// If socket_number==0, then opens next available socket. +// Returns: 0 if successful. +// -1 if socket already open. +// -2 if socket table full. +// -3 if IPX not installed. +// -4 if couldn't allocate low dos memory +// -5 if error with getting internetwork address +extern int ipx_init( int socket_number, int show_address ); + +extern int ipx_change_default_socket( ushort socket_number ); + +// Returns a pointer to 6-byte address +extern ubyte * ipx_get_my_local_address(); +// Returns a pointer to 4-byte server +extern ubyte * ipx_get_my_server_address(); + +// Determines the local address equivalent of an internetwork address. +void ipx_get_local_target( ubyte * server, ubyte * node, ubyte * local_target ); + +// If any packets waiting to be read in, this fills data in with the packet data and returns +// the number of bytes read. Else returns 0 if no packets waiting. +extern int ipx_get_packet_data( ubyte * data ); + +// Sends a broadcast packet to everyone on this socket. +extern void ipx_send_broadcast_packet_data( ubyte * data, int datasize ); + +// Sends a packet to a certain address +extern void ipx_send_packet_data( ubyte * data, int datasize, ubyte *network, ubyte *address, ubyte *immediate_address ); +extern void ipx_send_internetwork_packet_data( ubyte * data, int datasize, ubyte * server, ubyte *address ); + +#define IPX_MAX_DATA_SIZE (542) //(546-4) + +extern void ipx_read_user_file(char * filename); +extern void ipx_read_network_file(char * filename); + +#endif + diff --git a/arch/dos/joy2.asm b/arch/dos/joy2.asm new file mode 100644 index 00000000..69d22c56 --- /dev/null +++ b/arch/dos/joy2.asm @@ -0,0 +1,471 @@ +;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +;SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +;IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +;FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +; +; $Source: /cvs/cvsroot/d2x/arch/dos/joy2.asm,v $ +; $Revision: 1.1.1.1 $ +; $Author: bradleyb $ +; $Date: 2001-01-19 03:30:15 $ +; +; Contains routines for joystick interface. +; +; $Log: not supported by cvs2svn $ +; Revision 1.1.1.1 1999/06/14 21:57:53 donut +; Import of d1x 1.37 source. +; +; Revision 1.17 1995/10/07 13:22:11 john +; Added new method of reading joystick that allows higher-priority +; interrupts to go off. +; +; Revision 1.16 1995/03/30 11:03:30 john +; Made -JoyBios read buttons using BIOS. +; +; Revision 1.15 1995/02/14 11:39:36 john +; Added polled/bios joystick readers.. +; +; Revision 1.14 1995/01/29 18:36:00 john +; Made timer count in mode 2 instead of mode 3. +; +; Revision 1.13 1994/12/28 15:32:21 john +; Added code to read joystick axis not all at one time. +; +; Revision 1.12 1994/12/27 15:44:59 john +; Made the joystick timeout be at 1/100th of a second, +; regardless of CPU speed. +; +; Revision 1.11 1994/11/15 12:04:40 john +; Cleaned up timer code a bit... took out unused functions +; like timer_get_milliseconds, etc. +; +; Revision 1.10 1994/07/01 10:55:54 john +; Fixed some bugs... added support for 4 axis. +; +; Revision 1.9 1994/06/30 20:36:54 john +; Revamped joystick code. +; +; Revision 1.8 1994/04/22 12:52:06 john + +[BITS 32] + +[SECTION .data] + + LastTick dd 0 + TotalTicks dd 0 + + global _joy_bogus_reading + global _joy_retries + extern _JOY_PORT + _joy_bogus_reading dd 0 + _joy_retries dd 0 + RetryCount dd 0 + + +[SECTION .text] + +; JOY_PORT EQU 0209h + TDATA EQU 40h + TCOMMAND EQU 43h + +joy_get_timer: + xor al, al ; Latch timer 0 command + out TCOMMAND, al ; Latch timer + in al, TDATA ; Read lo byte + mov ah, al + in al, TDATA ; Read hi byte + xchg ah, al + and eax, 0ffffh + ret + + + + +global _joy_read_stick_friendly2 +_joy_read_stick_friendly2: + push ebx + push edi + + mov ebx,[esp+12] + mov edi,[esp+16] + mov ecx,[esp+20] + + ; ebx = read mask + ; edi = pointer to event buffer + ; ecx = timeout value + ; returns in eax the number of events + + mov dword [RetryCount], 0 + mov dword [_joy_bogus_reading], 0 + +_joy_read_stick_friendly_retry: + inc dword [RetryCount] + cmp dword [RetryCount], 3 + jbe @@f1 + mov dword [_joy_bogus_reading], 1 + inc dword [_joy_retries] + mov eax, 0 + pop edi + pop ebx + ret + +@@f1: + push ecx + push ebx + push edi + + and ebx, 01111b ; Make sure we only check the right values + ; number of events we found will be in bh, so this also clears it to zero. + + mov dx, [_JOY_PORT] + + cli ; disable interrupts while reading time... + call joy_get_timer ; Returns counter in EAX + sti ; enable interrupts after reading time... + mov dword [LastTick], eax + +waitforstable_f: in al, dx + and al, bl + jz ready_f ; Wait for the port in question to be done reading... + + cli ; disable interrupts while reading time... + call joy_get_timer ; Returns counter in EAX + sti ; enable interrupts after reading time... + xchg eax, dword [LastTick] + cmp eax, dword [LastTick] + jb @@f2 + sub eax, dword [LastTick] +@@f2: ; Higher... + add dword [TotalTicks], eax + cmp dword [TotalTicks], ecx ; Timeout at 1/200'th of a second + jae ready_f + jmp waitforstable_f + +ready_f: + cli + mov al, 0ffh + out dx, al ; Start joystick a readin' + + call joy_get_timer ; Returns counter in EAX + mov dword [LastTick], eax + mov dword [TotalTicks], 0 + + mov [edi], eax ; Store initial count + add edi, 4 + +again_f: in al, dx ; Read Joystick port + not al + and al, bl ; Mask off channels we don't want to read + jnz flip_f ; See if any of the channels flipped + + ; none flipped -- check any interrupts... + mov al, 0Ah + out 20h, al + in al, 20h ; Get interrupts pending + cmp al, 0 + je NoInts + + ; Need to do an interrupt + sti + nop ; let the interrupt go on... + cli + + ; See if any axis turned + in al, dx + not al + and al, bl + jz NoInts + + ; At this point, an interrupt occured, making one or more + ; of the axis values bogus. So, we will restart this process... + + pop edi + pop ebx + pop ecx + + jmp _joy_read_stick_friendly_retry + +NoInts: + call joy_get_timer ; Returns counter in EAX + + xchg eax, dword [LastTick] + cmp eax, dword [LastTick] + jb @@f3 + sub eax, dword [LastTick] +@@f3: ; Higher... + add dword [TotalTicks], eax + cmp dword [TotalTicks], ecx ; Timeout at 1/200'th of a second + jae timed_out_f + jmp again_f + + flip_f: and eax, 01111b ; Only care about axis values + mov [edi], eax ; Record what channel(s) flipped + add edi, 4 + xor bl, al ; Unmark the channels that just tripped + + call joy_get_timer ; Returns counter in EAX + mov [edi], eax ; Record the time this channel flipped + add edi, 4 + inc bh ; Increment number of events + + cmp bl, 0 + jne again_f ; If there are more channels to read, keep looping + + timed_out_f: + sti + + movzx eax, bh ; Return number of events + + pop edi + pop ebx + pop ecx + + pop edi + pop ebx + ret + + + +global _joy_read_stick_asm2 + +_joy_read_stick_asm2: + push ebx + push edi + + mov ebx,[esp+12] + mov edi,[esp+16] + mov ecx,[esp+20] + + ; ebx = read mask + ; edi = pointer to event buffer + ; ecx = timeout value + ; returns in eax the number of events + mov dword [_joy_bogus_reading], 0 + + and ebx, 01111b ; Make sure we only check the right values + ; number of events we found will be in bh, so this also clears it to zero. + + mov dx, [_JOY_PORT] + + cli ; disable interrupts while reading time... + call joy_get_timer ; Returns counter in EAX + sti ; enable interrupts after reading time... + mov dword [LastTick], eax + +waitforstable: in al, dx + and al, bl + jz ready ; Wait for the port in question to be done reading... + + cli ; disable interrupts while reading time... + call joy_get_timer ; Returns counter in EAX + sti ; enable interrupts after reading time... + xchg eax, dword [LastTick] + cmp eax, dword [LastTick] + jb @@f4 + sub eax, dword [LastTick] +@@f4: ; Higher... + add dword [TotalTicks], eax + cmp dword [TotalTicks], ecx ; Timeout at 1/200'th of a second + jae ready + jmp waitforstable + +ready: + cli + mov al, 0ffh + out dx, al ; Start joystick a readin' + + call joy_get_timer ; Returns counter in EAX + mov dword [LastTick], eax + mov dword [TotalTicks], 0 + + mov [edi], eax ; Store initial count + add edi, 4 + + again: in al, dx ; Read Joystick port + not al + and al, bl ; Mask off channels we don't want to read + jnz flip ; See if any of the channels flipped + + call joy_get_timer ; Returns counter in EAX + + xchg eax, dword [LastTick] + cmp eax, dword [LastTick] + jb @@f5 + sub eax, dword [LastTick] +@@f5: ; Higher... + add dword [TotalTicks], eax + cmp dword [TotalTicks], ecx ; Timeout at 1/200'th of a second + jae timedout + jmp again + + flip: and eax, 01111b ; Only care about axis values + mov [edi], eax ; Record what channel(s) flipped + add edi, 4 + xor bl, al ; Unmark the channels that just tripped + + call joy_get_timer ; Returns counter in EAX + mov [edi], eax ; Record the time this channel flipped + add edi, 4 + inc bh ; Increment number of events + + cmp bl, 0 + jne again ; If there are more channels to read, keep looping + + timedout: + movzx eax, bh ; Return number of events + + sti + pop edi + pop ebx + ret + + +global _joy_read_stick_polled2 + +_joy_read_stick_polled2: + push ebx + push edi + + mov ebx,[esp+12] + mov edi,[esp+16] + mov ecx,[esp+20] + + ; ebx = read mask + ; edi = pointer to event buffer + ; ecx = timeout value + ; returns in eax the number of events + mov dword [_joy_bogus_reading], 0 + + and ebx, 01111b ; Make sure we only check the right values + ; number of events we found will be in bh, so this also clears it to zero. + + mov dx, [_JOY_PORT] + + mov dword [TotalTicks], 0 + +waitforstable1: in al, dx + and al, bl + jz ready1 ; Wait for the port in question to be done reading... + + inc dword [TotalTicks] + cmp dword [TotalTicks], ecx ; Timeout at 1/200'th of a second + jae ready1 + jmp waitforstable1 +ready1: + cli + mov al, 0ffh + out dx, al ; Start joystick a readin' + + mov dword [TotalTicks], 0 + + mov dword [edi], 0 ; Store initial count + add edi, 4 + + again1: in al, dx ; Read Joystick port + not al + and al, bl ; Mask off channels we don't want to read + jnz flip1 ; See if any of the channels flipped + + inc dword [TotalTicks] + cmp dword [TotalTicks], ecx ; Timeout at 1/200'th of a second + jae timedout1 + jmp again1 + + flip1: and eax, 01111b ; Only care about axis values + mov [edi], eax ; Record what channel(s) flipped + add edi, 4 + xor bl, al ; Unmark the channels that just tripped + + mov eax, dword [TotalTicks] + mov [edi], eax ; Record the time this channel flipped + add edi, 4 + inc bh ; Increment number of events + + cmp bl, 0 + jne again1 ; If there are more channels to read, keep looping + + timedout1: + movzx eax, bh ; Return number of events + + sti + pop edi + pop ebx + ret + +global _joy_read_stick_bios2 + +_joy_read_stick_bios2: + push ebx + push edi + + mov ebx,[esp+12] + mov edi,[esp+16] + mov ecx,[esp+20] + ; ebx = read mask + ; edi = pointer to event buffer + ; ecx = timeout value + ; returns in eax the number of events + + mov dword [_joy_bogus_reading], 0 + + pusha + + mov dword [edi], 0 + + mov eax, 08400h + mov edx, 1 + cli + int 15h + sti + + mov dword [edi+4], 1 ; Axis 1 + and eax, 0ffffh + mov [edi+8], eax ; Axis 1 value + + mov dword [edi+12], 2 ; Axis 2 + and ebx, 0ffffh + mov [edi+16], ebx ; Axis 2 value + + mov dword [edi+20], 4 ; Axis 3 + and ecx, 0ffffh + mov [edi+24], ecx ; Axis 3 value + + mov dword [edi+28], 8 ; Axis 3 + and edx, 0ffffh + mov [edi+32], edx ; Axis 3 value + + popa + mov eax, 4 ; 4 events + + pop edi + pop ebx + ret + + +global _joy_read_buttons_bios2 + +_joy_read_buttons_bios2: + ; returns in eax the button settings + + push ebx + push ecx + push edx + mov eax, 08400h + mov edx, 0 ; Read switches + int 15h + pop edx + pop ecx + pop ebx + + shr eax, 4 + not eax + and eax, 01111b + ret +global _joy_read_buttons_bios_end2 +_joy_read_buttons_bios_end2: ; to calculate _joy_read_buttons_bios size + diff --git a/arch/dos/joyc.c b/arch/dos/joyc.c new file mode 100644 index 00000000..442873ab --- /dev/null +++ b/arch/dos/joyc.c @@ -0,0 +1,803 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/arch/dos/joyc.c,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:15 $ + * + * Routines for joystick reading. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 21:58:26 donut + * Import of d1x 1.37 source. + * + * Revision 1.37 1995/10/07 13:22:31 john + * Added new method of reading joystick that allows higher-priority + * interrupts to go off. + * + * Revision 1.36 1995/03/30 11:03:40 john + * Made -JoyBios read buttons using BIOS. + * + * Revision 1.35 1995/02/14 11:39:25 john + * Added polled/bios joystick readers.. + * + * Revision 1.34 1995/02/10 17:06:12 john + * Fixed bug with plugging in a joystick not getting detected. + * + * Revision 1.33 1995/01/27 16:39:42 john + * Made so that if no joystick detected, it wont't + * read buttons. + * + * Revision 1.32 1995/01/12 13:16:40 john + * Made it so that joystick can't lose an axis + * by 1 weird reading. Reading has to occurr during + * calibration for this to happen. + * + * Revision 1.31 1994/12/28 15:56:03 john + * Fixed bug that refused to read joysticks whose + * min,cen,max were less than 100 apart. + * + * Revision 1.30 1994/12/28 15:31:53 john + * Added code to read joystick axis not all at one time. + * + * Revision 1.29 1994/12/27 15:44:36 john + * Made the joystick timeout be at 1/100th of a second, + * regardless of CPU speed. + * + * Revision 1.28 1994/12/04 11:54:54 john + * Made stick read at whatever rate the clock is at, not + * at 18.2 times/second. + * + * Revision 1.27 1994/11/29 02:25:40 john + * Made it so that the scaled reading returns 0 + * if the calibration factors look funny.. + * + * Revision 1.26 1994/11/22 11:08:07 john + * Commented out the ARCADE joystick. + * + * Revision 1.25 1994/11/14 19:40:26 john + * Fixed bug with no joystick being detected. + * + * Revision 1.24 1994/11/14 19:36:40 john + * Took out initial cheapy calibration. + * + * Revision 1.23 1994/11/14 19:13:27 john + * Took out the calibration in joy_init + * + * Revision 1.22 1994/10/17 10:09:57 john + * Made the state look at last_State, so that a joy_flush + * doesn't cause a new down state to be added next reading. + * + * Revision 1.21 1994/10/13 11:36:23 john + * Made joy_down_time be kept track of in fixed seconds, + * not ticks. + * + * Revision 1.20 1994/10/12 16:58:50 john + * Fixed bug w/ previous comment. + * + * Revision 1.19 1994/10/12 16:57:44 john + * Added function to set a joystick button's state. + * + * Revision 1.18 1994/10/11 10:20:13 john + * Fixed Flightstick Pro/ + * .. + * + * Revision 1.17 1994/09/29 18:29:20 john + * *** empty log message *** + * + * Revision 1.16 1994/09/27 19:17:23 john + * Added code so that is joy_init is never called, joystick is not + * used at all. + * + * Revision 1.15 1994/09/22 16:09:23 john + * Fixed some virtual memory lockdown problems with timer and + * joystick. + * + * Revision 1.14 1994/09/16 11:44:42 john + * Fixed bug with slow joystick. + * + * Revision 1.13 1994/09/16 11:36:15 john + * Fixed bug with reading non-present channels. + * + * Revision 1.12 1994/09/15 20:52:48 john + * rme john + * Added support for the Arcade style joystick. + * + * Revision 1.11 1994/09/13 20:04:49 john + * Fixed bug with joystick button down_time. + * + * Revision 1.10 1994/09/10 13:48:07 john + * Made all 20 buttons read. + * + * Revision 1.9 1994/08/31 09:55:02 john + * *** empty log message *** + * + * Revision 1.8 1994/08/29 21:02:14 john + * Added joy_set_cal_values... + * + * Revision 1.7 1994/08/29 20:52:17 john + * Added better cyberman support; also, joystick calibration + * value return funcctiionn, + * + * Revision 1.6 1994/08/24 18:53:12 john + * Made Cyberman read like normal mouse; added dpmi module; moved + * mouse from assembly to c. Made mouse buttons return time_down. + * + * Revision 1.5 1994/07/14 22:12:23 john + * Used intrinsic forms of outp to fix vmm error. + * + * Revision 1.4 1994/07/07 19:52:59 matt + * Made joy_init() return success/fail flag + * Made joy_init() properly detect a stick if one is plugged in after joy_init() + * was called the first time. + * + * Revision 1.3 1994/07/01 10:55:55 john + * Fixed some bugs... added support for 4 axis. + * + * Revision 1.2 1994/06/30 20:36:55 john + * Revamped joystick code. + * + * Revision 1.1 1994/06/30 15:42:15 john + * Initial revision + * + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: joyc.c,v 1.1.1.1 2001-01-19 03:30:15 bradleyb Exp $"; +#endif + +#include +#include +#include +#include +#include + +//#define ARCADE 1 + +#include "types.h" +#include "mono.h" +#include "joy.h" +#include "u_dpmi.h" +#include "timer.h" + +#include "args.h" + +extern int joy_bogus_reading; +int JOY_PORT = 513; //201h; +int joy_deadzone = 0; + +int joy_read_stick_asm2( int read_masks, int * event_buffer, int timeout ); +int joy_read_stick_friendly2( int read_masks, int * event_buffer, int timeout ); +int joy_read_stick_polled2( int read_masks, int * event_buffer, int timeout ); +int joy_read_stick_bios2( int read_masks, int * event_buffer, int timeout ); +int joy_read_buttons_bios2(); +void joy_read_buttons_bios_end2(); + + +//In key.c +// ebx = read mask +// edi = pointer to buffer +// returns number of events + +char joy_installed = 0; +char joy_present = 0; + +typedef struct Button_info { + ubyte ignore; + ubyte state; + ubyte last_state; + int timedown; + ubyte downcount; + ubyte upcount; +} Button_info; + +typedef struct Joy_info { + ubyte present_mask; + ubyte slow_read; + int max_timer; + int read_count; + ubyte last_value; + Button_info buttons[MAX_BUTTONS]; + int axis_min[4]; + int axis_center[4]; + int axis_max[4]; +} Joy_info; + +Joy_info joystick; + +ubyte joy_read_buttons() +{ + return ((~(inp(JOY_PORT) >> 4))&0xf); +} + +void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max) +{ + int i; + + for (i=0; i<4; i++) { + axis_min[i] = joystick.axis_min[i]; + axis_center[i] = joystick.axis_center[i]; + axis_max[i] = joystick.axis_max[i]; + } +} + +void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max) +{ + int i; + + for (i=0; i<4; i++) { + joystick.axis_min[i] = axis_min[i]; + joystick.axis_center[i] = axis_center[i]; + joystick.axis_max[i] = axis_max[i]; + } +} + + +ubyte joy_get_present_mask() { + return joystick.present_mask; +} + +void joy_set_timer_rate(int max_value ) { + _disable(); + joystick.max_timer = max_value; + _enable(); +} + +int joy_get_timer_rate() { + return joystick.max_timer; +} + + +void joy_flush() { + int i; + + if (!joy_installed) return; + + _disable(); + for (i=0; i 7 ) { + joystick.read_count = 0; + value = joy_read_buttons_bios2(); + joystick.last_value = value; + } else { + value = joystick.last_value; + } + } else { + value = joy_read_buttons(); //JOY_READ_BUTTONS; + } + + for (i=0; iignore) { + if ( i < 5 ) + state = (value >> i) & 1; + else if (i==(value+4)) + state = 1; + else + state = 0; + + if ( button->last_state == state ) { + if (state) button->timedown += ticks_this_time; + } else { + if (state) { + button->downcount += state; + button->state = 1; + } else { + button->upcount += button->state; + button->state = 0; + } + button->last_state = state; + } + } + } +} + +void joy_handler_end() { // Dummy function to help calculate size of joystick handler function +} + +#pragma off (check_stack) + +ubyte joy_read_raw_buttons() { + if ( joystick.slow_read & JOY_BIOS_READINGS ) + return joy_read_buttons_bios2(); + else + return joy_read_buttons(); //JOY_READ_BUTTONS; +} + +void joy_set_slow_reading(int flag) +{ + joystick.slow_read |= flag; + joy_set_cen(); +} + +ubyte joystick_read_raw_axis( ubyte mask, int * axis ) +{ + ubyte read_masks, org_masks; + int t, t1, t2, buffer[4*2+2]; + int e, i, num_channels, c; + + axis[0] = 0; axis[1] = 0; + axis[2] = 0; axis[3] = 0; + + if (!joy_installed) return 0; + + read_masks = 0; + org_masks = mask; + + mask &= joystick.present_mask; // Don't read non-present channels + if ( mask==0 ) { + return 0; // Don't read if no stick connected. + } + + if ( joystick.slow_read & JOY_SLOW_READINGS ) { + for (c=0; c<4; c++ ) { + if ( mask & (1 << c)) { + // Time out at (1/100th of a second) + + if ( joystick.slow_read & JOY_POLLED_READINGS ) + num_channels = joy_read_stick_polled2( (1 << c), buffer, 65536 ); + else if ( joystick.slow_read & JOY_BIOS_READINGS ) + num_channels = joy_read_stick_bios2( (1 << c), buffer, 65536 ); + else if ( joystick.slow_read & JOY_FRIENDLY_READINGS ) + num_channels = joy_read_stick_friendly2( (1 << c), buffer, (1193180/100) ); + else + num_channels = joy_read_stick_asm2( (1 << c), buffer, (1193180/100) ); + + if ( num_channels > 0 ) { + t1 = buffer[0]; + e = buffer[1]; + t2 = buffer[2]; + if ( joystick.slow_read & (JOY_POLLED_READINGS|JOY_BIOS_READINGS) ) { + t = t2 - t1; + } else { + if ( t1 > t2 ) + t = t1 - t2; + else { + t = t1 + joystick.max_timer - t2; + //mprintf( 0, "%d, %d, %d, %d\n", t1, t2, joystick.max_timer, t ); + } + } + + if ( e & 1 ) { axis[0] = t; read_masks |= 1; } + if ( e & 2 ) { axis[1] = t; read_masks |= 2; } + if ( e & 4 ) { axis[2] = t; read_masks |= 4; } + if ( e & 8 ) { axis[3] = t; read_masks |= 8; } + } + } + } + } else { + // Time out at (1/100th of a second) + if ( joystick.slow_read & JOY_POLLED_READINGS ) + num_channels = joy_read_stick_polled2( mask, buffer, 65536 ); + else if ( joystick.slow_read & JOY_BIOS_READINGS ) + num_channels = joy_read_stick_bios2( mask, buffer, 65536 ); + else if ( joystick.slow_read & JOY_FRIENDLY_READINGS ) + num_channels = joy_read_stick_friendly2( mask, buffer, (1193180/100) ); + else + num_channels = joy_read_stick_asm2( mask, buffer, (1193180/100) ); + //mprintf(( 0, "(%d)\n", num_channels )); + + for (i=0; i t2 ) + t = t1 - t2; + else { + t = t1 + joystick.max_timer - t2; + //mprintf(( 0, "%d, %d, %d, %d\n", t1, t2, joystick.max_timer, t )); + } + } + e = buffer[i*2+1]; + + if ( e & 1 ) { axis[0] = t; read_masks |= 1; } + if ( e & 2 ) { axis[1] = t; read_masks |= 2; } + if ( e & 4 ) { axis[2] = t; read_masks |= 4; } + if ( e & 8 ) { axis[3] = t; read_masks |= 8; } + } + + } + + return read_masks; +} + +#ifdef __GNUC__ +#define near +#endif + +int joy_init() +{ + int i; + int temp_axis[4]; + +// if(FindArg("-joy209")) +// use_alt_joyport=1; + if(FindArg("-joy209")) + JOY_PORT = 521; //209h; + + joy_flush(); + + _disable(); + for (i=0; i 127 ) + x = 127; + +//added on 4/13/99 by Victor Rachels to add deadzone control + dz = (joy_deadzone) * 6; + if ((x > (-1*dz)) && (x < dz)) + x = 0; +//end this section addition -VR + + return x; +} + +int last_reading[4] = { 0, 0, 0, 0 }; + +void joy_get_pos( int *x, int *y ) +{ + ubyte flags; + int axis[4]; + + if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; } + + flags=joystick_read_raw_axis( JOY_1_X_AXIS+JOY_1_Y_AXIS, axis ); + + if ( joy_bogus_reading ) { + axis[0] = last_reading[0]; + axis[1] = last_reading[1]; + flags = JOY_1_X_AXIS+JOY_1_Y_AXIS; + } else { + last_reading[0] = axis[0]; + last_reading[1] = axis[1]; + } + + if ( flags & JOY_1_X_AXIS ) + *x = joy_get_scaled_reading( axis[0], 0 ); + else + *x = 0; + + if ( flags & JOY_1_Y_AXIS ) + *y = joy_get_scaled_reading( axis[1], 1 ); + else + *y = 0; +} + +ubyte joy_read_stick( ubyte masks, int *axis ) +{ + ubyte flags; + int raw_axis[4]; + + if ((!joy_installed)||(!joy_present)) { + axis[0] = 0; axis[1] = 0; + axis[2] = 0; axis[3] = 0; + return 0; + } + + flags=joystick_read_raw_axis( masks, raw_axis ); + + if ( joy_bogus_reading ) { + axis[0] = last_reading[0]; + axis[1] = last_reading[1]; + axis[2] = last_reading[2]; + axis[3] = last_reading[3]; + flags = masks; + } else { + last_reading[0] = axis[0]; + last_reading[1] = axis[1]; + last_reading[2] = axis[2]; + last_reading[3] = axis[3]; + } + + if ( flags & JOY_1_X_AXIS ) + axis[0] = joy_get_scaled_reading( raw_axis[0], 0 ); + else + axis[0] = 0; + + if ( flags & JOY_1_Y_AXIS ) + axis[1] = joy_get_scaled_reading( raw_axis[1], 1 ); + else + axis[1] = 0; + + if ( flags & JOY_2_X_AXIS ) + axis[2] = joy_get_scaled_reading( raw_axis[2], 2 ); + else + axis[2] = 0; + + if ( flags & JOY_2_Y_AXIS ) + axis[3] = joy_get_scaled_reading( raw_axis[3], 3 ); + else + axis[3] = 0; + + return flags; +} + + +int joy_get_btns() +{ + if ((!joy_installed)||(!joy_present)) return 0; + + return joy_read_raw_buttons(); +} + +void joy_get_btn_down_cnt( int *btn0, int *btn1 ) +{ + if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; } + + _disable(); + *btn0 = joystick.buttons[0].downcount; + joystick.buttons[0].downcount = 0; + *btn1 = joystick.buttons[1].downcount; + joystick.buttons[1].downcount = 0; + _enable(); +} + +int joy_get_button_state( int btn ) +{ + int count; + + if ((!joy_installed)||(!joy_present)) return 0; + + if ( btn >= MAX_BUTTONS ) return 0; + + _disable(); + count = joystick.buttons[btn].state; + _enable(); + + return count; +} + +int joy_get_button_up_cnt( int btn ) +{ + int count; + + if ((!joy_installed)||(!joy_present)) return 0; + + if ( btn >= MAX_BUTTONS ) return 0; + + _disable(); + count = joystick.buttons[btn].upcount; + joystick.buttons[btn].upcount = 0; + _enable(); + + return count; +} + +int joy_get_button_down_cnt( int btn ) +{ + int count; + + if ((!joy_installed)||(!joy_present)) return 0; + if ( btn >= MAX_BUTTONS ) return 0; + + _disable(); + count = joystick.buttons[btn].downcount; + joystick.buttons[btn].downcount = 0; + _enable(); + + return count; +} + + +fix joy_get_button_down_time( int btn ) +{ + fix count; + + if ((!joy_installed)||(!joy_present)) return 0; + if ( btn >= MAX_BUTTONS ) return 0; + + _disable(); + count = joystick.buttons[btn].timedown; + joystick.buttons[btn].timedown = 0; + _enable(); + + return fixmuldiv(count, 65536, 1193180 ); +} + +void joy_get_btn_up_cnt( int *btn0, int *btn1 ) +{ + if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; } + + _disable(); + *btn0 = joystick.buttons[0].upcount; + joystick.buttons[0].upcount = 0; + *btn1 = joystick.buttons[1].upcount; + joystick.buttons[1].upcount = 0; + _enable(); +} + +void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount ) +{ + _disable(); + joystick.buttons[btn].ignore = 1; + joystick.buttons[btn].state = state; + joystick.buttons[btn].timedown = fixmuldiv( timedown, 1193180, 65536 ); + joystick.buttons[btn].downcount = downcount; + joystick.buttons[btn].upcount = upcount; + _enable(); +} + +void joy_poll() +{ + if ( joystick.slow_read & JOY_BIOS_READINGS ) + joystick.last_value = joy_read_buttons_bios2(); +} diff --git a/arch/dos/joydefs.c b/arch/dos/joydefs.c new file mode 100644 index 00000000..e9b74514 --- /dev/null +++ b/arch/dos/joydefs.c @@ -0,0 +1,678 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/arch/dos/joydefs.c,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:15 $ + * + * . + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 21:58:29 donut + * Import of d1x 1.37 source. + * + * Revision 2.2 1995/06/30 12:30:22 john + * Added -Xname command line. + * + * Revision 2.1 1995/04/06 12:13:20 john + * Made so you can calibrate Gravis Gamepad. + * + * Revision 2.0 1995/02/27 11:30:27 john + * New version 2.0, which has no anonymous unions, builds with + * Watcom 10.0, and doesn't require parsing BITMAPS.TBL. + * + * Revision 1.71 1995/02/12 02:06:10 john + * Fixed bug with joystick incorrectly asking for + * calibration. + * + * Revision 1.70 1995/01/28 15:58:07 john + * Made joystick calibration be only when wrong detected in + * menu or joystick axis changed. + * + * Revision 1.69 1995/01/25 14:37:55 john + * Made joystick only prompt for calibration once... + * + * Revision 1.68 1995/01/24 16:34:29 john + * Made so that if you reconfigure joystick and + * add or subtract an axis, it asks for a recalibration + * upon leaving. + * + * Revision 1.67 1994/12/29 11:08:51 john + * Fixed Thrustmaster and Logitech Wingman extreme + * Hat by reading the y2 axis during the center stage + * of the calibration, and using 75, 50, 27, and 3 % + * as values for the 4 positions. + * + * Revision 1.66 1994/12/15 18:17:39 john + * Fixed warning with previous. + * + * Revision 1.65 1994/12/15 18:15:48 john + * Made the joy cal only write the .cfg file, not + * the player file. + * + * Revision 1.64 1994/12/13 14:43:35 john + * Took out the code in kconfig to build direction array. + * Called kc_set_controls after selecting a new control type. + * + * Revision 1.63 1994/12/10 12:08:47 john + * Changed some delays to use TICKER instead of timer_get_fixed_seconds. + * + * Revision 1.62 1994/12/09 11:01:07 mike + * force calibration of joystick on joystick selection from Controls... menu. + * + * Revision 1.61 1994/12/07 21:50:27 john + * Put stop/start time around joystick delay. + * + * Revision 1.60 1994/12/07 19:34:39 john + * Added delay. + * + * Revision 1.59 1994/12/07 18:12:14 john + * NEatened up joy cal., + * + * Revision 1.58 1994/12/07 17:07:51 john + * Fixed up joy cal. + * + * Revision 1.57 1994/12/07 16:48:53 yuan + * localization + * + * Revision 1.56 1994/12/07 16:05:55 john + * Changed the way joystick calibration works. + * + * Revision 1.55 1994/12/06 20:15:22 john + * Took out code that unpauses songs that were never paused. + * + * Revision 1.54 1994/12/06 15:14:09 yuan + * Localization + * + * Revision 1.53 1994/12/05 16:29:16 john + * Took out music pause around the cheat menu. + * + * Revision 1.52 1994/12/04 12:39:10 john + * MAde so that FCS calibration doesn't ask for axis #2. + * + * Revision 1.51 1994/12/03 15:14:59 john + * Took out the delay mentioned previosuly cause it would + * cause bigger problems than it helps, especially with netgames. + * + * Revision 1.50 1994/12/03 14:16:14 john + * Put a delay between screens in joy cal to keep Yuan from + * double hitting. + * + * Revision 1.49 1994/12/03 11:04:06 john + * Changed newmenu code a bit to fix bug with bogus + * backgrounds occcasionally. + * + * Revision 1.48 1994/12/02 11:03:44 yuan + * Localization. + * + * Revision 1.47 1994/12/02 10:50:33 yuan + * Localization + * + * Revision 1.46 1994/12/01 12:21:59 john + * Added code to calibrate 2 joysticks separately. + * + * Revision 1.45 1994/12/01 11:52:31 john + * Added message when you select FCS to say that if + * you have WCS, see manuel. + * + * Revision 1.44 1994/11/29 02:26:28 john + * Made the prompts for upper-left, lower right for joy + * calibration more obvious. + * + * Revision 1.43 1994/11/26 13:13:59 matt + * Changed "none" option to "keyboard only" + * + * Revision 1.42 1994/11/21 19:35:13 john + * Replaced calls to joy_init with if (joy_present) + * + * Revision 1.41 1994/11/21 19:28:34 john + * Changed warning for no joystick to use nm_messagebox.. + * + * Revision 1.40 1994/11/21 19:06:25 john + * Made it so that it only stops sound when your in game mode. + * + * Revision 1.39 1994/11/21 11:47:18 john + * Made sound pause during joystick calibration. + * + * Revision 1.38 1994/11/10 20:34:18 rob + * Removed menu-specific network mode support in favor in new stuff + * in newmenu.c + * + * Revision 1.37 1994/11/08 21:21:38 john + * Made Esc exit joystick calibration. + * + * Revision 1.36 1994/11/08 15:14:42 john + * Added more calls so net doesn't die in net game. + * + * Revision 1.35 1994/11/08 14:59:12 john + * Added code to respond to network while in menus. + * + * Revision 1.34 1994/10/24 19:56:32 john + * Made the new user setup prompt for config options. + * + * Revision 1.33 1994/10/22 14:11:52 mike + * Suppress compiler warning message. + * + * Revision 1.32 1994/10/19 12:44:24 john + * Added hours field to player structure. + * + * Revision 1.31 1994/10/17 13:07:13 john + * Moved the descent.cfg info into the player config file. + * + * Revision 1.30 1994/10/13 21:41:12 john + * MAde Esc exit out of joystick calibration. + * + * Revision 1.29 1994/10/13 19:22:27 john + * Added separate config saves for different devices. + * Made all the devices work together better, such as mice won't + * get read when you're playing with the joystick. + * + * Revision 1.28 1994/10/13 11:40:18 john + * Took out warnings. + * + * Revision 1.27 1994/10/13 11:35:23 john + * Made Thrustmaster FCS Hat work. Put a background behind the + * keyboard configure. Took out turn_sensitivity. Changed sound/config + * menu to new menu. Made F6 be calibrate joystick. + * + * Revision 1.26 1994/10/11 21:29:03 matt + * Made a bunch of menus have good initial selected values + * + * Revision 1.25 1994/10/11 17:08:39 john + * Added sliders for volume controls. + * + * Revision 1.24 1994/10/10 17:59:21 john + * Neatend previous. + * + * Revision 1.23 1994/10/10 17:57:59 john + * Neatend previous. + * + * Revision 1.22 1994/10/10 17:56:11 john + * Added messagebox that tells that config has been saved. + * + * Revision 1.21 1994/09/30 12:37:26 john + * Added midi,digi volume to configuration. + * + * Revision 1.20 1994/09/22 16:14:14 john + * Redid intro sequecing. + * + * Revision 1.19 1994/09/19 18:50:15 john + * Added switch to disable joystick. + * + * Revision 1.18 1994/09/12 11:47:36 john + * Made stupid cruise work better. Make kconfig values get + * read/written to disk. + * + * Revision 1.17 1994/09/10 15:46:47 john + * First version of new keyboard configuration. + * + * Revision 1.16 1994/09/06 19:35:44 john + * Fixed bug that didn';t load new size .cal file. + * + * Revision 1.15 1994/09/06 14:51:58 john + * Added sensitivity adjustment, fixed bug with joystick button not + * staying down. + * + * Revision 1.14 1994/09/02 16:13:47 john + * Made keys fill in position. + * + * Revision 1.13 1994/08/31 17:58:50 john + * Made a bit simpler. + * + * Revision 1.12 1994/08/31 14:17:54 john + * *** empty log message *** + * + * Revision 1.11 1994/08/31 14:10:56 john + * Made keys not work when KEY_DELETE pressed. + * + * Revision 1.10 1994/08/31 13:40:47 mike + * Change constant + * + * Revision 1.9 1994/08/31 12:56:27 john + * *** empty log message *** + * + * Revision 1.8 1994/08/30 20:38:29 john + * Add more config stuff.. + * + * Revision 1.7 1994/08/30 16:37:25 john + * Added menu options to set controls. + * + * Revision 1.6 1994/08/30 09:27:18 john + * *** empty log message *** + * + * Revision 1.5 1994/08/30 09:12:01 john + * *** empty log message *** + * + * Revision 1.4 1994/08/29 21:18:32 john + * First version of new keyboard/oystick remapping stuff. + * + * Revision 1.3 1994/08/24 19:00:29 john + * Changed key_down_time to return fixed seconds instead of + * milliseconds. + * + * Revision 1.2 1994/08/17 16:50:37 john + * Added damaging fireballs, missiles. + * + * Revision 1.1 1994/08/17 10:07:12 john + * Initial revision + * + * + */ + + +#ifdef RCS +#pragma off (unreferenced) +static char rcsid[] = "$Id: joydefs.c,v 1.1.1.1 2001-01-19 03:30:15 bradleyb Exp $"; +#pragma on (unreferenced) +#endif + +#include +#include +#include + +#include "mono.h" +#include "key.h" +#include "joy.h" +#include "timer.h" +#include "error.h" + +#include "inferno.h" +#include "game.h" +#include "object.h" +#include "player.h" + +#include "controls.h" +#include "joydefs.h" +#include "render.h" +#include "palette.h" +#include "newmenu.h" +#include "args.h" +#include "text.h" +#include "kconfig.h" +#include "digi.h" +#include "playsave.h" + +int joydefs_calibrate_flag = 0; + +void joy_delay() +{ +#ifdef __MSDOS__ + int t1 = TICKER + 19/4; // Wait 1/4 second... + stop_time(); + while( TICKER < t1 ); + joy_flush(); + start_time(); +#endif +} + + +int joycal_message( char * title, char * text ) +{ + int i; + newmenu_item m[2]; + m[0].type = NM_TYPE_TEXT; m[0].text = text; + m[1].type = NM_TYPE_MENU; m[1].text = TXT_OK; + i = newmenu_do( title, NULL, 2, m, NULL ); + if ( i < 0 ) + return 1; + return 0; +} + +extern int WriteConfigFile(); + +void joydefs_calibrate() +{ + ubyte masks; + int org_axis_min[4]; + int org_axis_center[4]; + int org_axis_max[4]; + + int axis_min[4] = { 0, 0, 0, 0 }; + int axis_cen[4] = { 0, 0, 0, 0 }; + int axis_max[4] = { 0, 0, 0, 0 }; + + int temp_values[4]; + char title[50]; + char text[50]; + int nsticks = 0; + + joydefs_calibrate_flag = 0; + + if ( (Config_control_type!=CONTROL_JOYSTICK) && (Config_control_type!=CONTROL_FLIGHTSTICK_PRO) && (Config_control_type!=CONTROL_THRUSTMASTER_FCS) && (Config_control_type!=CONTROL_GRAVIS_GAMEPAD) ) + return; + + joy_get_cal_vals(org_axis_min, org_axis_center, org_axis_max); + + joy_set_cen(); + joystick_read_raw_axis( JOY_ALL_AXIS, temp_values ); + + if (!joy_present) { + nm_messagebox( NULL, 1, TXT_OK, TXT_NO_JOYSTICK ); + return; + } + + masks = joy_get_present_mask(); + + if ( masks == JOY_ALL_AXIS ) + nsticks = 2; + else + nsticks = 1; + + if ( nsticks == 2 && !Joy_is_Sidewinder) { + sprintf( title, "%s #1\n%s", TXT_JOYSTICK, TXT_UPPER_LEFT); + sprintf( text, "%s #1 %s", TXT_MOVE_JOYSTICK, TXT_TO_UL); + } else { + sprintf( title, "%s\n%s", TXT_JOYSTICK, TXT_UPPER_LEFT); + sprintf( text, "%s %s", TXT_MOVE_JOYSTICK, TXT_TO_UL); + } + if (joycal_message( title, text )) { + joy_set_cal_vals(org_axis_min, org_axis_center, org_axis_max); + return; + } + joystick_read_raw_axis( JOY_ALL_AXIS, temp_values ); + axis_min[0] = temp_values[0]; + axis_min[1] = temp_values[1]; + joy_delay(); + + if ( nsticks == 2 && !Joy_is_Sidewinder) { + sprintf( title, "%s #1\n%s", TXT_JOYSTICK, TXT_LOWER_RIGHT); + sprintf( text, "%s #1 %s", TXT_MOVE_JOYSTICK, TXT_TO_LR); + } else { + sprintf( title, "%s\n%s", TXT_JOYSTICK, TXT_LOWER_RIGHT); + sprintf( text, "%s %s", TXT_MOVE_JOYSTICK, TXT_TO_LR); + } + if (joycal_message( title, text)) { + joy_set_cal_vals(org_axis_min, org_axis_center, org_axis_max); + return; + } + joystick_read_raw_axis( JOY_ALL_AXIS, temp_values ); + axis_max[0] = temp_values[0]; + axis_max[1] = temp_values[1]; + joy_delay(); + + if ( nsticks == 2 && !Joy_is_Sidewinder) { + sprintf( title, "%s #1\n%s", TXT_JOYSTICK, TXT_CENTER); + sprintf( text, "%s #1 %s", TXT_MOVE_JOYSTICK, TXT_TO_C); + } else { + sprintf( title, "%s\n%s", TXT_JOYSTICK, TXT_CENTER); + sprintf( text, "%s %s", TXT_MOVE_JOYSTICK, TXT_TO_C); + } + if (joycal_message( title, text)) { + joy_set_cal_vals(org_axis_min, org_axis_center, org_axis_max); + return; + } + joystick_read_raw_axis( JOY_ALL_AXIS, temp_values ); + axis_cen[0] = temp_values[0]; + axis_cen[1] = temp_values[1]; + joy_delay(); + + // The fcs uses axes 3 for hat, so don't calibrate it. + if (Config_control_type == CONTROL_THRUSTMASTER_FCS) { + axis_min[3] = 0; + axis_cen[3] = temp_values[3]/2; + axis_max[3] = temp_values[3]; + joy_delay(); + } + + if (Joy_is_Sidewinder || Config_control_type != CONTROL_THRUSTMASTER_FCS) { + // masks = joy_get_present_mask(); + + if ( nsticks == 2 ) { + if ( kconfig_is_axes_used(2) || kconfig_is_axes_used(3) ) { + if(Joy_is_Sidewinder) + { + sprintf( title, "%s\nTWIST-LEFT", TXT_JOYSTICK); + sprintf( text, "Twist Joystick to \nthe left side"); + } + else + { + sprintf( title, "%s #2\n%s", TXT_JOYSTICK, TXT_UPPER_LEFT); + sprintf( text, "%s #2 %s", TXT_MOVE_JOYSTICK, TXT_TO_UL); + } + if (joycal_message( title, text )) { + joy_set_cal_vals(org_axis_min, org_axis_center, org_axis_max); + return; + } + joystick_read_raw_axis( JOY_ALL_AXIS, temp_values ); + axis_min[2] = temp_values[2]; + axis_min[3] = temp_values[3]; + joy_delay(); + + if(Joy_is_Sidewinder) + { + sprintf( title, "%s\nTWIST-RIGHT", TXT_JOYSTICK); + sprintf( text, "Twist Joystick to \nthe right side"); + } + else + { + sprintf( title, "%s #2\n%s", TXT_JOYSTICK, TXT_LOWER_RIGHT); + sprintf( text, "%s #2 %s", TXT_MOVE_JOYSTICK, TXT_TO_LR); + } + if (joycal_message( title, text )) { + joy_set_cal_vals(org_axis_min, org_axis_center, org_axis_max); + return; + } + joystick_read_raw_axis( JOY_ALL_AXIS, temp_values ); + axis_max[2] = temp_values[2]; + axis_max[3] = temp_values[3]; + joy_delay(); + + + if(Joy_is_Sidewinder) + { + sprintf( title, "%s\nCENTER", TXT_JOYSTICK); + sprintf( text, "%s %s",TXT_MOVE_JOYSTICK, TXT_TO_C); + } + else + { + sprintf( title, "%s #2\n%s", TXT_JOYSTICK, TXT_CENTER); + sprintf( text, "%s #2 %s", TXT_MOVE_JOYSTICK, TXT_TO_C); + } + + if (joycal_message( title, text )) { + joy_set_cal_vals(org_axis_min, org_axis_center, org_axis_max); + return; + } + joystick_read_raw_axis( JOY_ALL_AXIS, temp_values ); + axis_cen[2] = temp_values[2]; + axis_cen[3] = temp_values[3]; + joy_delay(); + } + } else if ( (!(masks & JOY_2_X_AXIS)) && (masks & JOY_2_Y_AXIS) ) { + if ( kconfig_is_axes_used(3) ) { + // A throttle axis!!!!! + sprintf( title, "%s\n%s", TXT_THROTTLE, TXT_FORWARD); + if (joycal_message( title, TXT_MOVE_THROTTLE_F)) { + joy_set_cal_vals(org_axis_min, org_axis_center, org_axis_max); + return; + } + joystick_read_raw_axis( JOY_ALL_AXIS, temp_values ); + axis_min[3] = temp_values[3]; + joy_delay(); + + sprintf( title, "%s\n%s", TXT_THROTTLE, TXT_REVERSE); + if (joycal_message( title, TXT_MOVE_THROTTLE_R)) { + joy_set_cal_vals(org_axis_min, org_axis_center, org_axis_max); + return; + } + joystick_read_raw_axis( JOY_ALL_AXIS, temp_values ); + axis_max[3] = temp_values[3]; + joy_delay(); + + sprintf( title, "%s\n%s", TXT_THROTTLE, TXT_CENTER); + if (joycal_message( title, TXT_MOVE_THROTTLE_C)) { + joy_set_cal_vals(org_axis_min, org_axis_center, org_axis_max); + return; + } + joystick_read_raw_axis( JOY_ALL_AXIS, temp_values ); + axis_cen[3] = temp_values[3]; + joy_delay(); + } + } + } + joy_set_cal_vals(axis_min, axis_cen, axis_max); + + +//added 9/1/98 by Victor Rachels to make sidewinder calibratable +/* if(Joy_is_Sidewinder) + Config_control_type=tempstick; */ +//end this section addition - Victor Rachels + + + WriteConfigFile(); +} + + +//char *control_text[CONTROL_MAX_TYPES] = { "Keyboard only", "Joystick", "Flightstick Pro", "Thrustmaster FCS", "Gravis Gamepad", "Mouse", "Cyberman" }; + +void joydef_menuset_1(int nitems, newmenu_item * items, int *last_key, int citem ) +{ + int i; + int oc_type = Config_control_type; + + nitems = nitems; + last_key = last_key; + citem = citem; + + for (i=0; i-1); + + switch (Config_control_type) { + case CONTROL_JOYSTICK: + case CONTROL_FLIGHTSTICK_PRO: + case CONTROL_THRUSTMASTER_FCS: + case CONTROL_GRAVIS_GAMEPAD: + if ( joydefs_calibrate_flag ) + joydefs_calibrate(); + break; + } + +} + diff --git a/arch/dos/key.c b/arch/dos/key.c new file mode 100644 index 00000000..bec3d31a --- /dev/null +++ b/arch/dos/key.c @@ -0,0 +1,714 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/arch/dos/key.c,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:15 $ + * + * Functions for keyboard handler. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 21:58:32 donut + * Import of d1x 1.37 source. + * + * Revision 1.35 1995/01/25 20:13:30 john + * Took out not passing keys to debugger if w10. + * + * Revision 1.34 1995/01/14 19:19:31 john + * Made so when you press Shift+Baskspace, it release keys autmatically. + * + * Revision 1.33 1994/12/13 09:21:48 john + * Took out keyd_editor_mode, and KEY_DEBUGGED stuff for NDEBUG versions. + * + * Revision 1.32 1994/11/12 13:52:01 john + * Fixed bug with code that cleared bios buffer. + * + * Revision 1.31 1994/10/24 15:16:16 john + * Added code to detect KEY_PAUSE. + * + * Revision 1.30 1994/10/24 13:57:53 john + * Hacked in support for pause key onto code 0x61. + * + * Revision 1.29 1994/10/21 15:18:13 john + * *** empty log message *** + * + * Revision 1.28 1994/10/21 15:17:24 john + * Made LSHIFT+BACKSPACE do what PrtScr used to. + * + * Revision 1.27 1994/09/22 16:09:18 john + * Fixed some virtual memory lockdown problems with timer and + * joystick. + * + * Revision 1.26 1994/09/15 21:32:47 john + * Added bounds checking for down_count scancode + * parameter. + * + * Revision 1.25 1994/08/31 12:22:20 john + * Added KEY_DEBUGGED + * + * Revision 1.24 1994/08/24 18:53:48 john + * Made Cyberman read like normal mouse; added dpmi module; moved + * mouse from assembly to c. Made mouse buttons return time_down. + * + * Revision 1.23 1994/08/18 15:17:51 john + * *** empty log message *** + * + * Revision 1.22 1994/08/18 15:16:38 john + * fixed some bugs with clear_key_times and then + * removed it because i fixed key_flush to do the + * same. + * + * Revision 1.21 1994/08/17 19:01:25 john + * Attempted to fix a bug with a key being held down + * key_flush called, then the key released having too + * long of a time. + * + * Revision 1.20 1994/08/08 10:43:48 john + * Recorded when a key was pressed for key_inkey_time. + * + * Revision 1.19 1994/06/22 15:00:03 john + * Made keyboard close automatically on exit. + * + * Revision 1.18 1994/06/21 09:16:29 john + * *** empty log message *** + * + * Revision 1.17 1994/06/21 09:08:23 john + * *** empty log message *** + * + * Revision 1.16 1994/06/21 09:05:01 john + * *** empty log message *** + * + * Revision 1.15 1994/06/21 09:04:24 john + * Made PrtScreen do an int5 + * + * Revision 1.14 1994/06/17 17:17:06 john + * Added keyd_time_last_key_was_pressed or something like that. + * + * Revision 1.13 1994/05/14 13:55:16 matt + * Added #define to control key passing to bios + * + * Revision 1.12 1994/05/05 18:09:39 john + * Took out BIOS to prevent stuck keys. + * + * Revision 1.11 1994/05/03 17:39:12 john + * *** empty log message *** + * + * Revision 1.10 1994/04/29 12:14:20 john + * Locked all memory used during interrupts so that program + * won't hang when using virtual memory. + * + * Revision 1.9 1994/04/28 23:49:41 john + * Made key_flush flush more keys and also did something else but i forget what. + * + * Revision 1.8 1994/04/22 12:52:12 john + * *** empty log message *** + * + * Revision 1.7 1994/04/01 10:44:59 mike + * Change key_getch() to call getch() if our interrupt hasn't been installed. + * + * Revision 1.6 1994/03/09 10:45:48 john + * Neatend code a bit. + * + * Revision 1.5 1994/02/17 17:24:16 john + * Neatened up a bit. + * + * Revision 1.4 1994/02/17 16:30:29 john + * Put in code to pass keys when in debugger. + * + * Revision 1.3 1994/02/17 15:57:59 john + * Made handler not chain to BIOS handler. + * + * Revision 1.2 1994/02/17 15:56:06 john + * Initial version. + * + * Revision 1.1 1994/02/17 15:54:07 john + * Initial revision + * + * + */ + +//#define PASS_KEYS_TO_BIOS 1 //if set, bios gets keys + +#ifdef RCS +static char rcsid[] = "$Id: key.c,v 1.1.1.1 2001-01-19 03:30:15 bradleyb Exp $"; +#endif + +#include +#include +#include +#include +#include + +//#define WATCOM_10 +#ifdef __DJGPP__ +#include +#define _far +#define __far +#define __interrupt +#define near +_go32_dpmi_seginfo kbd_hand_info; +#endif +#include "error.h" +#include "key.h" +#include "timer.h" +#include "u_dpmi.h" + +#define KEY_BUFFER_SIZE 16 + + +//-------- Variable accessed by outside functions --------- +unsigned char keyd_buffer_type; // 0=No buffer, 1=buffer ASCII, 2=buffer scans +unsigned char keyd_repeat; +unsigned char keyd_editor_mode; +volatile unsigned char keyd_last_pressed; +volatile unsigned char keyd_last_released; +volatile unsigned char keyd_pressed[256]; +volatile int keyd_time_when_last_pressed; + +typedef struct keyboard { + unsigned short keybuffer[KEY_BUFFER_SIZE]; + fix time_pressed[KEY_BUFFER_SIZE]; + fix TimeKeyWentDown[256]; + fix TimeKeyHeldDown[256]; + unsigned int NumDowns[256]; + unsigned int NumUps[256]; + unsigned int keyhead, keytail; + unsigned char E0Flag; + unsigned char E1Flag; + int in_key_handler; +#ifdef __DJGPP__ + _go32_dpmi_seginfo prev_int_9; +#else + void (__interrupt __far *prev_int_9)(); +#endif +} keyboard; + +static volatile keyboard key_data; + +static unsigned char Installed=0; + +unsigned char ascii_table[128] = +{ 255, 255, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=',255,255, + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 255, 255, + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', 39, '`', + 255, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 255,'*', + 255, ' ', 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255,255, + 255, 255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255 }; + +unsigned char shifted_ascii_table[128] = +{ 255, 255, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+',255,255, + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 255, 255, + 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', + 255, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 255,255, + 255, ' ', 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255,255, + 255, 255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255 }; + +char * key_text[256] = { +"","ESC","1","2","3","4","5","6","7","8","9","0","-", +"=","BSPC","TAB","Q","W","E","R","T","Y","U","I","O", +"P","[","]","ƒ","LCTRL","A","S","D","F", +"G","H","J","K","L",";","'","`", +"LSHFT","\\","Z","X","C","V","B","N","M",",", +".","/","RSHFT","PAD*","LALT","SPC", +"CPSLK","F1","F2","F3","F4","F5","F6","F7","F8","F9", +"F10","NMLCK","SCLK","PAD7","PAD8","PAD9","PAD-", +"PAD4","PAD5","PAD6","PAD+","PAD1","PAD2","PAD3","PAD0", +"PAD.","","","","F11","F12","","","","","","","","","", +"","","","","","","","","","","","","","","","","","","","", +"","","","","","","","","","","","","","","","","","","","", +"","","","","","","","","","","","","","","","","","", +"PADƒ","RCTRL","","","","","","","","","","","","","", +"","","","","","","","","","","PAD/","","","RALT","", +"","","","","","","","","","","","","","HOME","‚","PGUP", +"","","","","","END","€","PGDN","INS", +"DEL","","","","","","","","","","","","","","","","","", +"","","","","","","","","","","","","","","","","","","","", +"","","","","","","" }; + +unsigned char key_to_ascii(int keycode ) +{ + int shifted; + + shifted = keycode & KEY_SHIFTED; + keycode &= 0xFF; + + if ( keycode>=127 ) + return 255; + + if (shifted) + return shifted_ascii_table[keycode]; + else + return ascii_table[keycode]; +} + +void key_clear_bios_buffer_all() +{ +#ifdef __WATCOMC__ + // Clear keyboard buffer... + *(ushort *)0x41a=*(ushort *)0x41c; + // Clear the status bits... + *(ubyte *)0x417 = 0; + *(ubyte *)0x418 = 0; +#else + _farpokew(_dos_ds,0x41a, _farpeekw(_dos_ds, 0x41c)); + _farpokeb(_dos_ds,0x417, 0); + _farpokeb(_dos_ds,0x418, 0); +#endif +} + +void key_clear_bios_buffer() +{ +#ifdef __WATCOMC__ + // Clear keyboard buffer... + *(ushort *)0x41a=*(ushort *)0x41c; +#else + _farpokew(_dos_ds,0x41a, _farpeekw(_dos_ds, 0x41c)); +#endif +} + +void key_flush() +{ + int i; + fix CurTime; + + _disable(); + + // Clear the BIOS buffer + key_clear_bios_buffer(); + + key_data.keyhead = key_data.keytail = 0; + + //Clear the keyboard buffer + for (i=0; i= KEY_BUFFER_SIZE ) n=0; + return n; +} + +// Returns 1 if character waiting... 0 otherwise +int key_checkch() +{ + int is_one_waiting = 0; + + _disable(); + + key_clear_bios_buffer(); + + if (key_data.keytail!=key_data.keyhead) + is_one_waiting = 1; + _enable(); + return is_one_waiting; +} + +int key_inkey() +{ + int key = 0; + + _disable(); + + key_clear_bios_buffer(); + + if (key_data.keytail!=key_data.keyhead) { + key = key_data.keybuffer[key_data.keyhead]; + key_data.keyhead = add_one(key_data.keyhead); + } + _enable(); + return key; +} + +int key_inkey_time(fix * time) +{ + int key = 0; + + _disable(); + + key_clear_bios_buffer(); + + if (key_data.keytail!=key_data.keyhead) { + key = key_data.keybuffer[key_data.keyhead]; + *time = key_data.time_pressed[key_data.keyhead]; + key_data.keyhead = add_one(key_data.keyhead); + } + _enable(); + return key; +} + + + +int key_peekkey() +{ + int key = 0; + + _disable(); + + key_clear_bios_buffer(); + + if (key_data.keytail!=key_data.keyhead) { + key = key_data.keybuffer[key_data.keyhead]; + } + _enable(); + return key; +} + +// If not installed, uses BIOS and returns getch(); +// Else returns pending key (or waits for one if none waiting). +int key_getch() +{ + int dummy=0; + + if (!Installed) + return getch(); + + while (!key_checkch()) + dummy++; + return key_inkey(); +} + +unsigned int key_get_shift_status() +{ + unsigned int shift_status = 0; + + _disable(); + + key_clear_bios_buffer(); + + if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT] ) + shift_status |= KEY_SHIFTED; + + if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT] ) + shift_status |= KEY_ALTED; + + if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL] ) + shift_status |= KEY_CTRLED; + +#ifndef NDEBUG + if (keyd_pressed[KEY_DELETE]) + shift_status |=KEY_DEBUGGED; +#endif + + _enable(); + + return shift_status; +} + +// Returns the number of seconds this key has been down since last call. +fix key_down_time(int scancode) { + fix time_down, time; + + if ((scancode<0)|| (scancode>255)) return 0; + +#ifndef NDEBUG + if (keyd_editor_mode && key_get_shift_status() ) + return 0; +#endif + + _disable(); + + if ( !keyd_pressed[scancode] ) { + time_down = key_data.TimeKeyHeldDown[scancode]; + key_data.TimeKeyHeldDown[scancode] = 0; + } else { + time = timer_get_fixed_secondsX(); + time_down = time - key_data.TimeKeyWentDown[scancode]; + key_data.TimeKeyWentDown[scancode] = time; + } + _enable(); + + return time_down; +} + +// Returns number of times key has went from up to down since last call. +unsigned int key_down_count(int scancode) { + int n; + + if ((scancode<0)|| (scancode>255)) return 0; + + _disable(); + n = key_data.NumDowns[scancode]; + key_data.NumDowns[scancode] = 0; + _enable(); + + return n; +} + + +// Returns number of times key has went from down to up since last call. +unsigned int key_up_count(int scancode) { + int n; + + if ((scancode<0)|| (scancode>255)) return 0; + + _disable(); + n = key_data.NumUps[scancode]; + key_data.NumUps[scancode] = 0; + _enable(); + + return n; +} + +// Use intrinsic forms so that we stay in the locked interrup code. + +#ifdef __WATCOMC__ +void Int5(); +#pragma aux Int5 = "int 5"; +#else +#ifdef __GNUC__ +#define Int5() asm volatile("int $5") +#endif +#endif + +#pragma off (check_stack) +void __interrupt __far key_handler() +{ + unsigned char scancode, breakbit, temp; + unsigned short keycode; + +#ifndef WATCOM_10 +#ifndef NDEBUG +#ifdef __WATCOMC__ /* must have _chain_intr */ + ubyte * MONO = (ubyte *)(0x0b0000+24*80*2); + if ( ((MONO[0]=='D') && (MONO[2]=='B') && (MONO[4]=='G') && (MONO[6]=='>')) || + ((MONO[14]=='<') && (MONO[16]=='i') && (MONO[18]=='>') && (MONO[20]==' ') && (MONO[22]=='-')) || + ((MONO[0]==200 ) && (MONO[2]==27) && (MONO[4]==17) ) + ) + _chain_intr( key_data.prev_int_9 ); +#endif +#endif +#endif + + // Read in scancode + scancode = inp( 0x60 ); + + switch( scancode ) { + case 0xE0: + key_data.E0Flag = 0x80; + break; + default: + // Parse scancode and break bit + if (key_data.E1Flag > 0 ) { // Special code for Pause, which is E1 1D 45 E1 9D C5 + key_data.E1Flag--; + if ( scancode == 0x1D ) { + scancode = KEY_PAUSE; + breakbit = 0; + } else if ( scancode == 0x9d ) { + scancode = KEY_PAUSE; + breakbit = 1; + } else { + break; // skip this keycode + } + } else if ( scancode==0xE1 ) { + key_data.E1Flag = 2; + break; + } else { + breakbit = scancode & 0x80; // Get make/break bit + scancode &= 0x7f; // Strip make/break bit off of scancode + scancode |= key_data.E0Flag; // Add in extended key code + } + key_data.E0Flag = 0; // Clear extended key code + + if (breakbit) { + // Key going up + keyd_last_released = scancode; + keyd_pressed[scancode] = 0; + key_data.NumUps[scancode]++; + temp = 0; + temp |= keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT]; + temp |= keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT]; + temp |= keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL]; +#ifndef NDEBUG + temp |= keyd_pressed[KEY_DELETE]; + if ( !(keyd_editor_mode && temp) ) +#endif // NOTICE LINK TO ABOVE IF!!!! + key_data.TimeKeyHeldDown[scancode] += timer_get_fixed_secondsX() - key_data.TimeKeyWentDown[scancode]; + } else { + // Key going down + keyd_last_pressed = scancode; + keyd_time_when_last_pressed = timer_get_fixed_secondsX(); + if (!keyd_pressed[scancode]) { + // First time down + key_data.TimeKeyWentDown[scancode] = timer_get_fixed_secondsX(); + keyd_pressed[scancode] = 1; + key_data.NumDowns[scancode]++; +#ifndef NDEBUG + if ( (keyd_pressed[KEY_LSHIFT]) && (scancode == KEY_BACKSP) ) { + keyd_pressed[KEY_LSHIFT] = 0; + Int5(); + } +#endif + } else if (!keyd_repeat) { + // Don't buffer repeating key if repeat mode is off + scancode = 0xAA; + } + + if ( scancode!=0xAA ) { + keycode = scancode; + + if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT] ) + keycode |= KEY_SHIFTED; + + if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT] ) + keycode |= KEY_ALTED; + + if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL] ) + keycode |= KEY_CTRLED; + +#ifndef NDEBUG + if ( keyd_pressed[KEY_DELETE] ) + keycode |= KEY_DEBUGGED; +#endif + + temp = key_data.keytail+1; + if ( temp >= KEY_BUFFER_SIZE ) temp=0; + + if (temp!=key_data.keyhead) { + key_data.keybuffer[key_data.keytail] = keycode; + key_data.time_pressed[key_data.keytail] = keyd_time_when_last_pressed; + key_data.keytail = temp; + } + } + } + } + +#ifndef NDEBUG +#ifdef PASS_KEYS_TO_BIOS + _chain_intr( key_data.prev_int_9 ); +#endif +#endif + + temp = inp(0x61); // Get current port 61h state + temp |= 0x80; // Turn on bit 7 to signal clear keybrd + outp( 0x61, temp ); // Send to port + temp &= 0x7f; // Turn off bit 7 to signal break + outp( 0x61, temp ); // Send to port + outp( 0x20, 0x20 ); // Reset interrupt controller +} + +#pragma on (check_stack) + +void key_handler_end() { // Dummy function to help calculate size of keyboard handler function +} + +void key_init() +{ + // Initialize queue + + keyd_time_when_last_pressed = timer_get_fixed_seconds(); + keyd_buffer_type = 1; + keyd_repeat = 1; + key_data.in_key_handler = 0; + key_data.E0Flag = 0; + key_data.E1Flag = 0; + + // Clear the keyboard array + key_flush(); + + if (Installed) return; + Installed = 1; + + //--------------- lock everything for the virtal memory ---------------------------------- + if (!dpmi_lock_region ((void near *)key_handler, (char *)key_handler_end - (char near *)key_handler)) { + printf( "Error locking keyboard handler!\n" ); + exit(1); + } + if (!dpmi_lock_region ((void *)&key_data, sizeof(keyboard))) { + printf( "Error locking keyboard handler's data1!\n" ); + exit(1); + } + if (!dpmi_lock_region (&keyd_buffer_type, sizeof(char))) { + printf( "Error locking keyboard handler's data2!\n" ); + exit(1); + } + if (!dpmi_lock_region (&keyd_repeat, sizeof(char))) { + printf( "Error locking keyboard handler's data3!\n" ); + exit(1); + } + if (!dpmi_lock_region (&keyd_editor_mode, sizeof(char))) { + printf( "Error locking keyboard handler's data4!\n" ); + exit(1); + } + if (!dpmi_lock_region ((void *)&keyd_last_pressed, sizeof(char))) { + printf( "Error locking keyboard handler's data5!\n" ); + exit(1); + } + if (!dpmi_lock_region ((void *)&keyd_last_released, sizeof(char))) { + printf( "Error locking keyboard handler's data6!\n" ); + exit(1); + } + if (!dpmi_lock_region ((void *)&keyd_pressed, sizeof(char)*256)) { + printf( "Error locking keyboard handler's data7!\n" ); + exit(1); + } + if (!dpmi_lock_region ((void *)&keyd_time_when_last_pressed, sizeof(int))) { + printf( "Error locking keyboard handler's data8!\n" ); + exit(1); + } + +#ifndef __DJGPP__ + key_data.prev_int_9 = (void *)_dos_getvect( 9 ); + _dos_setvect( 9, key_handler ); +#else + _go32_dpmi_get_protected_mode_interrupt_vector(9, + (_go32_dpmi_seginfo *)&key_data.prev_int_9); + kbd_hand_info.pm_offset = (int)key_handler; + kbd_hand_info.pm_selector = _my_cs(); + _go32_dpmi_allocate_iret_wrapper(&kbd_hand_info); + _go32_dpmi_set_protected_mode_interrupt_vector(9, &kbd_hand_info); +#endif + + atexit( key_close ); +} + +void key_close() +{ + if (!Installed) return; + Installed = 0; + +#ifndef __DJGPP__ + _dos_setvect( 9, key_data.prev_int_9 ); +#else + _go32_dpmi_set_protected_mode_interrupt_vector(9, + (_go32_dpmi_seginfo *)&key_data.prev_int_9); +#endif + + _disable(); + key_clear_bios_buffer_all(); + _enable(); + +} diff --git a/arch/dos/midiallg.c b/arch/dos/midiallg.c new file mode 100644 index 00000000..1f16e23d --- /dev/null +++ b/arch/dos/midiallg.c @@ -0,0 +1,148 @@ +#include +#include +#include "u_mem.h" +#include "mono.h" +#include "allg_snd.h" +#include "digi.h" +#include "timer.h" + +int midi_volume = 128/2; // Max volume +char digi_last_midi_song[16] = ""; +char digi_last_melodic_bank[16] = ""; +char digi_last_drum_bank[16] = ""; +int digi_midi_type = 0; // Midi driver type +int digi_midi_port = 0; // Midi driver port + +// handle for the initialized MIDI song +MIDI *SongHandle = NULL; + +void digi_set_midi_volume( int mvolume ) +{ + int old_volume = midi_volume; + + if ( mvolume > 127 ) + midi_volume = 127; + else if ( mvolume < 0 ) + midi_volume = 0; + else + midi_volume = mvolume; + + if ( (digi_midi_type > 0) ) { + if ( (old_volume < 1) && ( midi_volume > 1 ) ) { + if (SongHandle == NULL ) + digi_play_midi_song( digi_last_midi_song, digi_last_melodic_bank, digi_last_drum_bank, 1 ); + } + set_volume(-1, midi_volume * 2 + (midi_volume & 1)); + } +} + +void digi_stop_current_song() +{ + if (SongHandle) { + destroy_midi(SongHandle); + SongHandle = NULL; + } +} + +void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) +{ + //char fname[128]; + + if ( digi_midi_type <= 0 ) return; + + digi_stop_current_song(); + + if ( filename == NULL ) return; + + strcpy( digi_last_midi_song, filename ); + strcpy( digi_last_melodic_bank, melodic_bank ); + strcpy( digi_last_drum_bank, drum_bank ); + + if ( midi_volume < 1 ) + return; + + SongHandle = NULL; + +#if 0 /* needs bank loading to sound right */ + if (midi_card <= 4) { /* FM cards */ + int sl; + sl = strlen( filename ); + strcpy( fname, filename ); + fname[sl-1] = 'q'; + SongHandle = load_hmp(fname); + } +#endif + + if ( !SongHandle ) + SongHandle = load_hmp(filename); + + if (SongHandle) { + if (play_midi(SongHandle, loop)) { + destroy_midi(SongHandle); + SongHandle = NULL; + } + } + if (!SongHandle) { + mprintf( (1, "\nAllegro Error : %s", allegro_error )); + } +} + +void digi_midi_pause() { + if (digi_midi_type > 0 && SongHandle) + midi_pause(); +} + +void digi_midi_resume() { + if (digi_midi_type > 0 && SongHandle) + midi_resume(); +} + +void digi_midi_stop() { + if ( digi_midi_type > 0 ) { + if (SongHandle) { + destroy_midi(SongHandle); + SongHandle = NULL; + } + } + +} + +#ifndef ALLEGRO +extern int sb_hw_dsp_ver; + +static int midi_timer_system_initialized = 0; +static int digi_midi_initialized = 0; + +int digi_midi_init() { + if (!midi_timer_system_initialized) + { + allg_snd_init(); + midi_timer_system_initialized = 1; + } + sb_hw_dsp_ver = 1; /* set SB as already detected, functionless */ + if (!digi_midi_initialized) { + // amount of voices we need + // 16 for normal sounds and 16 for SoundObjects (fan, boss) + // for DIGMID we sacrify some sounds (32 is the max). +// reserve_voices(allegro_using_digmid() ? 16 : 32, -1); + if (install_sound(DIGI_NONE, MIDI_AUTODETECT, NULL)) + return 1; + //set_volume(255, -1); + digi_midi_type = midi_card; // only for 0, !=0 + } + digi_midi_initialized = 1; + digi_set_midi_volume( midi_volume ); + return 0; +} + +void digi_midi_close() { + remove_sound(); + digi_midi_initialized = 0; + + if ( midi_timer_system_initialized ) { + // Remove timer... + timer_set_function( NULL ); + midi_timer_system_initialized = 0; + } +} +#endif diff --git a/arch/dos/mm_snd/drv_sb.c b/arch/dos/mm_snd/drv_sb.c new file mode 100644 index 00000000..65373b0f --- /dev/null +++ b/arch/dos/mm_snd/drv_sb.c @@ -0,0 +1,518 @@ +/* + +Name: +DRV_SB.C + +Description: +Mikmod driver for output on Creative Labs Soundblasters & compatibles +(through DSP) + +Portability: + +MSDOS: BC(y) Watcom(y) DJGPP(y) +Win95: n +Os2: n +Linux: n + +(y) - yes +(n) - no (not possible or not useful) +(?) - may be possible, but not tested + +*/ +#include +#include +#include +//#include +//#include +#include +//#ifndef __DJGPP__ +//#include +//#endif + +#include "mikmod.h" +#include "mdma.h" +#include "mirq.h" + +/*************************************************************************** +>>>>>>>>>>>>>>>>>>>>>>>>> Lowlevel SB stuff <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +***************************************************************************/ + +static UWORD sb_port; /* sb base port */ + +/* + Define some important SB i/o ports: +*/ + +#define MIXER_ADDRESS (sb_port+0x4) +#define MIXER_DATA (sb_port+0x5) +#define DSP_RESET (sb_port+0x6) +#define DSP_READ_DATA (sb_port+0xa) +#define DSP_WRITE_DATA (sb_port+0xc) +#define DSP_WRITE_STATUS (sb_port+0xc) +#define DSP_DATA_AVAIL (sb_port+0xe) + + +static void SB_MixerStereo(void) +/* + Enables stereo output for DSP versions 3.00 >= ver < 4.00 +*/ +{ + outportb(MIXER_ADDRESS,0xe); + outportb(MIXER_DATA,inportb(MIXER_DATA)|2); +} + + + +static void SB_MixerMono(void) +/* + Disables stereo output for DSP versions 3.00 >= ver < 4.00 +*/ +{ + outportb(MIXER_ADDRESS,0xe); + outportb(MIXER_DATA,inportb(MIXER_DATA)&0xfd); +} + + + +static BOOL SB_WaitDSPWrite(void) +/* + Waits until the DSP is ready to be written to. + + returns FALSE on timeout +*/ +{ + UWORD timeout=32767; + + while(timeout--){ + if(!(inportb(DSP_WRITE_STATUS)&0x80)) return 1; + } + return 0; +} + + + +static BOOL SB_WaitDSPRead(void) +/* + Waits until the DSP is ready to read from. + + returns FALSE on timeout +*/ +{ + UWORD timeout=32767; + + while(timeout--){ + if(inportb(DSP_DATA_AVAIL)&0x80) return 1; + } + return 0; +} + + + +static BOOL SB_WriteDSP(UBYTE data) +/* + Writes byte 'data' to the DSP. + + returns FALSE on timeout. +*/ +{ + if(!SB_WaitDSPWrite()) return 0; + outportb(DSP_WRITE_DATA,data); + return 1; +} + + + +static UWORD SB_ReadDSP(void) +/* + Reads a byte from the DSP. + + returns 0xffff on timeout. +*/ +{ + if(!SB_WaitDSPRead()) return 0xffff; + return(inportb(DSP_READ_DATA)); +} + + + +static void SB_SpeakerOn(void) +/* + Enables DAC speaker output. +*/ +{ + SB_WriteDSP(0xd1); +} + + + +static void SB_SpeakerOff(void) +/* + Disables DAC speaker output +*/ +{ + SB_WriteDSP(0xd3); +} + + + +static void SB_ResetDSP(void) +/* + Resets the DSP. +*/ +{ + int t; + /* reset the DSP by sending 1, (delay), then 0 */ + outportb(DSP_RESET,1); + for(t=0;t<8;t++) inportb(DSP_RESET); + outportb(DSP_RESET,0); +} + + + +static BOOL SB_Ping(void) +/* + Checks if a SB is present at the current baseport by + resetting the DSP and checking if it returned the value 0xaa. + + returns: TRUE => SB is present + FALSE => No SB detected +*/ +{ + SB_ResetDSP(); + return(SB_ReadDSP()==0xaa); +} + + + +static UWORD SB_GetDSPVersion(void) +/* + Gets SB-dsp version. returns 0xffff if dsp didn't respond. +*/ +{ + UWORD hi,lo; + + if(!SB_WriteDSP(0xe1)) return 0xffff; + + hi=SB_ReadDSP(); + lo=SB_ReadDSP(); + + return((hi<<8)|lo); +} + + + +/*************************************************************************** +>>>>>>>>>>>>>>>>>>>>>>>>> The actual SB driver <<<<<<<<<<<<<<<<<<<<<<<<<<<<< +***************************************************************************/ + +static DMAMEM *SB_DMAMEM; +static char *SB_DMABUF; + +static UBYTE SB_TIMECONSTANT; + +static UWORD sb_int; /* interrupt vector that belongs to sb_irq */ +static UWORD sb_ver; /* DSP version number */ +static UBYTE sb_irq; /* sb irq */ +static UBYTE sb_lodma; /* 8 bit dma channel (1.0/2.0/pro) */ +static UBYTE sb_hidma; /* 16 bit dma channel (16/16asp) */ +static UBYTE sb_dma; /* current dma channel */ + + +static BOOL SB_IsThere(void) +{ + char *envptr,c; + static char *endptr; + + sb_port =0xffff; + sb_irq =0xff; + sb_lodma=0xff; + sb_hidma=0xff; + + if((envptr=getenv("BLASTER"))==NULL) return 0; + + while(1){ + + /* skip whitespace */ + + do c=*(envptr++); while(c==' ' || c=='\t'); + + /* reached end of string? -> exit */ + + if(c==0) break; + + switch(c){ + + case 'a': + case 'A': + sb_port=strtol(envptr,&endptr,16); + break; + + case 'i': + case 'I': + sb_irq=strtol(envptr,&endptr,10); + //added on 11/5/98 by Victor Rachels to hardwire 2->9 + if(sb_irq==0x02) + sb_irq=0x09; + //end this section addition - VR + break; + + case 'd': + case 'D': + sb_lodma=strtol(envptr,&endptr,10); + break; + + case 'h': + case 'H': + sb_hidma=strtol(envptr,&endptr,10); + break; + + default: + strtol(envptr,&endptr,16); + break; + } + envptr=endptr; + } + + if(sb_port==0xffff || sb_irq==0xff || sb_lodma==0xff) return 0; + + /* determine interrupt vector */ + + sb_int = (sb_irq>7) ? sb_irq+104 : sb_irq+8; + + if(!SB_Ping()) return 0; + + /* get dsp version. */ + + if((sb_ver=SB_GetDSPVersion())==0xffff) return 0; + + return 1; +} + + +static void interrupt newhandler(MIRQARGS) +{ + if(sb_ver<0x200){ + SB_WriteDSP(0x14); + SB_WriteDSP(0xff); + SB_WriteDSP(0xfe); + } + + if(md_mode & DMODE_16BITS) + inportb(sb_port+0xf); + else + inportb(DSP_DATA_AVAIL); + + MIrq_EOI(sb_irq); +} + + +static PVI oldhandler; + + +static BOOL SB_Init(void) +{ + ULONG t; + + if(!SB_IsThere()){ + myerr="No such hardware detected, check your 'BLASTER' env. variable"; + return 0; + } + +/* printf("SB version %x\n",sb_ver); */ +/* if(sb_ver>0x200) sb_ver=0x200; */ + + if(sb_ver>=0x400 && sb_hidma==0xff){ + myerr="High-dma setting in 'BLASTER' variable is required for SB-16"; + return 0; + } + + if(sb_ver<0x400 && md_mode&DMODE_16BITS){ + /* DSP versions below 4.00 can't do 16 bit sound. */ + md_mode&=~DMODE_16BITS; + } + + if(sb_ver<0x300 && md_mode&DMODE_STEREO){ + /* DSP versions below 3.00 can't do stereo sound. */ + md_mode&=~DMODE_STEREO; + } + + /* Use low dma channel for 8 bit, high dma for 16 bit */ + + sb_dma=(md_mode & DMODE_16BITS) ? sb_hidma : sb_lodma; + + if(sb_ver<0x400){ + + t=md_mixfreq; + if(md_mode & DMODE_STEREO) t<<=1; + + SB_TIMECONSTANT=256-(1000000L/t); + + if(sb_ver<0x201){ + if(SB_TIMECONSTANT>210) SB_TIMECONSTANT=210; + } + else{ + if(SB_TIMECONSTANT>233) SB_TIMECONSTANT=233; + } + + md_mixfreq=1000000L/(256-SB_TIMECONSTANT); + if(md_mode & DMODE_STEREO) md_mixfreq>>=1; + } + + if(!VC_Init()) return 0; + + SB_DMAMEM=MDma_AllocMem(md_dmabufsize); + + if(SB_DMAMEM==NULL){ + VC_Exit(); + myerr="Couldn't allocate page-contiguous dma-buffer"; + return 0; + } + + SB_DMABUF=(char *)MDma_GetPtr(SB_DMAMEM); + + oldhandler=MIrq_SetHandler(sb_irq,newhandler); + return 1; +} + + + +static void SB_Exit(void) +{ + MIrq_SetHandler(sb_irq,oldhandler); + MDma_FreeMem(SB_DMAMEM); + VC_Exit(); +} + + +static UWORD last=0; +static UWORD curr=0; + + +static void SB_Update(void) +{ + UWORD todo,index; + + curr=(md_dmabufsize-MDma_Todo(sb_dma))&0xfffc; + + if(curr==last) return; + + if(curr>last){ + todo=curr-last; index=last; + last+=VC_WriteBytes(&SB_DMABUF[index],todo); + MDma_Commit(SB_DMAMEM,index,todo); + if(last>=md_dmabufsize) last=0; + } + else{ + todo=md_dmabufsize-last; + VC_WriteBytes(&SB_DMABUF[last],todo); + MDma_Commit(SB_DMAMEM,last,todo); + last=VC_WriteBytes(SB_DMABUF,curr); + MDma_Commit(SB_DMAMEM,0,curr); + } +} + + + + +static void SB_PlayStart(void) +{ + VC_PlayStart(); + + MIrq_OnOff(sb_irq,1); + + if(sb_ver>=0x300 && sb_ver<0x400){ + if(md_mode & DMODE_STEREO){ + SB_MixerStereo(); + } + else{ + SB_MixerMono(); + } + } + + /* clear the dma buffer to zero (16 bits + signed ) or 0x80 (8 bits unsigned) */ + + if(md_mode & DMODE_16BITS) + memset(SB_DMABUF,0,md_dmabufsize); + else + memset(SB_DMABUF,0x80,md_dmabufsize); + + MDma_Commit(SB_DMAMEM,0,md_dmabufsize); + + if(!MDma_Start(sb_dma,SB_DMAMEM,md_dmabufsize,INDEF_WRITE)){ + return; + } + + if(sb_ver<0x400){ + SB_SpeakerOn(); + + SB_WriteDSP(0x40); + SB_WriteDSP(SB_TIMECONSTANT); + + if(sb_ver<0x200){ + SB_WriteDSP(0x14); + SB_WriteDSP(0xff); + SB_WriteDSP(0xfe); + } + else if(sb_ver==0x200){ + SB_WriteDSP(0x48); + SB_WriteDSP(0xff); + SB_WriteDSP(0xfe); + SB_WriteDSP(0x1c); + } + else{ + SB_WriteDSP(0x48); + SB_WriteDSP(0xff); + SB_WriteDSP(0xfe); + SB_WriteDSP(0x90); + } + } + else{ + SB_WriteDSP(0x41); + + SB_WriteDSP(md_mixfreq>>8); + SB_WriteDSP(md_mixfreq&0xff); + + if(md_mode & DMODE_16BITS){ + SB_WriteDSP(0xb6); + SB_WriteDSP((md_mode & DMODE_STEREO) ? 0x30 : 0x10); + } + else{ + SB_WriteDSP(0xc6); + SB_WriteDSP((md_mode & DMODE_STEREO) ? 0x20 : 0x00); + } + + SB_WriteDSP(0xff); + SB_WriteDSP(0xef); + } +} + + +static void SB_PlayStop(void) +{ + VC_PlayStop(); + SB_SpeakerOff(); + SB_ResetDSP(); + SB_ResetDSP(); + MDma_Stop(sb_dma); + MIrq_OnOff(sb_irq,0); +} + + +MDRIVER drv_sb={ + NULL, + "Soundblaster & compatibles", + "MikMod Soundblaster Driver v2.1 for 1.0 / 2.0 / Pro / 16", + SB_IsThere, + VC_SampleLoad, + VC_SampleUnload, + SB_Init, + SB_Exit, + SB_PlayStart, + SB_PlayStop, + SB_Update, + VC_VoiceSetVolume, + VC_VoiceSetFrequency, + VC_VoiceSetPanning, + VC_VoicePlay +}; diff --git a/arch/dos/mm_snd/include/mdma.h b/arch/dos/mm_snd/include/mdma.h new file mode 100644 index 00000000..893d359f --- /dev/null +++ b/arch/dos/mm_snd/include/mdma.h @@ -0,0 +1,42 @@ +#ifndef MDMA_H +#define MDMA_H + +#include "mtypes.h" + +#define READ_DMA 0 +#define WRITE_DMA 1 +#define INDEF_READ 2 +#define INDEF_WRITE 3 + +#ifdef __WATCOMC__ + +typedef struct{ + void *continuous; /* the pointer to a page-continous dma buffer */ + UWORD raw_selector; /* the raw allocated dma selector */ +} DMAMEM; + +#elif defined(__DJGPP__) + +typedef struct{ + void *continuous; /* the pointer to a page-continous dma buffer */ + _go32_dpmi_seginfo raw; /* points to the memory that was allocated */ +} DMAMEM; + +#else + +typedef struct{ + void *continuous; /* the pointer to a page-continous dma buffer */ + void *raw; /* points to the memory that was allocated */ +} DMAMEM; + +#endif + +DMAMEM *MDma_AllocMem(UWORD size); +void MDma_FreeMem(DMAMEM *dm); +int MDma_Start(int channel,DMAMEM *dm,UWORD size,int type); +void MDma_Stop(int channel); +void *MDma_GetPtr(DMAMEM *dm); +void MDma_Commit(DMAMEM *dm,UWORD index,UWORD count); +UWORD MDma_Todo(int channel); + +#endif diff --git a/arch/dos/mm_snd/include/mikmod.h b/arch/dos/mm_snd/include/mikmod.h new file mode 100644 index 00000000..a54087e7 --- /dev/null +++ b/arch/dos/mm_snd/include/mikmod.h @@ -0,0 +1 @@ +#include "mm_drv.h" diff --git a/arch/dos/mm_snd/include/mirq.h b/arch/dos/mm_snd/include/mirq.h new file mode 100644 index 00000000..7fcf97f2 --- /dev/null +++ b/arch/dos/mm_snd/include/mirq.h @@ -0,0 +1,35 @@ +#ifndef MIRQ_H +#define MIRQ_H + +#include "mtypes.h" + + +#ifdef __WATCOMC__ + #define MIRQARGS void + typedef void (interrupt far *PVI)(MIRQARGS); +#endif + +#ifdef __DJGPP__ + #define MIRQARGS void + typedef void (*PVI)(MIRQARGS); +#endif + +#ifdef __BORLANDC__ + + #ifdef __cplusplus + #define MIRQARGS ... + #else + #define MIRQARGS + #endif + + typedef void interrupt (far *PVI)(MIRQARGS); + +#endif + + +BOOL MIrq_IsEnabled(UBYTE irqno); +BOOL MIrq_OnOff(UBYTE irqno,UBYTE onoff); +PVI MIrq_SetHandler(UBYTE irqno,PVI handler); +void MIrq_EOI(UBYTE irqno); + +#endif diff --git a/arch/dos/mm_snd/include/mm_drv.h b/arch/dos/mm_snd/include/mm_drv.h new file mode 100644 index 00000000..9e241903 --- /dev/null +++ b/arch/dos/mm_snd/include/mm_drv.h @@ -0,0 +1,124 @@ +#ifndef _MM_DRV +#define _MM_DRV +#include + +#if 1 +#include "mtypes.h" +#else +typedef unsigned char UBYTE; +typedef signed char SBYTE; +typedef int BOOL; +typedef int SWORD; +typedef unsigned int UWORD; +typedef unsigned int ULONG; +typedef int SLONG; +#endif +typedef char CHAR; +typedef int SAMPLOAD; +typedef int SAMPLE; + +#if 1 +typedef struct MDRIVER{ + struct MDRIVER *next; + char *Name; + char *Version; + BOOL (*IsPresent) (void); + SWORD (*SampleLoad) (FILE *fp,ULONG size,ULONG reppos,ULONG repend,UWORD flags); + void (*SampleUnLoad) (SWORD handle); + BOOL (*Init) (void); + void (*Exit) (void); + void (*PlayStart) (void); + void (*PlayStop) (void); + void (*Update) (void); + void (*VoiceSetVolume) (UBYTE voice,UBYTE vol); + void (*VoiceSetFrequency) (UBYTE voice,ULONG frq); + void (*VoiceSetPanning) (UBYTE voice,UBYTE pan); + void (*VoicePlay) (UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags); +} MDRIVER; +#else +typedef struct MDRIVER +{ struct MDRIVER *next; + CHAR *Name; + CHAR *Version; + UBYTE HardVoiceLimit, /* Limit of hardware mixer voices for this driver */ + SoftVoiceLimit; /* Limit of software mixer voices for this driver */ + + BOOL (*IsPresent) (void); + SWORD (*SampleLoad) (SAMPLOAD *s, int type, FILE *fp); + void (*SampleUnLoad) (SWORD handle); + ULONG (*FreeSampleSpace) (int type); + ULONG (*RealSampleLength) (int type, SAMPLE *s); + BOOL (*Init) (void); + void (*Exit) (void); + BOOL (*Reset) (void); + BOOL (*SetNumVoices) (void); + BOOL (*PlayStart) (void); + void (*PlayStop) (void); + void (*Update) (void); + void (*VoiceSetVolume) (UBYTE voice, UWORD vol); + void (*VoiceSetFrequency) (UBYTE voice, ULONG frq); + void (*VoiceSetPanning) (UBYTE voice, ULONG pan); + void (*VoicePlay) (UBYTE voice, SWORD handle, ULONG start, ULONG size, ULONG reppos, ULONG repend, UWORD flags); + void (*VoiceStop) (UBYTE voice); + BOOL (*VoiceStopped) (UBYTE voice); + void (*VoiceReleaseSustain)(UBYTE voice); + SLONG (*VoiceGetPosition) (UBYTE voice); + ULONG (*VoiceRealVolume) (UBYTE voice); + + BOOL (*StreamInit) (ULONG speed, UWORD flags); + void (*StreamExit) (void); + void (*StreamSetSpeed) (ULONG speed); + SLONG (*StreamGetPosition) (void); + void (*StreamLoadFP) (FILE *fp); + void (*Wait) (void); +} MDRIVER; +#endif + +extern BOOL VC_Init(void); +extern void VC_Exit(void); +extern BOOL VC_SetNumVoices(void); +extern ULONG VC_SampleSpace(int type); +extern ULONG VC_SampleLength(int type, SAMPLE *s); + +extern BOOL VC_PlayStart(void); +extern void VC_PlayStop(void); + +#if 1 +extern SWORD VC_SampleLoad(FILE *fp,ULONG size,ULONG reppos,ULONG repend,UWORD flags); +#else +extern SWORD VC_SampleLoad(SAMPLOAD *sload, int type, FILE *fp); +#endif +extern void VC_SampleUnload(SWORD handle); + +extern void VC_WriteSamples(SBYTE *buf,ULONG todo); +extern ULONG VC_WriteBytes(SBYTE *buf,ULONG todo); +extern void VC_SilenceBytes(SBYTE *buf,ULONG todo); + +#if 1 +extern void VC_VoiceSetVolume(UBYTE voice, UBYTE vol); +extern void VC_VoiceSetPanning(UBYTE voice, UBYTE pan); +#else +extern void VC_VoiceSetVolume(UBYTE voice, UWORD vol); +extern void VC_VoiceSetPanning(UBYTE voice, ULONG pan); +#endif +extern void VC_VoiceSetFrequency(UBYTE voice, ULONG frq); +extern void VC_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags); + +extern void VC_VoiceStop(UBYTE voice); +extern BOOL VC_VoiceStopped(UBYTE voice); +extern void VC_VoiceReleaseSustain(UBYTE voice); +extern SLONG VC_VoiceGetPosition(UBYTE voice); +extern ULONG VC_VoiceRealVolume(UBYTE voice); + +extern int md_mode; +extern int md_mixfreq; +extern int md_dmabufsize; +extern char *myerr; + +#define DMODE_16BITS 1 +#define DMODE_STEREO 2 + +char *_mm_malloc(int size); +void _mm_free(char *buf); + +#endif diff --git a/arch/dos/mm_snd/include/mmio.h b/arch/dos/mm_snd/include/mmio.h new file mode 100644 index 00000000..e77c6174 --- /dev/null +++ b/arch/dos/mm_snd/include/mmio.h @@ -0,0 +1 @@ +/* empty */ \ No newline at end of file diff --git a/arch/dos/mm_snd/include/mtypes.h b/arch/dos/mm_snd/include/mtypes.h new file mode 100644 index 00000000..18f79b8b --- /dev/null +++ b/arch/dos/mm_snd/include/mtypes.h @@ -0,0 +1,75 @@ +#ifndef MTYPES_H +#define MTYPES_H + +/* + MikMod atomic types: + ==================== +*/ + + +#ifdef __OS2__ + +typedef signed char SBYTE; /* has to be 1 byte signed */ +typedef unsigned char UBYTE; /* has to be 1 byte unsigned */ +typedef short SWORD; /* has to be 2 bytes signed */ +typedef unsigned short UWORD; /* has to be 2 bytes unsigned */ +typedef long SLONG; /* has to be 4 bytes signed */ +/* ULONG and BOOL are already defined in OS2.H */ + +#elif defined(__alpha) + +typedef char SBYTE; /* has to be 1 byte signed */ +typedef unsigned char UBYTE; /* has to be 1 byte unsigned */ +typedef short SWORD; /* has to be 2 bytes signed */ +typedef unsigned short UWORD; /* has to be 2 bytes unsigned */ +/* long is 8 bytes on dec alpha - RCA */ +typedef int SLONG; /* has to be 4 bytes signed */ +typedef unsigned int ULONG; /* has to be 4 bytes unsigned */ +typedef int BOOL; /* doesn't matter.. 0=FALSE, <>0 true */ + +#else + +typedef char SBYTE; /* has to be 1 byte signed */ +typedef unsigned char UBYTE; /* has to be 1 byte unsigned */ +//typedef short SWORD; /* has to be 2 bytes signed */ +//typedef unsigned short UWORD; /* has to be 2 bytes unsigned */ +typedef int SWORD; /* (used to) has to be 2 bytes signed */ +typedef unsigned int UWORD; /* (used to) has to be 2 bytes unsigned */ +typedef long SLONG; /* has to be 4 bytes signed */ +typedef unsigned long ULONG; /* has to be 4 bytes unsigned */ +typedef int BOOL; /* doesn't matter.. 0=FALSE, <>0 true */ + +#endif + + +#ifdef __OS2__ +#define INCL_DOS +#define INCL_MCIOS2 +#define INCL_MMIOOS2 +#include +#include +#include +#endif + + +#ifdef __WATCOMC__ +#define inportb(x) inp(x) +#define outportb(x,y) outp(x,y) +#define inport(x) inpw(x) +#define outport(x,y) outpw(x,y) +#define disable() _disable() +#define enable() _enable() +#endif + + +#ifdef __DJGPP__ +#include +#include +#include +#define inp inportw +#define outport outportw +#define inport inportw +#define interrupt +#endif + +#endif diff --git a/arch/dos/mm_snd/mdma.c b/arch/dos/mm_snd/mdma.c new file mode 100644 index 00000000..05417d5c --- /dev/null +++ b/arch/dos/mm_snd/mdma.c @@ -0,0 +1,543 @@ +/* + +Name: +MDMA.C + +Description: +DMA routines + +Portability: + +MSDOS: BC(y) Watcom(y) DJGPP(y) +Win95: n +Os2: n +Linux: n + +(y) - yes +(n) - no (not possible or not useful) +(?) - may be possible, but not tested + +*/ +#include +#include +#include +#include "mdma.h" + + +/* DMA Controler #1 (8-bit controller) */ +#define DMA1_STAT 0x08 /* read status register */ +#define DMA1_WCMD 0x08 /* write command register */ +#define DMA1_WREQ 0x09 /* write request register */ +#define DMA1_SNGL 0x0A /* write single bit register */ +#define DMA1_MODE 0x0B /* write mode register */ +#define DMA1_CLRFF 0x0C /* clear byte ptr flip/flop */ +#define DMA1_MCLR 0x0D /* master clear register */ +#define DMA1_CLRM 0x0E /* clear mask register */ +#define DMA1_WRTALL 0x0F /* write all mask register */ + +/* DMA Controler #2 (16-bit controller) */ +#define DMA2_STAT 0xD0 /* read status register */ +#define DMA2_WCMD 0xD0 /* write command register */ +#define DMA2_WREQ 0xD2 /* write request register */ +#define DMA2_SNGL 0xD4 /* write single bit register */ +#define DMA2_MODE 0xD6 /* write mode register */ +#define DMA2_CLRFF 0xD8 /* clear byte ptr flip/flop */ +#define DMA2_MCLR 0xDA /* master clear register */ +#define DMA2_CLRM 0xDC /* clear mask register */ +#define DMA2_WRTALL 0xDE /* write all mask register */ + +#define DMA0_ADDR 0x00 /* chan 0 base adddress */ +#define DMA0_CNT 0x01 /* chan 0 base count */ +#define DMA1_ADDR 0x02 /* chan 1 base adddress */ +#define DMA1_CNT 0x03 /* chan 1 base count */ +#define DMA2_ADDR 0x04 /* chan 2 base adddress */ +#define DMA2_CNT 0x05 /* chan 2 base count */ +#define DMA3_ADDR 0x06 /* chan 3 base adddress */ +#define DMA3_CNT 0x07 /* chan 3 base count */ +#define DMA4_ADDR 0xC0 /* chan 4 base adddress */ +#define DMA4_CNT 0xC2 /* chan 4 base count */ +#define DMA5_ADDR 0xC4 /* chan 5 base adddress */ +#define DMA5_CNT 0xC6 /* chan 5 base count */ +#define DMA6_ADDR 0xC8 /* chan 6 base adddress */ +#define DMA6_CNT 0xCA /* chan 6 base count */ +#define DMA7_ADDR 0xCC /* chan 7 base adddress */ +#define DMA7_CNT 0xCE /* chan 7 base count */ + +#define DMA0_PAGE 0x87 /* chan 0 page register (refresh)*/ +#define DMA1_PAGE 0x83 /* chan 1 page register */ +#define DMA2_PAGE 0x81 /* chan 2 page register */ +#define DMA3_PAGE 0x82 /* chan 3 page register */ +#define DMA4_PAGE 0x8F /* chan 4 page register (unuseable)*/ +#define DMA5_PAGE 0x8B /* chan 5 page register */ +#define DMA6_PAGE 0x89 /* chan 6 page register */ +#define DMA7_PAGE 0x8A /* chan 7 page register */ + +#define MAX_DMA 8 + +#define DMA_DECREMENT 0x20 /* mask to make DMA hardware go backwards */ + +typedef struct { + UBYTE dma_disable; /* bits to disable dma channel */ + UBYTE dma_enable; /* bits to enable dma channel */ + UWORD page; /* page port location */ + UWORD addr; /* addr port location */ + UWORD count; /* count port location */ + UWORD single; /* single mode port location */ + UWORD mode; /* mode port location */ + UWORD clear_ff; /* clear flip-flop port location */ + UBYTE write; /* bits for write transfer */ + UBYTE read; /* bits for read transfer */ +} DMA_ENTRY; + +/* Variables needed ... */ + +static DMA_ENTRY mydma[MAX_DMA] = { + +/* DMA channel 0 */ + {0x04,0x00,DMA0_PAGE,DMA0_ADDR,DMA0_CNT, + DMA1_SNGL,DMA1_MODE,DMA1_CLRFF,0x48,0x44}, + +/* DMA channel 1 */ + {0x05,0x01,DMA1_PAGE,DMA1_ADDR,DMA1_CNT, + DMA1_SNGL,DMA1_MODE,DMA1_CLRFF,0x49,0x45}, + +/* DMA channel 2 */ + {0x06,0x02,DMA2_PAGE,DMA2_ADDR,DMA2_CNT, + DMA1_SNGL,DMA1_MODE,DMA1_CLRFF,0x4A,0x46}, + +/* DMA channel 3 */ + {0x07,0x03,DMA3_PAGE,DMA3_ADDR,DMA3_CNT, + DMA1_SNGL,DMA1_MODE,DMA1_CLRFF,0x4B,0x47}, + +/* DMA channel 4 */ + {0x04,0x00,DMA4_PAGE,DMA4_ADDR,DMA4_CNT, + DMA2_SNGL,DMA2_MODE,DMA2_CLRFF,0x48,0x44}, + +/* DMA channel 5 */ + {0x05,0x01,DMA5_PAGE,DMA5_ADDR,DMA5_CNT, + DMA2_SNGL,DMA2_MODE,DMA2_CLRFF,0x49,0x45}, + +/* DMA channel 6 */ + {0x06,0x02,DMA6_PAGE,DMA6_ADDR,DMA6_CNT, + DMA2_SNGL,DMA2_MODE,DMA2_CLRFF,0x4A,0x46}, + +/* DMA channel 7 */ + {0x07,0x03,DMA7_PAGE,DMA7_ADDR,DMA7_CNT, + DMA2_SNGL,DMA2_MODE,DMA2_CLRFF,0x4B,0x47}, +}; + + +/* + +Each specialised DMA code part should provide the following things: + +In MDMA.H: + + - a DMAMEM typedef, which should contain all the data that the + routines need for maintaining/allocating/freeing dma memory. + + +In MDMA.C: + + - 2 macros ENTER_CRITICAL and LEAVE_CRITICAL + + - A function 'static BOOL MDma_AllocMem0(DMAMEM *dm,UWORD size)' + which should perform the actual dma-memory allocation. It should + use DMAMEM *dm to store all it's information. + + - A function 'static void MDma_FreeMem0(DMAMEM *dm)' to free the memory + + - A function 'static ULONG MDma_GetLinearPtr(DMAMEM *dm)' which should + return the linear 20 bits pointer to the actual dmabuffer.. this + function is used by MDma_Start + + - A function 'void *MDma_GetPtr(DMAMEM *dm)' which should return a pointer + to the dmabuffer. If the dma memory can't be accessed directly it should + return a pointer to a FAKE dma buffer (DJGPP!!) + + - A function 'void MDma_Commit(DMAMEM *dm,UWORD index,UWORD count)'. This + function will be called each time a routine wrote something to the + dmabuffer (returned by MDma_GetPtr()). In the case of a FAKE dmabuffer + this routine should take care of copying the data from the fake buffer to + the real dma memory ('count' bytes from byteoffset 'index'). + +*/ + + + +#ifdef __WATCOMC__ + +/**************************************************************************** +********************* Watcom C specialised DMA code: ************************ +****************************************************************************/ + +#define ENTER_CRITICAL IRQ_PUSH_OFF() +extern void IRQ_PUSH_OFF (void); +#pragma aux IRQ_PUSH_OFF = \ + "pushfd", \ + "cli" \ + modify [esp]; + +#define LEAVE_CRITICAL IRQ_POP() +extern void IRQ_POP (void); +#pragma aux IRQ_POP = \ + "popfd" \ + modify [esp]; + + +static BOOL MDma_AllocMem0(DMAMEM *dm,UWORD size) +/* + Allocates a dma buffer of 'size' bytes. + returns FALSE if failed. +*/ +{ + static union REGS r; + ULONG p; + + /* allocate TWICE the size of the requested dma buffer.. + this fixes the 'page-crossing' bug of previous versions */ + + r.x.eax = 0x0100; /* DPMI allocate DOS memory */ + r.x.ebx = ((size*2) + 15) >> 4; /* Number of paragraphs requested */ + + int386 (0x31, &r, &r); + + if( r.x.cflag ) return 0; /* failed */ + + dm->raw_selector=r.x.edx; + + /* convert the segment into a linear address */ + + p=(r.x.eax&0xffff)<<4; + + /* if the first half of the allocated memory crosses a page + boundary, return the second half which is then guaranteed to + be page-continuous */ + + if( (p>>16) != ((p+size-1)>>16) ) p+=size; + + dm->continuous=(void *)p; + + return 1; +} + + +static void MDma_FreeMem0(DMAMEM *dm) +{ + static union REGS r; + r.x.eax = 0x0101; /* DPMI free DOS memory */ + r.x.edx = dm->raw_selector; /* base selector */ + int386 (0x31, &r, &r); +} + + +static ULONG MDma_GetLinearPtr(DMAMEM *dm) +{ + return (ULONG)dm->continuous; +} + + +void *MDma_GetPtr(DMAMEM *dm) +{ + return(dm->continuous); +} + + +void MDma_Commit(DMAMEM *dm,UWORD index,UWORD count) +{ + /* This function doesnt do anything here (WATCOM C + can access dma memory directly) */ +} + + +#elif defined(__DJGPP__) +/**************************************************************************** +*********************** DJGPP specialised DMA code: ************************* +****************************************************************************/ +#define ENTER_CRITICAL __asm__( "pushf \n\t popl %0 \n\t cli" : "=g" (__flags)) +#define LEAVE_CRITICAL __asm__( "pushl %0 \n\t popf" : : "g" (__flags)) +#include +#include + +static BOOL MDma_AllocMem0(DMAMEM *dm,UWORD size) +/* + Allocates a dma buffer of 'size' bytes - one in the code segment and + one in the lower 1 Mb physical mem. + It checks if the dma mem is page-continuous, and can only be + used to allocate exactly 1 block. +*/ +{ + int sel, seg; + + if (!(dm->continuous = (void *) malloc(size))) + return 0; + + // allocate twice + if ((seg = __dpmi_allocate_dos_memory((size * 2 + 15) >> 4, &sel)) < 0) + { + free(dm->continuous); + return 0; + } + + if ((seg & 0xf000) != ((seg + (size >> 4)) & 0xf000)) // crosses boundary? + { + // use second half + seg += (size >> 4); + } + + dm->raw.pm_offset = 0; + dm->raw.pm_selector = sel; + dm->raw.rm_offset = 0; + dm->raw.rm_segment = seg; + + return 1; +} + + + +static void MDma_FreeMem0(DMAMEM *dm) +{ + __dpmi_free_dos_memory(dm->raw.pm_selector); + free(dm->continuous); +} + +static ULONG MDma_GetLinearPtr(DMAMEM *dm) +{ + return (ULONG) dm->raw.rm_segment << 4; +} + + +void *MDma_GetPtr(DMAMEM *dm) +{ + return(dm->continuous); +} + +void MDma_Commit(DMAMEM *dm,UWORD index,UWORD count) +{ + char *src = &(((UBYTE*)dm->continuous)[index]); + ULONG dest = 16 * dm->raw.rm_segment + (ULONG) index; + #if 0 + _farsetsel(_go32_conventional_mem_selector()); + while(count--) { + _farnspokeb(dest++, *(src++)); + } + #endif + dosmemput(src, count, dest); +} + +#else + +/**************************************************************************** +********************* Borland C specialised DMA code: *********************** +****************************************************************************/ + +#define ENTER_CRITICAL asm{ pushf; cli } +#define LEAVE_CRITICAL asm{ popf } + +#define LPTR(ptr) (((ULONG)FP_SEG(ptr)<<4)+FP_OFF(ptr)) +#define NPTR(ptr) MK_FP(FP_SEG(p)+(FP_OFF(p)>>4),FP_OFF(p)&15) + + +static BOOL MDma_AllocMem0(DMAMEM *dm,UWORD size) +/* + Allocates a dma buffer of 'size' bytes. + returns FALSE if failed. +*/ +{ + char huge *p; + ULONG s; + + /* allocate TWICE the size of the requested dma buffer.. + so we can always get a page-contiguous dma buffer */ + + if((dm->raw=malloc((ULONG)size*2))==NULL) return 0; + + p=(char huge *)dm->raw; + s=LPTR(p); + + /* if the first half of the allocated memory crosses a page + boundary, return the second half which is then guaranteed to + be page-continuous */ + + if( (s>>16) != ((s+size-1)>>16) ) p+=size; + + /* put the page-continuous pointer into DMAMEM */ + + dm->continuous=NPTR(p); + + return 1; +} + + +static void MDma_FreeMem0(DMAMEM *dm) +{ + free(dm->raw); +} + + +static ULONG MDma_GetLinearPtr(DMAMEM *dm) +{ + return LPTR(dm->continuous); +} + + +void *MDma_GetPtr(DMAMEM *dm) +{ + return(dm->continuous); +} + +#pragma argsused + +void MDma_Commit(DMAMEM *dm,UWORD index,UWORD count) +{ + /* This function doesnt do anything here (BORLAND C + can access dma memory directly) */ +} + +#endif + + +/**************************************************************************** +************************* General DMA code: ********************************* +****************************************************************************/ + + +DMAMEM *MDma_AllocMem(UWORD size) +{ + DMAMEM *p; + + /* allocate dma memory structure */ + + if(!(p=(DMAMEM *)malloc(sizeof(DMAMEM)))) return NULL; + + /* allocate dma memory */ + + if(!MDma_AllocMem0(p,size)){ + + /* didn't succeed? -> free everything & return NULL */ + + free(p); + return NULL; + } + + return p; +} + + +void MDma_FreeMem(DMAMEM *p) +{ + MDma_FreeMem0(p); + free(p); +} + + +int MDma_Start(int channel,DMAMEM *dm,UWORD size,int type) +{ + DMA_ENTRY *tdma; + ULONG s_20bit,e_20bit; + UWORD spage,saddr,tcount; + UWORD epage/*,eaddr*/; + UBYTE cur_mode; + int __flags; + + tdma=&mydma[channel]; /* point to this dma data */ + + /* Convert the pc address to a 20 bit physical + address that the DMA controller needs */ + + s_20bit = MDma_GetLinearPtr(dm); + + e_20bit = s_20bit + size - 1; + spage = s_20bit>>16; + epage = e_20bit>>16; + + if(spage != epage) return 0; + + if(channel>=4){ + /* if 16-bit xfer, then addr,count & size are divided by 2 */ + s_20bit = s_20bit >> 1; + e_20bit = e_20bit >> 1; + size = size >> 1; + } + + saddr=s_20bit&0xffff; + + tcount = size-1; + + switch (type){ + + case READ_DMA: + cur_mode = tdma->read; + break; + + case WRITE_DMA: + cur_mode = tdma->write; + break; + + case INDEF_READ: + cur_mode = tdma->read | 0x10; /* turn on auto init */ + break; + + case INDEF_WRITE: + cur_mode = tdma->write | 0x10; /* turn on auto init */ + break; + + default: + return 0; + } + + ENTER_CRITICAL; + outportb(tdma->single,tdma->dma_disable); /* disable channel */ + outportb(tdma->mode,cur_mode); /* set mode */ + outportb(tdma->clear_ff,0); /* clear f/f */ + outportb(tdma->addr,saddr&0xff); /* LSB */ + outportb(tdma->addr,saddr>>8); /* MSB */ + outportb(tdma->page,spage); /* page # */ + outportb(tdma->clear_ff,0); /* clear f/f */ + outportb(tdma->count,tcount&0x0ff); /* LSB count */ + outportb(tdma->count,tcount>>8); /* MSB count */ + outportb(tdma->single,tdma->dma_enable); /* enable */ + LEAVE_CRITICAL; + + return 1; +} + + +void MDma_Stop(int channel) +{ + DMA_ENTRY *tdma; + tdma=&mydma[channel]; /* point to this dma data */ + outportb(tdma->single,tdma->dma_disable); /* disable chan */ +} + + +UWORD MDma_Todo(int channel) +{ + UWORD creg; + UWORD val1,val2; + int __flags; + + DMA_ENTRY *tdma=&mydma[channel]; + + creg=tdma->count; + + ENTER_CRITICAL; + + outportb(tdma->clear_ff,0xff); + + redo: + val1=inportb(creg); + val1|=inportb(creg)<<8; + val2=inportb(creg); + val2|=inportb(creg)<<8; + + val1-=val2; + if((SWORD)val1>64) goto redo; + if((SWORD)val1<-64) goto redo; + + LEAVE_CRITICAL; + + if(channel>3) val2<<=1; + + return val2; +} diff --git a/arch/dos/mm_snd/mirq.c b/arch/dos/mm_snd/mirq.c new file mode 100644 index 00000000..8d0db6d6 --- /dev/null +++ b/arch/dos/mm_snd/mirq.c @@ -0,0 +1,102 @@ +/* + +Name: +MDMA.C + +Description: +Some general purpose IRQ routines + +Portability: + +MSDOS: BC(y) Watcom(y) DJGPP(y) +Win95: n +Os2: n +Linux: n + +(y) - yes +(n) - no (not possible or not useful) +(?) - may be possible, but not tested + +*/ +#include +#include +#include "mirq.h" + +#define OCR1 0x20 /* 8259-1 Operation control register */ +#define IMR1 0x21 /* 8259-1 Mask register */ + +#define OCR2 0xA0 /* 8259-2 Operation control register */ +#define IMR2 0xA1 /* 8259-2 Mask register */ + + +BOOL MIrq_IsEnabled(UBYTE irqno) +/* + Returns true if the specified hardware irq is enabled. +*/ +{ + UBYTE imr=(irqno>7) ? IMR2 : IMR1; /* interrupt mask register */ + UBYTE msk=1<<(irqno&7); /* interrupt mask */ + return((inportb(imr) & msk) == 0); +} + + +BOOL MIrq_OnOff(UBYTE irqno,UBYTE onoff) +/* + Use to enable or disable the specified irq. +*/ +{ + UBYTE imr=(irqno>7) ? IMR2 : IMR1; /* interrupt mask register */ + UBYTE ocr=(irqno>7) ? OCR2 : OCR1; /* ocr */ + UBYTE msk=1<<(irqno&7); /* interrupt mask */ + UBYTE eoi=0x60|(irqno&7); /* specific end-of-interrupt */ + BOOL oldstate; + + /* save current setting of this irq */ + oldstate=((inportb(imr) & msk) == 0); + + if(onoff){ + outportb(imr,inportb(imr) & ~msk); + outportb(ocr,eoi); + if(irqno>7) MIrq_OnOff(2,1); + } + else{ + outportb(imr,inportb(imr) | msk); + } + + return oldstate; +} + + +void MIrq_EOI(UBYTE irqno) +/* + Clears the specified interrupt request at the interrupt controller. +*/ +{ + UBYTE ocr=(irqno>7) ? OCR2 : OCR1; /* ocr */ + UBYTE eoi=0x60|(irqno&7); /* specific end-of-interrupt */ + + outportb(ocr,eoi); + if(irqno>7) outportb(OCR1,0x20); +} + + +PVI MIrq_SetHandler(UBYTE irqno,PVI handler) +{ +#ifdef __DJGPP__ + _go32_dpmi_seginfo seginfo; +#endif + PVI oldvect; + int vecno=(irqno>7) ? irqno+0x68 : irqno+0x8; +#ifdef __DJGPP__ + _go32_dpmi_get_protected_mode_interrupt_vector(vecno, &seginfo); + oldvect = (PVI)seginfo.pm_offset; + seginfo.pm_offset = (int)handler; + seginfo.pm_selector = _go32_my_cs(); + _go32_dpmi_allocate_iret_wrapper(&seginfo); + _go32_dpmi_set_protected_mode_interrupt_vector(vecno, &seginfo); +#else + oldvect=_dos_getvect(vecno); + _dos_setvect(vecno,handler); +#endif + return oldvect; +} diff --git a/arch/dos/mm_snd/readme.txt b/arch/dos/mm_snd/readme.txt new file mode 100644 index 00000000..202cefe7 --- /dev/null +++ b/arch/dos/mm_snd/readme.txt @@ -0,0 +1,2 @@ +A larger part of the source in this directory is taken from MikMod 2.10 +by Jean-Paul Mikkers, which is now in the public domain. diff --git a/arch/dos/modex.asm b/arch/dos/modex.asm new file mode 100644 index 00000000..1f149eb7 --- /dev/null +++ b/arch/dos/modex.asm @@ -0,0 +1,829 @@ +;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +;SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +;IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +;FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +; +; $Source: /cvs/cvsroot/d2x/arch/dos/modex.asm,v $ +; $Revision: 1.1.1.1 $ +; $Author: bradleyb $ +; $Date: 2001-01-19 03:30:15 $ +; +; Routines to access ModeX VGA memory +; +; $Log: not supported by cvs2svn $ +; Revision 1.1.1.1 1999/06/14 21:57:56 donut +; Import of d1x 1.37 source. +; +; Revision 1.19 1995/03/01 15:37:46 john +; Better ModeX support. +; +; Revision 1.18 1994/11/24 13:24:20 john +; Made sure that some rep movs had the cld set first. +; Took some unused functions out. +; +; Revision 1.17 1994/09/22 18:15:02 john +; Made flip page wait for retrace. +; +; Revision 1.16 1994/09/22 16:08:27 john +; Fixed some palette stuff. +; +; Revision 1.15 1994/07/13 12:03:05 john +; Added assembly modex line-drawer. +; +; Revision 1.14 1994/05/06 12:50:34 john +; Added supertransparency; neatend things up; took out warnings. +; +; Revision 1.13 1994/05/03 19:39:04 john +; *** empty log message *** +; +; Revision 1.12 1994/02/18 15:32:32 john +; *** empty log message *** +; +; Revision 1.11 1993/12/21 11:40:36 john +; *** empty log message *** +; +; Revision 1.10 1993/12/09 15:02:26 john +; Changed palette stuff majorly +; +; Revision 1.9 1993/12/03 12:11:32 john +; fixed cx/ecx loop bugs. +; +; Revision 1.8 1993/11/16 11:28:18 john +; *** empty log message *** +; +; Revision 1.7 1993/10/15 16:23:23 john +; y +; +; Revision 1.6 1993/09/28 19:07:19 john +; stripped the waitforretrace out of fade to speed things up. +; +; Revision 1.5 1993/09/26 18:58:58 john +; fade stuff +; +; Revision 1.4 1993/09/21 14:01:15 john +; turned off video before mode set to reduce flicker. +; +; Revision 1.3 1993/09/08 11:38:36 john +; changed rcs stuff at beginning. +; +; +; + + +[BITS 32] + +section .data +%include "vgaregs.inc" +%include "tweak.inc" + +extern _gr_var_bwidth +extern _gr_video_memory + +global _modex_line_vertincr +global _modex_line_incr1 +global _modex_line_incr2 +global _modex_line_x1 +global _modex_line_x2 +global _modex_line_y1 +global _modex_line_y2 +global _modex_line_Color + +_modex_line_vertincr dd 0 +_modex_line_incr1 dd 0 +_modex_line_incr2 dd 0 +_modex_line_x1 dd 0 +_modex_line_y1 dd 0 +_modex_line_x2 dd 0 +_modex_line_y2 dd 0 +_modex_line_Color db 0 + + +_modex_line_routine dd 0 +SavedColor db 0 + +%define LEFT_MASK1 1000b +%define LEFT_MASK2 1100b +%define LEFT_MASK3 1110b +%define RIGHT_MASK1 0001b +%define RIGHT_MASK2 0011b +%define RIGHT_MASK3 0111b +%define ALL_MASK 1111b + +tmppal times 768 db 0 +fb_pal dd 0 +fb_add dw 0 +fb_count dd 0 + +MaskTable1 db ALL_MASK & RIGHT_MASK1 + db ALL_MASK & RIGHT_MASK2 + db ALL_MASK & RIGHT_MASK3 + db ALL_MASK + db LEFT_MASK3 & RIGHT_MASK1 + db LEFT_MASK3 & RIGHT_MASK2 + db LEFT_MASK3 & RIGHT_MASK3 + db LEFT_MASK3 + db LEFT_MASK2 & RIGHT_MASK1 + db LEFT_MASK2 & RIGHT_MASK2 + db LEFT_MASK2 & RIGHT_MASK3 + db LEFT_MASK2 + db LEFT_MASK1 & RIGHT_MASK1 + db LEFT_MASK1 & RIGHT_MASK2 + db LEFT_MASK1 & RIGHT_MASK3 + db LEFT_MASK1 + +MaskTable2 db ALL_MASK,RIGHT_MASK1 + db ALL_MASK,RIGHT_MASK2 + db ALL_MASK,RIGHT_MASK3 + db ALL_MASK,ALL_MASK + db LEFT_MASK3,RIGHT_MASK1 + db LEFT_MASK3,RIGHT_MASK2 + db LEFT_MASK3,RIGHT_MASK3 + db LEFT_MASK3,ALL_MASK + db LEFT_MASK2,RIGHT_MASK1 + db LEFT_MASK2,RIGHT_MASK2 + db LEFT_MASK2,RIGHT_MASK3 + db LEFT_MASK2,ALL_MASK + db LEFT_MASK1,RIGHT_MASK1 + db LEFT_MASK1,RIGHT_MASK2 + db LEFT_MASK1,RIGHT_MASK3 + db LEFT_MASK1,ALL_MASK + +DrawTable dd DrawMR + dd DrawMR + dd DrawMR + dd DrawM + dd DrawLMR + dd DrawLMR + dd DrawLMR + dd DrawLM + dd DrawLMR + dd DrawLMR + dd DrawLMR + dd DrawLM + dd DrawLMR + dd DrawLMR + dd DrawLMR + dd DrawLM + +section .text + +global _gr_sync_display + +_gr_sync_display: + mov dx, VERT_RESCAN +VS2A: in al, dx + and al, 08h + jnz VS2A ; Loop until not in vertical retrace +VS2B: in al, dx + and al, 08h + jz VS2B ; Loop until in vertical retrace + ret + + +; gr_modex_uscanline(int x1,int x2,int y,int color); +global _gr_modex_uscanline + +_gr_modex_uscanline: + push ebx + mov eax,[esp+8];x1 + mov edx,[esp+12];x2 + mov ebx,[esp+16];y + mov ecx,[esp+20];color + push edi + + ; EAX = X1 (X1 and X2 don't need to be sorted) + ; EDX = X2 + ; EBX = Y + ; ECX = Color + + mov [SavedColor], cl + + ;mov ebx, _RowOffset[ebx*4] + mov edi, [_gr_var_bwidth] + imul edi, ebx + add edi, [_gr_video_memory] + cmp eax, edx + jle @@f1 + xchg eax, edx +@@f1: mov bl, al + shl bl, 2 + mov bh, dl + and bh, 011b + or bl, bh + and ebx, 0fh + ; BX = LeftRight switch command. (4bit) + shr eax, 2 + shr edx, 2 + add edi, eax + ; EDI = Offset into video memory + mov ecx, edx + sub ecx, eax + ; ECX = X2/4 - X1/4 - 1 + jnz LargerThan4 + +;======================= ONE GROUP OF 4 OR LESS TO DRAW ==================== + + mov dx, SC_INDEX + mov al, SC_MAP_MASK + out dx, al + inc dx + mov al, [MaskTable1+ebx] + out dx, al + mov al, [SavedColor] + mov [edi], al ; Write the one pixel + pop edi + pop ebx + ret + +LargerThan4: + dec ecx + jnz LargerThan8 + +;===================== TWO GROUPS OF 4 OR LESS TO DRAW ==================== + + mov cx, word [MaskTable2+ebx*2] + mov bl, [SavedColor] + mov dx, SC_INDEX + mov al, SC_MAP_MASK + out dx, al + inc dx + mov al, cl + out dx, al + mov [edi], bl ; Write the left pixel + mov al, ch + out dx, al + mov [edi+1], bl ; Write the right pixel + pop edi + pop ebx + ret + +;========================= MANY GROUPS OF 4 TO DRAW ====================== +LargerThan8: + mov dx, SC_INDEX + mov al, SC_MAP_MASK + out dx, al + inc dx + ; DX = SC_INDEX + mov al, [SavedColor] + mov ah, al + ; AL,AH = color of pixel + jmp dword [DrawTable+ebx*4] + + +DrawM: ;AH=COLOR, EDI=DEST, CX=X2/4-X1/4-1, BX=Table Index + mov al, ALL_MASK + out dx, al + mov al, ah + cld + add ecx, 2 + shr ecx, 1 + rep stosw ; Write the middle pixels + jnc @@f2 + stosb ; Write the middle odd pixel +@@f2: pop edi + pop ebx + ret + +DrawLM: + ;AH=COLOR, EDI=DEST, CX=X2/4-X1/4-1, BX=Table Index + mov al, byte [MaskTable2+ebx*2] + out dx, al + mov [edi], ah ; Write leftmost pixels + inc edi + mov al, ALL_MASK + out dx, al + mov al, ah + cld + inc ecx + shr ecx, 1 + rep stosw ; Write the middle pixels + jnc @@f3 + stosb ; Write the middle odd pixel +@@f3: pop edi + pop ebx + ret + + +DrawLMR: ;AH=COLOR, EDI=DEST, CX=X2/4-X1/4-1, BX=Table Index + mov bx, word [MaskTable2+ebx*2] + mov al, bl + out dx, al + mov [edi], ah ; Write leftmost pixels + inc edi + mov al, ALL_MASK + out dx, al + mov al, ah + cld + shr ecx, 1 + rep stosw ; Write the middle pixels + jnc @@f4 + stosb ; Write the middle odd pixel +@@f4: mov al, bh + out dx, al + mov [edi], ah ; Write the rightmost pixels + pop edi + pop ebx + ret + +DrawMR: ;AH=COLOR, EDI=DEST, CX=X2/4-X1/4-1, BX=Table Index + mov bx, word [MaskTable2+ebx*2] + mov al, ALL_MASK + out dx, al + mov al, ah + cld + inc ecx + shr ecx, 1 + rep stosw ; Write the middle pixels + jnc @@f5 + stosb ; Write the middle odd pixel +@@f5: mov al, bh + out dx, al + mov [edi], ah ; Write the rightmost pixels + pop edi + pop ebx + ret + + +global _gr_modex_setmode + +_gr_modex_setmode: + mov eax,[esp+4] + push ecx + push edx + push esi + push edi + + mov ecx, eax + dec ecx + + cmp ecx, LAST_X_MODE + jbe @@f6 + mov ecx, 0 +@@f6: + + ;call turn_screen_off + + push ecx ; some bios's dont preserve cx + + ;mov ax, 1201h + ;mov bl, 31h ; disable palette loading at mode switch + ;int 10h + mov ax,13h ; let the BIOS set standard 256-color + int 10h ; mode (320x200 linear) + ;mov ax, 1200h + ;mov bl, 31h ; enable palette loading at mode switch + ;int 10h + + pop ecx + + mov dx,SC_INDEX + mov ax,0604h + out dx,ax ; disable chain4 mode + + mov dx,SC_INDEX + mov ax,0100h + out dx,ax ; synchronous reset while setting Misc + ; Output for safety, even though clock + ; unchanged + + mov esi, dword [ModeTable+ecx*4] + lodsb + + or al,al + jz DontSetDot + + mov dx,MISC_OUTPUT + out dx,al ; select the dot clock and Horiz + ; scanning rate + + ;mov dx,SC_INDEX + ;mov al,01h + ;out dx,al + ;inc dx + ;in al, dx + ;or al, 1000b + ;out dx, al + +DontSetDot: + mov dx,SC_INDEX + mov ax,0300h + out dx,ax ; undo reset (restart sequencer) + + mov dx,CRTC_INDEX ; reprogram the CRT Controller + mov al,11h ; VSync End reg contains register write + out dx,al ; protect bit + inc dx ; CRT Controller Data register + in al,dx ; get current VSync End register setting + and al,07fh ; remove write protect on various + out dx,al ; CRTC registers + dec dx ; CRT Controller Index + cld + xor ecx,ecx + lodsb + mov cl,al + +SetCRTParmsLoop: + lodsw ; get the next CRT Index/Data pair + out dx,ax ; set the next CRT Index/Data pair + loop SetCRTParmsLoop + + mov dx,SC_INDEX + mov ax,0f02h + out dx,ax ; enable writes to all four planes + mov edi, [_gr_video_memory] ; point ES:DI to display memory + xor eax,eax ; clear to zero-value pixels + mov ecx,4000h ; # of dwords in display memory + rep stosd ; clear all of display memory + + ; Set pysical screen dimensions + + xor eax, eax + lodsw ; Load scrn pixel width + mov cx, ax + shl eax, 16 + + mov dx,CRTC_INDEX + mov al,CRTC_OFFSET + out dx,al + inc dx + mov ax,cx + shr ax,3 + out dx,al + + ;mov si, 360 + ;@@: + ;mov ax, 04f06h + ;mov bl, 0 + ;mov cx, si + ;int 10h + ;cmp cx, si + ;je @f + ;inc si + ;jmp @B + ;@@: + ;movzx eax, si + + lodsw ; Load Screen Phys. Height + + ;call turn_screen_on + + pop edi + pop esi + pop edx + pop ecx + + ret + +global _gr_modex_setplane + +_gr_modex_setplane: + mov eax,[esp+4] + + mov cl, al + + ; SELECT WRITE PLANE + and cl,011b ;CL = plane + mov ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg + shl ah,cl ;set only the bit for the required + ; plane to 1 + mov dx,SC_INDEX ;set the Map Mask to enable only the + out dx,ax ; pixel's plane + + ; SELECT READ PLANE + mov ah,cl ;AH = plane + mov al,READ_MAP ;AL = index in GC of the Read Map reg + mov dx,GC_INDEX ;set the Read Map to read the pixel's + out dx,ax ; plane + ret + +global _gr_modex_setstart + +_gr_modex_setstart: + push ebx + mov eax,[esp+8] + mov edx,[esp+12] + mov ebx,[esp+16] + push ebx + + ; EAX = X + ; EDX = Y + ; EBX = Wait for retrace + + mov ecx, [_gr_var_bwidth] + imul ecx, edx + + shr eax, 2 + add eax, ecx + + mov ch, ah + mov bh, al + + mov bl, CC_START_LO + mov cl, CC_START_HI + + cli + mov dx, VERT_RESCAN +WaitDE: in al, dx + test al, 01h + jnz WaitDE + + mov dx, CRTC_INDEX + mov ax, bx + out dx, ax ; Start address low + mov ax, cx + out dx, ax ; Start address high + sti + + pop ebx + cmp ebx, 0 + je NoWaitVS + mov dx, VERT_RESCAN +WaitVS: in al, dx + test al, 08h + jz WaitVS ; Loop until in vertical retrace +NoWaitVS: + + pop ebx + + ret + + + + +%macro ModeXAddr 0 +; given: ebx=x, eax=y, return cl=plane mask, ebx=address, trash eax + mov cl, bl + and cl, 3 + shr ebx, 2 + imul eax, [_gr_var_bwidth] + add ebx, eax + add ebx, [_gr_video_memory] +%endmacro + + +;----------------------------------------------------------------------- +; +; Line drawing function for all MODE X 256 Color resolutions +; Based on code from "PC and PS/2 Video Systems" by Richard Wilton. + +global _gr_modex_line + +_gr_modex_line: + pusha + + mov dx,SC_INDEX ; setup for plane mask access + +; check for vertical line + + mov esi,[_gr_var_bwidth] + mov ecx,[_modex_line_x2] + sub ecx,[_modex_line_x1] + jz near VertLine + +; force x1 < x2 + + jns L01 + + neg ecx + + mov ebx,[_modex_line_x2] + xchg ebx,[_modex_line_x1] + mov [_modex_line_x2],ebx + + mov ebx,[_modex_line_y2] + xchg ebx,[_modex_line_y1] + mov [_modex_line_y2],ebx + +; calc dy = abs(y2 - y1) + +L01: + mov ebx,[_modex_line_y2] + sub ebx,[_modex_line_y1] + jnz short skip + jmp HorizLine +skip: jns L03 + + neg ebx + neg esi + +; select appropriate routine for slope of line + +L03: + mov [_modex_line_vertincr],esi + mov dword [_modex_line_routine],LoSlopeLine + cmp ebx,ecx + jle L04 + mov dword [_modex_line_routine],HiSlopeLine + xchg ebx,ecx + +; calc initial decision variable and increments + +L04: + shl ebx,1 + mov [_modex_line_incr1],ebx + sub ebx,ecx + mov esi,ebx + sub ebx,ecx + mov [_modex_line_incr2],ebx + +; calc first pixel address + + push ecx + mov eax,[_modex_line_y1] + mov ebx,[_modex_line_x1] + ModeXAddr + mov edi,ebx + mov al,1 + shl al,cl + mov ah,al ; duplicate nybble + shl al,4 + add ah,al + mov bl,ah + pop ecx + inc ecx + jmp near dword [_modex_line_routine] + +; routine for verticle lines + +VertLine: + mov eax,[_modex_line_y1] + mov ebx,[_modex_line_y2] + mov ecx,ebx + sub ecx,eax + jge L31 + neg ecx + mov eax,ebx + +L31: + inc ecx + mov ebx,[_modex_line_x1] + push ecx + ModeXAddr + + mov ah,1 + shl ah,cl + mov al,MAP_MASK + out dx,ax + pop ecx + mov ax, word [_modex_line_Color] + +; draw the line + +L32: + mov [ebx],al + add ebx,esi + loop L32 + jmp Lexit + +; routine for horizontal line + +HorizLine: + + mov eax,[_modex_line_y1] + mov ebx,[_modex_line_x1] + ModeXAddr + + mov edi,ebx ; set dl = first byte mask + mov dl,00fh + shl dl,cl + + mov ecx,[_modex_line_x2] ; set dh = last byte mask + and cl,3 + mov dh,00eh + shl dh,cl + not dh + +; determine byte offset of first and last pixel in line + + mov eax,[_modex_line_x2] + mov ebx,[_modex_line_x1] + + shr eax,2 ; set ax = last byte column + shr ebx,2 ; set bx = first byte column + mov ecx,eax ; cx = ax - bx + sub ecx,ebx + + mov eax,edx ; mov end byte masks to ax + mov dx,SC_INDEX ; setup dx for VGA outs + mov bl,[_modex_line_Color] + +; set pixels in leftmost byte of line + + or ecx,ecx ; is start and end pt in same byte + jnz L42 ; no ! + and ah,al ; combine start and end masks + jmp short L44 + +L42: push eax + mov ah,al + mov al,MAP_MASK + out dx,ax + mov al,bl + stosb + dec ecx + +; draw remainder of the line + +L43: + mov ah,0Fh + mov al,MAP_MASK + out dx,ax + mov al,bl + rep stosb + pop eax + +; set pixels in rightmost byte of line + +L44: + mov al,MAP_MASK + out dx, ax + mov [edi],bl + jmp Lexit + + +; routine for dy >= dx (slope <= 1) + +LoSlopeLine: + mov al,MAP_MASK + mov bh,byte [_modex_line_Color] +L10: + mov ah,bl + +L11: + or ah,bl + rol bl,1 + jc L14 + +; bit mask not shifted out + + or esi,esi + jns L12 + add esi,[_modex_line_incr1] + loop L11 + + out dx,ax + mov [edi],bh + jmp short Lexit + +L12: + add esi,[_modex_line_incr2] + out dx,ax + mov [edi],bh + add edi,[_modex_line_vertincr] + loop L10 + jmp short Lexit + +; bit mask shifted out + +L14: out dx,ax + mov [edi],bh + inc edi + or esi,esi + jns L15 + add esi,[_modex_line_incr1] + loop L10 + jmp short Lexit + +L15: + add esi,[_modex_line_incr2] + add edi,[_modex_line_vertincr] + loop L10 + jmp short Lexit + +; routine for dy > dx (slope > 1) + +HiSlopeLine: + mov ebx,[_modex_line_vertincr] + mov al,MAP_MASK +L21: out dx,ax + push eax + mov al,[_modex_line_Color] + mov [edi],al + pop eax + add edi,ebx + +L22: + or esi,esi + jns L23 + + add esi,[_modex_line_incr1] + loop L21 + jmp short Lexit + +L23: + add esi,[_modex_line_incr2] + rol ah,1 + adc edi,0 +lx21: loop L21 + +; return to caller + +Lexit: + popa + ret diff --git a/arch/dos/mono.c b/arch/dos/mono.c new file mode 100644 index 00000000..fcfab0f3 --- /dev/null +++ b/arch/dos/mono.c @@ -0,0 +1,470 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/arch/dos/mono.c,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:15 $ + * + * Library functions for printing to mono card. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 21:58:35 donut + * Import of d1x 1.37 source. + * + * Revision 1.12 1995/02/23 11:59:57 john + * Made the windows smaller so they don't overwrite the debug file menus. + * + * Revision 1.11 1994/11/27 23:07:50 matt + * Made changes needed to be able to compile out monochrome debugging code + * + * Revision 1.10 1994/10/26 22:23:43 john + * Limited windows to 2. Took away saving what was under + * a window. + * + * Revision 1.9 1994/07/14 23:25:44 matt + * Allow window 0 to be opened; don't allow mono to be initialized twice + * + * Revision 1.8 1994/03/09 10:45:38 john + * Sped up scroll. + * + * Revision 1.7 1994/01/26 08:56:55 mike + * Comment out int3 in mputc. + * + * Revision 1.6 1994/01/12 15:56:34 john + * made backspace do an int3 during mono stuff. + * ., + * + * Revision 1.5 1993/12/07 12:33:23 john + * *** empty log message *** + * + * Revision 1.4 1993/10/15 10:10:25 john + * *** empty log message *** + * + * Revision 1.3 1993/09/14 20:55:13 matt + * Made minit() and mopen() check for presence of mono card in machine. + * + * Revision 1.2 1993/07/22 13:10:21 john + * *** empty log message *** + * + * Revision 1.1 1993/07/10 13:10:38 matt + * Initial revision + * + * + */ + +#ifdef RCS +static char rcsid[] = "$Id: mono.c,v 1.1.1.1 2001-01-19 03:30:15 bradleyb Exp $"; +#endif + +// Library functions for printing to mono card. + +#include +#include +#include +#include +#include +#include + +#include "key.h" + +//#define MONO_IS_STDERR +#ifndef __GNUC__ +void mono_int_3(); +#pragma aux mono_int_3 = "int 3"; +#else +static inline void mono_int_3() { asm("int $3"); } +#endif +void msetcursor(short row, short col); + +#define MAX_NUM_WINDOWS 2 + +struct mono_element { + unsigned char character; + unsigned char attribute; +}; + +typedef struct { + short first_row; + short height; + short first_col; + short width; + short cursor_row; + short cursor_col; + short open; + struct mono_element save_buf[25][80]; + struct mono_element text[25][80]; +} WINDOW; + + +void scroll( short n ); +void drawbox( short n ); + +#define ROW Window[n].first_row +#define HEIGHT Window[n].height +#define COL Window[n].first_col +#define WIDTH Window[n].width +#define CROW Window[n].cursor_row +#define CCOL Window[n].cursor_col +#define OPEN Window[n].open +#define CHAR(r,c) (*monoscreen)[ROW+(r)][COL+(c)].character +#define ATTR(r,c) (*monoscreen)[ROW+(r)][COL+(c)].attribute +#define XCHAR(r,c) Window[n].text[ROW+(r)][COL+(c)].character +#define XATTR(r,c) Window[n].text[ROW+(r)][COL+(c)].attribute + +static WINDOW Window[MAX_NUM_WINDOWS]; + +struct mono_element (*monoscreen)[25][80]; + +void mputc( short n, char c ) +{ + if (!OPEN) return; + +// if (keyd_pressed[KEY_BACKSP]) +// mono_int_3(); + + switch (c) + { + case 8: + if (CCOL > 0) CCOL--; + break; + case 9: + CHAR( CROW, CCOL ) = ' '; + ATTR( CROW, CCOL ) = XATTR( CROW, CCOL ); + XCHAR( CROW, CCOL ) = ' '; + CCOL++; + while (CCOL % 4) { + CHAR( CROW, CCOL ) = ' '; + ATTR( CROW, CCOL ) = XATTR( CROW, CCOL ); + XCHAR( CROW, CCOL ) = ' '; + CCOL++; + } + break; + case 10: + case 13: + CCOL = 0; + CROW++; + break; + default: + CHAR( CROW, CCOL ) = c; + ATTR( CROW, CCOL ) = XATTR( CROW, CCOL ); + XCHAR( CROW, CCOL ) = c; + CCOL++; + } + + if ( CCOL >= WIDTH ) { + CCOL = 0; + CROW++; + } + if ( CROW >= HEIGHT ) { + CROW--; + scroll(n); + } + + msetcursor( ROW+CROW, COL+CCOL ); + +} + +void mputc_at( short n, short row, short col, char c ) +{ + CROW = row; + CCOL = col; + + if (!OPEN) return; + + mputc( n, c ); + +} + +#ifdef __WATCOMC__ +void copy_row(int nwords,short *src, short *dest1, short *dest2 ); +#pragma aux copy_row parm [ecx] [esi] [ebx] [edx] modify exact [eax ebx ecx edx esi] = \ +" shr ecx, 1" \ +" jnc even_num" \ +" mov ax, [esi]" \ +" add esi, 2" \ +" mov [ebx], ax" \ +" add ebx, 2" \ +" mov [edx], ax" \ +" add edx, 2" \ +"even_num: cmp ecx, 0" \ +" je done" \ +"rowloop: mov eax, [esi]" \ +" add esi, 4" \ +" mov [edx], eax" \ +" add edx, 4" \ +" mov [ebx], eax" \ +" add ebx, 4" \ +" loop rowloop" \ +"done: " +#else +void copy_row(int nwords,short *src, short *dest1, short *dest2 ) { + while (nwords--) + *(dest1++) = *(dest2++) = *(src++); +} +#endif + +void scroll( short n ) +{ + register int row, col; + + if (!OPEN) return; + + col = 0; + for ( row = 0; row < (HEIGHT-1); row++ ) + copy_row( WIDTH, (short *)&XCHAR(row+1,col), (short *)&CHAR(row,col), (short *)&XCHAR(row,col) ); + +// for ( col = 0; col < WIDTH; col++ ) +// { +// CHAR( row, col ) = XCHAR( row+1, col ); +// ATTR( row, col ) = XATTR( row+1, col ); +// XCHAR( row, col ) = XCHAR( row+1, col ); +// XATTR( row, col ) = XATTR( row+1, col ); +// } + + for ( col = 0; col < WIDTH; col++ ) + { + CHAR( HEIGHT-1, col ) = ' '; + ATTR( HEIGHT-1, col ) = XATTR( HEIGHT-1, col ); + XCHAR( HEIGHT-1, col ) = ' '; + } + +} + +void msetcursor(short row, short col) +{ + int pos = row*80+col; + + outp( 0x3b4, 15 ); + outp( 0x3b5, pos & 0xFF ); + outp( 0x3b4, 14 ); + outp( 0x3b5, (pos >> 8) & 0xff ); +} + +static char temp_m_buffer[1000]; +void _mprintf( short n, char * format, ... ) +{ +#ifdef MONO_IS_STDERR + va_list args; + va_start(args, format ); + vfprintf(stderr, format, args); +#else + char *ptr=temp_m_buffer; + va_list args; + + if (!OPEN) return; + + va_start(args, format ); + vsprintf(temp_m_buffer,format,args); + while( *ptr ) + mputc( n, *ptr++ ); +#endif +} + +void _mprintf_at( short n, short row, short col, char * format, ... ) +{ + int r,c; + char buffer[1000], *ptr=buffer; + va_list args; + + if (!OPEN) return; + + r = CROW; c = CCOL; + + CROW = row; + CCOL = col; + + va_start(args, format ); + vsprintf(buffer,format,args); + while( *ptr ) + mputc( n, *ptr++ ); + + + CROW = r; CCOL = c; + + msetcursor( ROW+CROW, COL+CCOL ); + +} + + +void drawbox(short n) +{ + short row, col; + + if (!OPEN) return; + + for (row=0; row +#define _BORLAND_DOS_REGS 1 +#define near +_go32_dpmi_registers handler_regs; +#endif + +#include + +#include +#include +#include +#include +#include +#include + +#include "error.h" +#include "fix.h" +#include "u_dpmi.h" +#include "mouse.h" +#include "timer.h" + +#define ME_CURSOR_MOVED (1<<0) +#define ME_LB_P (1<<1) +#define ME_LB_R (1<<2) +#define ME_RB_P (1<<3) +#define ME_RB_R (1<<4) +#define ME_MB_P (1<<5) +#define ME_MB_R (1<<6) +#define ME_OB_P (1<<7) +#define ME_OB_R (1<<8) +#define ME_X_C (1<<9) +#define ME_Y_C (1<<10) +#define ME_Z_C (1<<11) +#define ME_P_C (1<<12) +#define ME_B_C (1<<13) +#define ME_H_C (1<<14) +#define ME_O_C (1<<15) + +#define MOUSE_MAX_BUTTONS 11 + +typedef struct event_info { + short x; + short y; + short z; + short pitch; + short bank; + short heading; + ushort button_status; + ushort device_dependant; +} event_info; + +typedef struct mouse_info { + fix ctime; + ubyte cyberman; + int num_buttons; + ubyte pressed[MOUSE_MAX_BUTTONS]; + fix time_went_down[MOUSE_MAX_BUTTONS]; + fix time_held_down[MOUSE_MAX_BUTTONS]; + uint num_downs[MOUSE_MAX_BUTTONS]; + uint num_ups[MOUSE_MAX_BUTTONS]; + event_info *x_info; + ushort button_status; +} mouse_info; + +typedef struct cyberman_info { + ubyte device_type; + ubyte major_version; + ubyte minor_version; + ubyte x_descriptor; + ubyte y_descriptor; + ubyte z_descriptor; + ubyte pitch_descriptor; + ubyte roll_descriptor; + ubyte yaw_descriptor; + ubyte reserved; +} cyberman_info; + +static mouse_info Mouse; + +static int Mouse_installed = 0; + +#ifdef __DJGPP__ +#define m_ax r->d.eax +#define mbx r->d.ebx +#define mcx r->d.ecx +#define mdx r->d.edx +#define msi r->d.esi +#define mdi r->d.edi +void mouse_handler (_go32_dpmi_registers *r) +{ +#else +#pragma off (check_stack) +void _loadds far mouse_handler (int m_ax, int mbx, int mcx, int mdx, int msi, int mdi) +{ +#pragma aux mouse_handler parm [EAX] [EBX] [ECX] [EDX] [ESI] [EDI] +#endif + Mouse.ctime = timer_get_fixed_secondsX(); + + if (m_ax & ME_LB_P) { // left button pressed + if (!Mouse.pressed[MB_LEFT]) { + Mouse.pressed[MB_LEFT] = 1; + Mouse.time_went_down[MB_LEFT] = Mouse.ctime; + } + Mouse.num_downs[MB_LEFT]++; + } else if (m_ax & ME_LB_R ) { // left button released + if (Mouse.pressed[MB_LEFT]) { + Mouse.pressed[MB_LEFT] = 0; + Mouse.time_held_down[MB_LEFT] += Mouse.ctime-Mouse.time_went_down[MB_LEFT]; + } + Mouse.num_ups[MB_LEFT]++; + } + + if (m_ax & ME_RB_P ) { // right button pressed + if (!Mouse.pressed[MB_RIGHT]) { + Mouse.pressed[MB_RIGHT] = 1; + Mouse.time_went_down[MB_RIGHT] = Mouse.ctime; + } + Mouse.num_downs[MB_RIGHT]++; + } else if (m_ax & ME_RB_R ) {// right button released + if (Mouse.pressed[MB_RIGHT]) { + Mouse.pressed[MB_RIGHT] = 0; + Mouse.time_held_down[MB_RIGHT] += Mouse.ctime-Mouse.time_went_down[MB_RIGHT]; + } + Mouse.num_ups[MB_RIGHT]++; + } + + if (m_ax & ME_MB_P ) { // middle button pressed + if (!Mouse.pressed[MB_MIDDLE]) { + Mouse.pressed[MB_MIDDLE] = 1; + Mouse.time_went_down[MB_MIDDLE] = Mouse.ctime; + } + Mouse.num_downs[MB_MIDDLE]++; + } else if (m_ax & ME_MB_R ) { // middle button released + if (Mouse.pressed[MB_MIDDLE]) { + Mouse.pressed[MB_MIDDLE] = 0; + Mouse.time_held_down[MB_MIDDLE] += Mouse.ctime-Mouse.time_went_down[MB_MIDDLE]; + } + Mouse.num_ups[MB_MIDDLE]++; + } + + if (Mouse.cyberman && (m_ax & (ME_Z_C|ME_P_C|ME_B_C|ME_H_C))) { + Mouse.x_info = (event_info *)((msi & 0xFFFF) << 4); + + if (m_ax & ME_Z_C ) { // z axis changed + if (Mouse.pressed[MB_Z_UP]) { + // z up released + Mouse.pressed[MB_Z_UP] = 0; + Mouse.time_held_down[MB_Z_UP] += Mouse.ctime-Mouse.time_went_down[MB_Z_UP]; + Mouse.num_ups[MB_Z_UP]++; + } else if ( Mouse.x_info->z>0 ) { + // z up pressed + Mouse.pressed[MB_Z_UP] = 1; + Mouse.time_went_down[MB_Z_UP]=Mouse.ctime; + Mouse.num_downs[MB_Z_UP]++; + } + if (Mouse.pressed[MB_Z_DOWN]) { + // z down released + Mouse.pressed[MB_Z_DOWN] = 0; + Mouse.time_held_down[MB_Z_DOWN] += Mouse.ctime-Mouse.time_went_down[MB_Z_DOWN]; + Mouse.num_ups[MB_Z_DOWN]++; + } else if ( Mouse.x_info->z<0 ) { + // z down pressed + Mouse.pressed[MB_Z_DOWN] = 1; + Mouse.time_went_down[MB_Z_DOWN]=Mouse.ctime; + Mouse.num_downs[MB_Z_DOWN]++; + } + } + if (m_ax & ME_P_C ) { // pitch changed + if (Mouse.pressed[MB_PITCH_BACKWARD]) { + // pitch backward released + Mouse.pressed[MB_PITCH_BACKWARD] = 0; + Mouse.time_held_down[MB_PITCH_BACKWARD] += Mouse.ctime-Mouse.time_went_down[MB_PITCH_BACKWARD]; + Mouse.num_ups[MB_PITCH_BACKWARD]++; + } else if ( Mouse.x_info->pitch>0 ) { + // pitch backward pressed + Mouse.pressed[MB_PITCH_BACKWARD] = 1; + Mouse.time_went_down[MB_PITCH_BACKWARD]=Mouse.ctime; + Mouse.num_downs[MB_PITCH_BACKWARD]++; + } + if (Mouse.pressed[MB_PITCH_FORWARD]) { + // pitch forward released + Mouse.pressed[MB_PITCH_FORWARD] = 0; + Mouse.time_held_down[MB_PITCH_FORWARD] += Mouse.ctime-Mouse.time_went_down[MB_PITCH_FORWARD]; + Mouse.num_ups[MB_PITCH_FORWARD]++; + } else if ( Mouse.x_info->pitch<0 ) { + // pitch forward pressed + Mouse.pressed[MB_PITCH_FORWARD] = 1; + Mouse.time_went_down[MB_PITCH_FORWARD]=Mouse.ctime; + Mouse.num_downs[MB_PITCH_FORWARD]++; + } + } + + if (m_ax & ME_B_C ) { // bank changed + if (Mouse.pressed[MB_BANK_LEFT]) { + // bank left released + Mouse.pressed[MB_BANK_LEFT] = 0; + Mouse.time_held_down[MB_BANK_LEFT] += Mouse.ctime-Mouse.time_went_down[MB_BANK_LEFT]; + Mouse.num_ups[MB_BANK_LEFT]++; + } else if ( Mouse.x_info->bank>0 ) { + // bank left pressed + Mouse.pressed[MB_BANK_LEFT] = 1; + Mouse.time_went_down[MB_BANK_LEFT]=Mouse.ctime; + Mouse.num_downs[MB_BANK_LEFT]++; + } + if (Mouse.pressed[MB_BANK_RIGHT]) { + // bank right released + Mouse.pressed[MB_BANK_RIGHT] = 0; + Mouse.time_held_down[MB_BANK_RIGHT] += Mouse.ctime-Mouse.time_went_down[MB_BANK_RIGHT]; + Mouse.num_ups[MB_BANK_RIGHT]++; + } else if ( Mouse.x_info->bank<0 ) { + // bank right pressed + Mouse.pressed[MB_BANK_RIGHT] = 1; + Mouse.time_went_down[MB_BANK_RIGHT]=Mouse.ctime; + Mouse.num_downs[MB_BANK_RIGHT]++; + } + } + + if (m_ax & ME_H_C ) { // heading changed + if (Mouse.pressed[MB_HEAD_LEFT]) { + // head left released + Mouse.pressed[MB_HEAD_LEFT] = 0; + Mouse.time_held_down[MB_HEAD_LEFT] += Mouse.ctime-Mouse.time_went_down[MB_HEAD_LEFT]; + Mouse.num_ups[MB_HEAD_LEFT]++; + } else if ( Mouse.x_info->heading>0 ) { + // head left pressed + Mouse.pressed[MB_HEAD_LEFT] = 1; + Mouse.time_went_down[MB_HEAD_LEFT]=Mouse.ctime; + Mouse.num_downs[MB_HEAD_LEFT]++; + } + if (Mouse.pressed[MB_HEAD_RIGHT]) { + // head right released + Mouse.pressed[MB_HEAD_RIGHT] = 0; + Mouse.time_held_down[MB_HEAD_RIGHT] += Mouse.ctime-Mouse.time_went_down[MB_HEAD_RIGHT]; + Mouse.num_ups[MB_HEAD_RIGHT]++; + } else if ( Mouse.x_info->heading<0 ) { + // head right pressed + Mouse.pressed[MB_HEAD_RIGHT] = 1; + Mouse.time_went_down[MB_HEAD_RIGHT]=Mouse.ctime; + Mouse.num_downs[MB_HEAD_RIGHT]++; + } + } + } + +} + + + + +void mouse_handler_end (void) // dummy functions +{ +} +#pragma on (check_stack) + +//-------------------------------------------------------- +// returns 0 if no mouse +// else number of buttons +int mouse_init(int enable_cyberman) +{ + dpmi_real_regs rr; + cyberman_info *ci; +#ifndef __DJGPP__ + struct SREGS sregs; +#endif + union REGS inregs, outregs; + ubyte *Mouse_dos_mem; + + if (Mouse_installed) + return Mouse.num_buttons; + +#ifdef __DJGPP__ + if (_farpeekl(_dos_ds, 0x33 * 4) == 0) { +#else + if (_dos_getvect(0x33) == NULL) { +#endif + // No mouse driver loaded + return 0; + } + + // Reset the mouse driver + memset( &inregs, 0, sizeof(inregs) ); + inregs.w.ax = 0; + int386(0x33, &inregs, &outregs); + if (outregs.w.ax != 0xffff) + return 0; + + Mouse.num_buttons = outregs.w.bx; + Mouse.cyberman = 0; + + // Enable mouse driver + memset( &inregs, 0, sizeof(inregs) ); + inregs.w.ax = 0x0020; + int386(0x33, &inregs, &outregs); + if (outregs.w.ax != 0xffff ) + return 0; + + if ( enable_cyberman ) { + Mouse_dos_mem = dpmi_get_temp_low_buffer( 64 ); + if (Mouse_dos_mem==NULL) { + printf( "Unable to allocate DOS buffer in mouse.c\n" ); + } else { + // Check for Cyberman... + memset( &rr, 0, sizeof(dpmi_real_regs) ); + rr.es = DPMI_real_segment(Mouse_dos_mem); + rr.edx = DPMI_real_offset(Mouse_dos_mem); + rr.eax = 0x53c1; + dpmi_real_int386x( 0x33, &rr ); + if (rr.eax==1) { + // SWIFT functions supported + ci = (cyberman_info *)Mouse_dos_mem; + if (ci->device_type==1) { // Cyberman + Mouse.cyberman = 1; + //printf( "Cyberman mouse detected\n" ); + Mouse.num_buttons = 11; + } + } + } + } + + if (!dpmi_lock_region(&Mouse,sizeof(mouse_info))) { + printf( "Unable to lock mouse data region" ); + exit(1); + } + if (!dpmi_lock_region((void near *)mouse_handler,(char *)mouse_handler_end - (char near *)mouse_handler)) { + printf( "Unable to lock mouse handler" ); + exit(1); + } + + // Install mouse handler +#ifdef __DJGPP__ + { + dpmi_real_regs rregs; + _go32_dpmi_seginfo info; + memset(&rregs, 0, sizeof(rregs)); + info.pm_offset = (unsigned int)&mouse_handler; + if (_go32_dpmi_allocate_real_mode_callback_retf(&info, &handler_regs)) { + printf( "Unable allocate mouse handler callback" ); + exit(1); + } + rregs.eax = 0xC; + rregs.ecx = ME_LB_P|ME_LB_R|ME_RB_P|ME_RB_R|ME_MB_P|ME_MB_R; // watch all 3 button ups/downs + if (Mouse.cyberman) + rregs.ecx |= ME_Z_C| ME_P_C| ME_B_C| ME_H_C; // if using a cyberman, also watch z, pitch, bank, heading. + rregs.edx = info.rm_offset; + rregs.es = info.rm_segment; + dpmi_real_int386x( 0x33, &rregs ); + } +#else + memset( &inregs, 0, sizeof(inregs)); + memset( &sregs, 0, sizeof(sregs)); + inregs.w.ax = 0xC; + inregs.w.cx = ME_LB_P|ME_LB_R|ME_RB_P|ME_RB_R|ME_MB_P|ME_MB_R; // watch all 3 button ups/downs + if (Mouse.cyberman) + inregs.w.cx |= ME_Z_C| ME_P_C| ME_B_C| ME_H_C; // if using a cyberman, also watch z, pitch, bank, heading. + inregs.x.edx = FP_OFF(mouse_handler); + sregs.es = FP_SEG(mouse_handler); + int386x(0x33, &inregs, &outregs, &sregs); +#endif + + Mouse_installed = 1; + + atexit( mouse_close ); + + mouse_flush(); + + return Mouse.num_buttons; +} + + + +void mouse_close() +{ + struct SREGS sregs; + union REGS inregs, outregs; + + if (Mouse_installed) { + Mouse_installed = 0; + // clear mouse handler by setting flags to 0. + memset( &inregs, 0, sizeof(inregs)); + memset( &sregs, 0, sizeof(sregs)); + inregs.w.ax = 0xC; + inregs.w.cx = 0; // disable event handler by setting to zero. + inregs.x.edx = 0; + sregs.es = 0; + int386x(0x33, &inregs, &outregs, &sregs); + } +} + + +void mouse_set_limits( int x1, int y1, int x2, int y2 ) +{ + union REGS inregs, outregs; + + if (!Mouse_installed) return; + + memset( &inregs, 0, sizeof(inregs)); + inregs.w.ax = 0x7; // Set Horizontal Limits for Pointer + inregs.w.cx = x1; + inregs.w.dx = x2; + int386(0x33, &inregs, &outregs); + + memset( &inregs, 0, sizeof(inregs)); + inregs.w.ax = 0x8; // Set Vertical Limits for Pointer + inregs.w.cx = y1; + inregs.w.dx = y2; + int386(0x33, &inregs, &outregs); +} + +void mouse_get_pos( int *x, int *y) +{ + union REGS inregs, outregs; + + if (!Mouse_installed) { + *x = *y = 0; + return; + } + memset( &inregs, 0, sizeof(inregs)); + inregs.w.ax = 0x3; // Get Mouse Position and Button Status + int386(0x33, &inregs, &outregs); + *x = (short)outregs.w.cx; + *y = (short)outregs.w.dx; +} + +void mouse_get_delta( int *dx, int *dy ) +{ + union REGS inregs, outregs; + + if (!Mouse_installed) { + *dx = *dy = 0; + return; + } + + memset( &inregs, 0, sizeof(inregs)); + inregs.w.ax = 0xb; // Read Mouse motion counters + int386(0x33, &inregs, &outregs); + *dx = (short)outregs.w.cx; + *dy = (short)outregs.w.dx; +} + +int mouse_get_btns() +{ + int i; + uint flag=1; + int status = 0; + + if (!Mouse_installed) + return 0; + + for (i=0; ix+8128)*256)/(8064+8128+1)) - 127; + *y = (((ei->y+8128)*256)/(8064+8128+1)) - 127; +} + diff --git a/arch/dos/serial.c b/arch/dos/serial.c new file mode 100644 index 00000000..e1e18951 --- /dev/null +++ b/arch/dos/serial.c @@ -0,0 +1,21 @@ +// dummy serial code because of linux serial stuff +#include "serial.h" + +void com_write(char *buffer, int len) +{ +} + +int com_read(char *buffer, int len, int timeout_value) +{ + return 0; +} + +int com_getdcd() +{ + return 0; +} + +int com_readline(int timeout, char *input_buffer, int len) +{ + return 0; +} diff --git a/arch/dos/sgrep.out b/arch/dos/sgrep.out new file mode 100644 index 00000000..83df7b91 --- /dev/null +++ b/arch/dos/sgrep.out @@ -0,0 +1,3 @@ +SGREP 2.8 (c) Copyright 1991,92,93 - California Software Design +Searching for [BCD.C] +SGREP 2.8 (c) Copyright 1991,92,93 - California Software Design diff --git a/arch/dos/timer.asm b/arch/dos/timer.asm new file mode 100644 index 00000000..e738fe61 --- /dev/null +++ b/arch/dos/timer.asm @@ -0,0 +1,496 @@ +[BITS 32] + +[EXTERN _atexit] +[EXTERN ___djgpp_base_address] + +[GLOBAL _timer_get_fixed_seconds] +[GLOBAL _timer_get_fixed_secondsX] +[GLOBAL _timer_get_approx_seconds] +[GLOBAL _timer_set_rate] +[GLOBAL _timer_set_function] +[GLOBAL _timer_set_joyhandler] +[GLOBAL _timer_init] +[GLOBAL _timer_close] + + +[SECTION .data] +TDATA EQU 40h +TCOMMAND EQU 43h +PIC EQU 020h +STACK_SIZE EQU 4096 + +%define df times 3 dw + +TimerData db 0 + dd 0 + dd 65536 + dd 0 + dd 0 + df 0 + df 0 + df 0 + df 0 + dd 0 + db 0 +times STACK_SIZE db 0 + +td_in_timer equ TimerData +td_nested_counter equ td_in_timer+1 +td__timer_cnt equ td_nested_counter+4 +td_dos_timer equ td__timer_cnt+4 +td_joystick_poller equ td_dos_timer+4 +td_user_function equ td_joystick_poller+4 +td_org_interrupt equ td_user_function+6 +td_saved_stack equ td_org_interrupt+6 +td_new_stack equ td_saved_stack+6 +td_tick_count equ td_new_stack+6 +td_Installed equ td_tick_count+4 +td_TimerStack equ td_Installed+1 + + +[SECTION .text] + +TIMER_LOCKED_CODE_START: + +__my_ds dw 0 + +timer_get_stamp64: +; Return a 64-bit stamp that is the number of 1.19Mhz pulses +; since the time was initialized. Returns in EDX:EAX. +; Also, interrupts must be disabled. + + xor eax, eax ; Clear all of EAX + out TCOMMAND, al ; Tell timer to latch + + mov al, 0ah ; Find if interrupt pending + out PIC, al + jmp @ + @: + in al, PIC + and eax, 01b + jz NoInterrupt + + in al, TDATA ; Read in lo byte + mov dl, al + in al, TDATA ; Read in hi byte + mov dh, al + and edx, 0ffffh + mov eax, [td__timer_cnt] + shl eax, 1 + sub eax, edx + + push ebx + mov ebx, eax + mov eax, [td_tick_count] + imul dword [td__timer_cnt] ; edx:eax = Number of 1.19 MHz ticks elapsed... + add eax, ebx + adc edx, 0 + pop ebx + + ret + +NoInterrupt: + in al, TDATA ; Read in lo byte + mov ah, al + in al, TDATA ; Read in hi byte + xchg ah, al ; arrange em correctly + mov edx, [td__timer_cnt] + sub dx, ax ; BX = timer ticks + mov ax, dx + + push ebx + mov ebx, eax + mov eax, [td_tick_count] + imul dword [td__timer_cnt] ; edx:eax = Number of 1.19 MHz ticks elapsed... + add eax, ebx + adc edx, 0 + pop ebx + + ret + + +_timer_get_fixed_seconds: + push ebx + push edx + + cli + call timer_get_stamp64 + sti + +; Timing in fixed point (16.16) seconds. +; Can be used for up to 1000 hours + shld edx, eax, 16 ; Keep 32+11 bits + shl eax, 16 +; edx:eax = number of 1.19Mhz pulses elapsed. + mov ebx, 1193180 + +; Make sure we won't divide overflow. Make time wrap at about 9 hours +sub_again: + sub edx, ebx ; subtract until negative... + jns sub_again ; ...to prevent divide overflow... + add edx, ebx ; ...then add in to get correct value. + div ebx +; eax = fixed point seconds elapsed... + + pop edx + pop ebx + + ret + + +_timer_get_fixed_secondsX: + push ebx + push edx + + call timer_get_stamp64 + +; Timing in fixed point (16.16) seconds. +; Can be used for up to 1000 hours + shld edx, eax, 16 ; Keep 32+11 bits + shl eax, 16 +; edx:eax = number of 1.19Mhz pulses elapsed. + mov ebx, 1193180 + +xsub_again: + sub edx, ebx ; subtract until negative... + jns xsub_again ; ...to prevent divide overflow... + add edx, ebx ; ...then add in to get correct value. + + div ebx +; eax = fixed point seconds elapsed... + + pop edx + pop ebx + + ret + +_timer_get_approx_seconds: + push ebx + push edx + + mov eax, [td_tick_count] + imul dword [td__timer_cnt] ; edx:eax = Number of 1.19 MHz ticks elapsed... + shld edx, eax, 16 ; Keep 32+16 bits, for conversion to fixed point + shl eax, 16 +; edx:eax = number of 1.19Mhz pulses elapsed. + mov ebx, 1193180 + +approx_sub_again: + sub edx, ebx ; subtract until negative... + jns approx_sub_again ; ...to prevent divide overflow... + add edx, ebx ; ...then add in to get correct value. + + div ebx +; eax = fixed point seconds elapsed... + + pop edx + pop ebx + ret + +;---------------------------------------------------------------------------- +;Prototype: extern void timer_set_rate(int count_val); +;---------------------------------------------------------------------------- +_timer_set_rate: + mov eax,[esp+4] +; eax = rate + pushad + +; Make sure eax below or equal to 65535 and above 0 +; if its not, make it be 65536 which is normal dos +; timing. + cmp eax, 65535 + jbe @@ + mov eax, 65536 +@@: + cmp eax, 0 + jne @@@ + mov eax, 65536 +@@@: ; Set the timer rate to eax + cli + mov dword [td_tick_count], 0 + mov [td__timer_cnt], eax + mov al, 34h ; count in binary, mode 2, load low byte then hi byte, counter 0: 00 11 010 0 + out TCOMMAND, al ; Reset PIT channel 0 + mov eax, [td__timer_cnt] + out TDATA, al + mov al, ah + out TDATA, al + sti + popad + ret + +;---------------------------------------------------------------------------- +;Prototype: extern void timer_set_function( void * function ); +;---------------------------------------------------------------------------- +_timer_set_function: +; arg1 = near pointer to user function + push eax + mov eax, [esp+8] ; arg 1 + cli + mov dword [td_user_function+0], eax ; offset + mov word [td_user_function+4], cs ; selector + sti + pop eax + ret + +_timer_set_joyhandler: + mov eax, [esp+4] + cli + mov dword [td_joystick_poller], eax + sti + ret + +;************************************************************************ +;************************************************************************ +;***** ***** +;***** T I M E R _ H A N D L E R ***** +;***** ***** +;************************************************************************ +;************************************************************************ + +timer_handler: + push ds + push es + push eax + + mov ax, [cs:__my_ds] ; Interrupt, so point to our data segment + mov ds, ax + mov es, ax + +; Increment time counter... + inc dword [td_tick_count] + + mov eax, [td__timer_cnt] + add dword [td_dos_timer], eax ; Increment DOS timer + cmp dword [td_dos_timer], 65536 + jb NoChainToOld ; See if we need to chain to DOS 18.2 + and dword [td_dos_timer], 0ffffh + +; +; Call the original DOS handler.... +; + pushfd + call far dword [td_org_interrupt] + + jmp NoReset ;old handler has reset, so we don't + +NoChainToOld: +; Reset controller + mov al, 20h ; Reset interrupt controller + out 20h, al + +NoReset: + cmp byte [td_in_timer], 0 + jne ExitInterrupt + + mov byte [td_in_timer], 1 ; Mark that we're in a timer interrupt... + + ; Reenable interrupts + sti ; Reenable interrupts + + cmp word [td_user_function+4], 0 ; Check the selector... + je NoUserFunction + +; Switch stacks while calling the user-definable function... + pushad + push fs + push gs + mov dword [td_saved_stack+0], esp + mov word [td_saved_stack+4], ss + lss esp, [td_new_stack] ; Switch to new stack + call far dword [td_user_function] ; Call new function + lss esp, [td_saved_stack] ; Switch back to original stack + pop gs + pop fs + popad + +NoUserFunction: + cmp dword [td_joystick_poller], 0 + je NoJoyPolling + mov eax, [td__timer_cnt] + mov dword [td_saved_stack+0], esp + mov word [td_saved_stack+4], ss + lss esp, [td_new_stack] ; Switch to new stack + pusha + push eax + call dword [td_joystick_poller] + pop eax + popa + lss esp, [td_saved_stack] ; Switch back to original stack + +NoJoyPolling: + cli + mov byte [td_in_timer], 0 + +ExitInterrupt: +;;mov al, 20h ; Reset interrupt controller +;;out 20h, al + pop eax + pop es + pop ds + iretd ; Return from timer interrupt + +TIMER_LOCKED_CODE_STOP: + +;************************************************************************ +;************************************************************************ +;***** ***** +;***** T I M E R _ I N I T ***** +;***** ***** +;************************************************************************ +;************************************************************************ + +_timer_init: + pushad + push ds + push es + + cmp byte [td_Installed], 1 + je NEAR AlreadyInstalled + + mov [__my_ds],ds + + mov dword [td__timer_cnt], 65536 ; Set to BIOS's normal 18.2 Hz + mov dword [td_dos_timer], 0 ; clear DOS Interrupt counter + mov dword [td_user_function+0], 0 ; offset of user function + mov word [td_user_function+4], 0 ; selector of user function + + lea eax, [ds:td_TimerStack] ; Use EAX as temp stack pointer + add eax, STACK_SIZE ; Top of stack minus space for saving old ss:esp + mov dword [td_new_stack+0], eax + mov word [td_new_stack+4], ds + + ;--------------- lock data used in interrupt + mov eax, (td_TimerStack-TimerData)+STACK_SIZE ;sizeof timer_data + mov esi, eax + shr esi, 16 + mov edi, eax + and edi, 0ffffh ; si:di = length of region to lock in bytes + mov ebx, TimerData + add ebx, [___djgpp_base_address] + mov ecx, ebx + shr ebx, 16 + and ecx, 0ffffh ; bx:cx = start of linear address to lock + mov eax, 0600h ; DPMI lock address function + int 31h ; call dpmi + jnc @@@@ + int 3 ; LOCK FAILED!! +@@@@: + ;--------------- lock code used in interrupt + mov eax, TIMER_LOCKED_CODE_STOP + sub eax, TIMER_LOCKED_CODE_START + inc eax ; EAX = size of timer interrupt handler + mov esi, eax + shr esi, 16 + mov edi, eax + and edi, 0ffffh ; si:di = length of region to lock in bytes + mov ebx, TIMER_LOCKED_CODE_START + add ebx, [___djgpp_base_address] + mov ecx, ebx + shr ebx, 16 + and ecx, 0ffffh ; bx:cx = start of linear address to lock + mov eax, 0600h ; DPMI lock address function + int 31h ; call dpmi + jnc @@@@@ ;This is getting fun + int 3 ; LOCK FAILED!! +@@@@@: + +;************************************************************** +;******************* SAVE OLD INT8 HANDLER ******************** +;************************************************************** + mov ax,0204h + mov bl,8 + int 31h + mov dword [td_org_interrupt+0],edx + mov word [td_org_interrupt+4],cx + +;************************************************************** +;***************** INSTALL NEW INT8 HANDLER ******************* +;************************************************************** + + cli + + mov al, 34h ; count in binary, mode 2, load low byte then hi byte, counter 0: 00 11 010 0 + out TCOMMAND, al ; Reset PIT channel 0 + mov eax, [td__timer_cnt] + out TDATA, al + mov al, ah + out TDATA, al + + mov dword [td_tick_count], 0 + mov byte [td_Installed],1 + + mov ax,0205h + mov bl,8 + mov edx,timer_handler + mov cx,cs + int 31h + + + sti + push dword _timer_close + call _atexit + add esp,4 + +AlreadyInstalled: + + pop es + pop ds + popad + + ret + +;************************************************************************ +;************************************************************************ +;***** ***** +;***** T I M E R _ C L O S E _ ***** +;***** ***** +;************************************************************************ +;************************************************************************ + +_timer_close: + push eax + push ebx + push ecx + push edx + + cmp byte [td_Installed], 0 + je NotInstalled + mov byte [td_Installed], 0 + +;************************************************************** +;***************** RESTORE OLD INT8 HANDLER ******************* +;************************************************************** + + cli + mov al, 36h ; count in binary, mode 3, load low byte then hi byte, counter 0: 00 11 011 0 + out TCOMMAND, al ; Reser PIT channel 0 + mov ax, 0h + out TDATA, al + mov al, ah + out TDATA, al + + mov ax,0205h + mov bl,8 + mov edx,dword [td_org_interrupt+0] + mov cx,word [td_org_interrupt+4] + int 31h + + sti + + cmp dword [td_nested_counter], 0 + je NoNestedInterrupts + mov eax, [td_nested_counter] + ;int 3 ; Get John!! + +NoNestedInterrupts: + + +NotInstalled: + pop edx + pop ecx + pop ebx + pop eax + + ret + diff --git a/arch/dos/tweak.inc b/arch/dos/tweak.inc new file mode 100644 index 00000000..4c7222dc --- /dev/null +++ b/arch/dos/tweak.inc @@ -0,0 +1,258 @@ +;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +;SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +;IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +;FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +; +; $Source: /cvs/cvsroot/d2x/arch/dos/tweak.inc,v $ +; $Revision: 1.1.1.1 $ +; $Author: bradleyb $ +; $Date: 2001-01-19 03:30:15 $ +; +; Parameters used by modex.asm to set various modex resolutions. +; +; $Log: not supported by cvs2svn $ +; Revision 1.1.1.1 1999/06/14 21:58:45 donut +; Import of d1x 1.37 source. +; +; Revision 1.3 1993/11/16 11:28:09 john +; *** empty log message *** +; +; Revision 1.2 1993/10/15 16:23:18 john +; y +; +; Revision 1.1 1993/09/08 11:41:09 john +; Initial revision +; +; +; + + +; Mode X CRTC register tweaks for various resolutions + +X320Y200 db 00 ; 0e3h ; dot clock + db 02 ; Number of CRTC Registers to update + dw 00014h ; turn off dword mode + dw 0e317h ; turn on byte mode + dw 320 ; width + dw 200 ; height + +X320Y240 db 0e3h ; dot clock + db 10 ; Number of CRTC Registers to update + dw 00d06h ; vertical total + dw 03e07h ; overflow (bit 8 of vertical counts) + dw 04109h ; cell height (2 to double-scan) + dw 0ea10h ; v sync start + dw 0ac11h ; v sync end and protect cr0-cr7 + dw 0df12h ; vertical displayed + dw 00014h ; turn off dword mode + dw 0e715h ; v blank start + dw 00616h ; v blank end + dw 0e317h ; turn on byte mode + dw 320 ; width + dw 240 ; height + +X360Y200 db 0e7h ; dot clock + db 08 ; Number of CRTC Registers to update + dw 06b00h ; horz total + dw 05901h ; horz displayed + dw 05a02h ; start horz blanking + dw 08e03h ; end horz blanking + dw 05e04h ; start h sync + dw 08a05h ; end h sync + dw 00014h ; turn off dword mode + dw 0e317h ; turn on byte mode + dw 360 ; width + dw 200 ; height + + +X360Y240 db 0e7h ; dot clock + db 17 ; Number of CRTC Registers to update + dw 06b00h ; horz total + dw 05901h ; horz displayed + dw 05a02h ; start horz blanking + dw 08e03h ; end horz blanking + dw 05e04h ; start h sync + dw 08a05h ; end h sync + dw 00d06h ; vertical total + dw 03e07h ; overflow (bit 8 of vertical counts) + dw 04109h ; cell height (2 to double-scan) + dw 0ea10h ; v sync start + dw 0ac11h ; v sync end and protect cr0-cr7 + dw 0df12h ; vertical displayed + dw 02d13h ; offset; + dw 00014h ; turn off dword mode + dw 0e715h ; v blank start + dw 00616h ; v blank end + dw 0e317h ; turn on byte mode + dw 360 + dw 240 + +X376Y282 db 0e7h + db 18 + dw 06e00h ; horz total + dw 05d01h ; horz displayed + dw 05e02h ; start horz blanking + dw 09103h ; end horz blanking + dw 06204h ; start h sync + dw 08f05h ; end h sync + dw 06206h ; vertical total + dw 0f007h ; overflow + dw 06109h ; cell height + dw 0310fh ; + dw 03710h ; v sync start + dw 08911h ; v sync end and protect cr0-cr7 + dw 03312h ; vertical displayed + dw 02f13h ; offset + dw 00014h ; turn off dword mode + dw 03c15h ; v blank start + dw 05c16h ; v blank end + dw 0eb17h ; turn on byte mode + dw 376 + dw 282 + + +X320Y400 db 0h ; dot clock + db 03 ; Number of CRTC Registers to update + dw 04009h ; cell height + dw 00014h ; turn off dword mode + dw 0e317h ; turn on byte mode + dw 320 ; width + dw 400 ; height + +X320Y480 db 0e3h ; dotclock + db 10 ; Number of CRTC Registers to update + dw 00d06h ; vertical total + dw 03e07h ; overflow (bit 8 of vertical counts) + dw 04009h ; cell height (2 to double-scan) + dw 0ea10h ; v sync start + dw 0ac11h ; v sync end and protect cr0-cr7 + dw 0df12h ; vertical displayed + dw 00014h ; turn off dword mode + dw 0e715h ; v blank start + dw 00616h ; v blank end + dw 0e317h ; turn on byte mode + dw 320 ; width + dw 480 ; height + +X360Y400 db 0e7h ; dot clock + db 09 ; Number of CRTC Registers to update + dw 06b00h ; horz total + dw 05901h ; horz displayed + dw 05a02h ; start horz blanking + dw 08e03h ; end horz blanking + dw 05e04h ; start h sync + dw 08a05h ; end h sync + dw 04009h ; cell height + dw 00014h ; turn off dword mode + dw 0e317h ; turn on byte mode + dw 360 ; width + dw 400 ; height + +X360Y480 db 0e7h + db 17 + dw 06b00h ; horz total + dw 05901h ; horz displayed + dw 05a02h ; start horz blanking + dw 08e03h ; end horz blanking + dw 05e04h ; start h sync + dw 08a05h ; end h sync + dw 00d06h ; vertical total + dw 03e07h ; overflow + dw 04009h ; cell height + dw 0ea10h ; v sync start + dw 0ac11h ; v sync end and protect cr0-cr7 + dw 0df12h ; vertical displayed + dw 02d13h ; offset + dw 00014h ; turn off dword mode + dw 0e715h ; v blank start + dw 00616h ; v blank end + dw 0e317h ; turn on byte mode + dw 360 + dw 480 + +X360Y360 db 0e7h + db 15 + dw 06b00h ; horz total + dw 05901h ; horz displayed + dw 05a02h ; start horz blanking + dw 08e03h ; end horz blanking + dw 05e04h ; start h sync + dw 08a05h ; end h sync + dw 04009h ; cell height + dw 08810h ; v sync start + dw 08511h ; v sync end and protect cr0-cr7 + dw 06712h ; vertical displayed + dw 02d13h ; offset + dw 00014h ; turn off dword mode + dw 06d15h ; v blank start + dw 0ba16h ; v blank end + dw 0e317h ; turn on byte mode + dw 360 + dw 360 + +X376Y308 db 0e7h + db 18 + dw 06e00h ; horz total + dw 05d01h ; horz displayed + dw 05e02h ; start horz blanking + dw 09103h ; end horz blanking + dw 06204h ; start h sync + dw 08f05h ; end h sync + dw 06206h ; vertical total + dw 00f07h ; overflow + dw 04009h ; + dw 0310fh ; + dw 03710h ; v sync start + dw 08911h ; v sync end and protect cr0-cr7 + dw 03312h ; vertical displayed + dw 02f13h ; offset + dw 00014h ; turn off dword mode + dw 03c15h ; v blank start + dw 05c16h ; v blank end + dw 0e317h ; turn on byte mode + dw 376 + dw 308 + +X376Y564 db 0e7h + db 18 + dw 06e00h ; horz total + dw 05d01h ; horz displayed + dw 05e02h ; start horz blanking + dw 09103h ; end horz blanking + dw 06204h ; start h sync + dw 08f05h ; end h sync + dw 06206h ; vertical total + dw 0f007h ; overflow + dw 06009h ; + dw 0310fh ; + dw 03710h ; v sync start + dw 08911h ; v sync end and protect cr0-cr7 + dw 03312h ; vertical displayed + dw 02f13h ; offset + dw 00014h ; turn off dword mode + dw 03c15h ; v blank start + dw 05c16h ; v blank end + dw 0e317h ; turn on byte mode + dw 376 + dw 564 + +%define LAST_X_MODE 11 + +ModeTable dd X320Y200 + dd X320Y240 + dd X360Y200 + dd X360Y240 + dd X376Y282 + dd X320Y400 + dd X320Y480 + dd X360Y400 + dd X360Y480 + dd X360Y360 + dd X376Y308 + dd X376Y564 diff --git a/arch/dos/vesa.c b/arch/dos/vesa.c new file mode 100644 index 00000000..54791301 --- /dev/null +++ b/arch/dos/vesa.c @@ -0,0 +1,134 @@ +#include +#include "gr.h" +#include "grdef.h" +#include "u_dpmi.h" +#include "vesa.h" + +#define SC_INDEX 0x3c4 +#define CRTC_INDEX 0x3d4 +#define CRTC_DATA 0x3d5 + +static int bankshift; +static int lastbank; + +/* this comes from Allegro */ +typedef struct vesa_mode_info +{ + unsigned short ModeAttributes; + unsigned char WinAAttributes; + unsigned char WinBAttributes; + unsigned short WinGranularity; + unsigned short WinSize; + unsigned short WinASegment; + unsigned short WinBSegment; + unsigned long WinFuncPtr; + unsigned short BytesPerScanLine; + unsigned short XResolution; + unsigned short YResolution; + unsigned char XCharSize; + unsigned char YCharSize; + unsigned char NumberOfPlanes; + unsigned char BitsPerPixel; + unsigned char NumberOfBanks; + unsigned char MemoryModel; + unsigned char BankSize; + unsigned char NumberOfImagePages; + unsigned char Reserved_page; + unsigned char RedMaskSize; + unsigned char RedMaskPos; + unsigned char GreenMaskSize; + unsigned char GreenMaskPos; + unsigned char BlueMaskSize; + unsigned char BlueMaskPos; + unsigned char ReservedMaskSize; + unsigned char ReservedMaskPos; + unsigned char DirectColorModeInfo; + unsigned long PhysBasePtr; + unsigned long OffScreenMemOffset; + unsigned short OffScreenMemSize; + unsigned char Reserved[206]; +} __attribute__ ((packed)) vesa_mode_info; + + +int gr_vesa_checkmode(int mode) { + int i; + dpmi_real_regs rregs; + vesa_mode_info *mode_info; + + if (!(mode_info = dpmi_get_temp_low_buffer( 1024 ))) + return 7; + rregs.eax = 0x4f01; + rregs.ecx = mode; + rregs.edi = DPMI_real_offset(mode_info); + rregs.es = DPMI_real_segment(mode_info); + dpmi_real_int386x( 0x10, &rregs ); + if (rregs.eax != 0x4f) + return 5; /* no vesa */ + if (!(mode_info->ModeAttributes & 1)) + return 4; /* unsupported mode */ + + bankshift = 0; + i = mode_info->WinGranularity; + while (i < 64) { + i <<= 1; + bankshift++; + } + if (i != 64) + return 2; /* incompatible window granularity */ + return 0; +} + +int gr_vesa_setmode(int mode) { + int ret; + lastbank = -1; + if ((ret = gr_vesa_checkmode(mode))) + return ret; + asm volatile("int $0x10" : "=a" (ret) : "a" (0x4f02), "b" (mode)); + return (ret == 0x4f) ? 0 : 4; +} + +inline void gr_vesa_setpage(int bank) { + if (bank != lastbank) + asm volatile("int $0x10" + : : "a" (0x4f05), "b" (0), "d" ((lastbank = bank) << bankshift) + : "%eax"); +} + +void gr_vesa_incpage() { + gr_vesa_setpage(lastbank + 1); +} + +void gr_vesa_setstart(int col, int row) { + asm volatile("int $0x10" + : : "a" (0x4f07), "b" (0), "c" (col), "d" (row) : "%eax"); +} + +int gr_vesa_setlogical(int line_width) { + int ret; + asm volatile("int $0x10" + : "=c" (ret) : "a" (0x4f07), "b" (0), "c" (line_width) : "%eax"); + return ret; +} + +void gr_vesa_scanline(int x1, int x2, int y, unsigned char color) { + int addr = (y * gr_var_bwidth) + x1; + int left = x2 - x1 + 1; + gr_vesa_setpage(addr >> 16); + addr &= 0xffff; + while (left) { + if (left > (65536 - addr)) { + left -= (65536 - addr); + memset(gr_video_memory + addr, color, 65536 - addr); + addr = 0; + gr_vesa_incpage(); + } else { + memset(gr_video_memory + addr, color, left); + left = 0; + } + } +} + +void gr_vesa_pixel(unsigned char color, unsigned int addr) { + gr_vesa_setpage(addr >> 16); + gr_video_memory[addr & 0xffff] = color; +} diff --git a/arch/dos/vgaregs.inc b/arch/dos/vgaregs.inc new file mode 100644 index 00000000..fd9f66e4 --- /dev/null +++ b/arch/dos/vgaregs.inc @@ -0,0 +1,62 @@ +;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +;SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +;IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +;FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +; +; $Source: /cvs/cvsroot/d2x/arch/dos/vgaregs.inc,v $ +; $Revision: 1.1.1.1 $ +; $Author: bradleyb $ +; $Date: 2001-01-19 03:30:15 $ +; +; Readable descriptions of VGA ports. +; +; $Log: not supported by cvs2svn $ +; Revision 1.1.1.1 1999/06/14 21:58:45 donut +; Import of d1x 1.37 source. +; +; Revision 1.2 1993/10/15 16:22:45 john +; *** empty log message *** +; +; Revision 1.1 1993/09/08 11:41:00 john +; Initial revision +; +; +; + + +%define MISC_OUTPUT 03c2h ;Miscellaneous Output register +%define MAP_MASK 02h ;index in SC of Map Mask register +%define READ_MAP 04h ;index in GC of the Read Map register +%define BIT_MASK 08h ;index in GC of Bit Mask register + +%define SC_INDEX 3c4h ;Index register for sequencer ctrl. +%define SC_MAP_MASK 2 ;Number of map mask register + +%define SC_INDEX 3c4h ;Index register for sequencer ctrl. +%define SC_MAP_MASK 2 ;Number of map mask register +%define SC_MEM_MODE 4 ;Number of memory mode register + +%define GC_INDEX 3ceh ;Index register for graphics ctrl. +%define GC_READ_MAP 4 ;Number of read map register +%define GC_GRAPH_MODE 5 ;Number of graphics mode register +%define GC_MISCELL 6 ;Number of miscellaneous register + +%define CRTC_INDEX 3d4h ;Index register for CRT controller +%define CC_MAX_SCAN 9 ;Number of maximum scan line reg. +%define CC_START_HI 0Ch ;Number of start address high register +%define CC_START_LO 0Dh ;Number of start address low register +%define CC_UNDERLINE 14h ;Number of underline register +%define CC_MODE_CTRL 17h ;Number of mode control register +%define CRTC_OFFSET 13h ; CRTC offset register index + +%define DAC_WRITE_ADR 3C8h ;DAC write address +%define DAC_READ_ADR 3C7h ;DAC read address +%define DAC_DATA 3C9h ;DAC data register + +%define VERT_RESCAN 3DAh ;Input status register #1 diff --git a/arch/linux/Makefile.am b/arch/linux/Makefile.am new file mode 100644 index 00000000..c0749e0f --- /dev/null +++ b/arch/linux/Makefile.am @@ -0,0 +1,6 @@ +noinst_LIBRARIES = libarchlinux.a +INCLUDES = -I $(top_srcdir)/includes -I../../input/sdl/include -I../../input/linux/include -I $(top_srcdir)/main -Iinclude + +libarchlinux_a_SOURCES = \ +init.c ipx_lin.c \ +ipx_bsd.c ipx_udp.c linuxnet.c findfile.c diff --git a/arch/linux/Makefile.in b/arch/linux/Makefile.in new file mode 100644 index 00000000..66efad5d --- /dev/null +++ b/arch/linux/Makefile.in @@ -0,0 +1,302 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +CFLAGS = @CFLAGS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +NASM = @NASM@ +NASMFLAGS = @NASMFLAGS@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_LIBS = @SDL_LIBS@ +VERSION = @VERSION@ + +noinst_LIBRARIES = libarchlinux.a +INCLUDES = -I $(top_srcdir)/includes -I../../input/sdl/include -I../../input/linux/include -I $(top_srcdir)/main -Iinclude + +libarchlinux_a_SOURCES = init.c ipx_lin.c ipx_bsd.c ipx_udp.c linuxnet.c findfile.c + +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../../conf.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I../.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +libarchlinux_a_LIBADD = +libarchlinux_a_OBJECTS = init.o ipx_lin.o ipx_bsd.o ipx_udp.o \ +linuxnet.o findfile.o +AR = ar +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +DEP_FILES = .deps/findfile.P .deps/init.P .deps/ipx_bsd.P \ +.deps/ipx_lin.P .deps/ipx_udp.P .deps/linuxnet.P +SOURCES = $(libarchlinux_a_SOURCES) +OBJECTS = $(libarchlinux_a_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu arch/linux/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +libarchlinux.a: $(libarchlinux_a_OBJECTS) $(libarchlinux_a_DEPENDENCIES) + -rm -f libarchlinux.a + $(AR) cru libarchlinux.a $(libarchlinux_a_OBJECTS) $(libarchlinux_a_LIBADD) + $(RANLIB) libarchlinux.a + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = arch/linux + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu arch/linux/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile $(LIBRARIES) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ + mostlyclean-tags mostlyclean-depend mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \ + clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-noinstLIBRARIES distclean-compile \ + distclean-tags distclean-depend distclean-generic \ + clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/arch/linux/alsadigi.c b/arch/linux/alsadigi.c new file mode 100644 index 00000000..d68a80fe --- /dev/null +++ b/arch/linux/alsadigi.c @@ -0,0 +1,918 @@ +// ALSA digital audio support + +#include +#include +#include +#include +#include + +#include "error.h" +#include "mono.h" +#include "fix.h" +#include "vecmat.h" +#include "gr.h" // needed for piggy.h +#include "piggy.h" +#include "digi.h" +#include "sounds.h" +#include "wall.h" +#include "newdemo.h" +#include "kconfig.h" + +//edited 05/17/99 Matt Mueller - added ifndef NO_ASM +//added on 980905 by adb to add inline fixmul for mixer on i386 +#ifndef NO_ASM +#ifdef __i386__ +#define do_fixmul(x,y) \ +({ \ + int _ax, _dx; \ + asm("imull %2\n\tshrdl %3,%1,%0" \ + : "=a"(_ax), "=d"(_dx) \ + : "rm"(y), "i"(16), "0"(x)); \ + _ax; \ +}) +extern inline fix fixmul(fix x, fix y) { return do_fixmul(x,y); } +#endif +#endif +//end edit by adb +//end edit -MM + +//changed on 980905 by adb to increase number of concurrent sounds +#define MAX_SOUND_SLOTS 32 +//end changes by adb +#define SOUND_BUFFER_SIZE 512 + +#define MIN_VOLUME 10 + +/* This table is used to add two sound values together and pin + * the value to avoid overflow. (used with permission from ARDI) + * DPH: Taken from SDL/src/SDL_mixer.c. + */ +static const ubyte mix8[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, + 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, + 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, + 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, + 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, + 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, + 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, + 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, + 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, + 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, + 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, + 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, + 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, + 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +}; + +#define SOF_USED 1 // Set if this sample is used +#define SOF_PLAYING 2 // Set if this sample is playing on a channel +#define SOF_LINK_TO_OBJ 4 // Sound is linked to a moving object. If object dies, then finishes play and quits. +#define SOF_LINK_TO_POS 8 // Sound is linked to segment, pos +#define SOF_PLAY_FOREVER 16 // Play forever (or until level is stopped), otherwise plays once + +typedef struct sound_object { + short signature; // A unique signature to this sound + ubyte flags; // Used to tell if this slot is used and/or currently playing, and how long. + fix max_volume; // Max volume that this sound is playing at + fix max_distance; // The max distance that this sound can be heard at... + int volume; // Volume that this sound is playing at + int pan; // Pan value that this sound is playing at + int handle; // What handle this sound is playing on. Valid only if SOF_PLAYING is set. + short soundnum; // The sound number that is playing + union { + struct { + short segnum; // Used if SOF_LINK_TO_POS field is used + short sidenum; + vms_vector position; + }pos; + struct { + short objnum; // Used if SOF_LINK_TO_OBJ field is used + short objsignature; + }obj; + }link; +} sound_object; +#define lp_segnum link.pos.segnum +#define lp_sidenum link.pos.sidenum +#define lp_position link.pos.position + +#define lo_objnum link.obj.objnum +#define lo_objsignature link.obj.objsignature + +#define MAX_SOUND_OBJECTS 16 +sound_object SoundObjects[MAX_SOUND_OBJECTS]; +short next_signature=0; + +//added/changed on 980905 by adb to make sfx volume work, on 990221 by adb changed F1_0 to F1_0 / 2 +#define SOUND_MAX_VOLUME (F1_0 / 2) + +int digi_volume = SOUND_MAX_VOLUME; +//end edit by adb + +int digi_lomem = 0; + +static int digi_initialised = 0; + +struct sound_slot { + int soundno; + int playing; // Is there a sample playing on this channel? + int looped; // Play this sample looped? + fix pan; // 0 = far left, 1 = far right + fix volume; // 0 = nothing, 1 = fully on + //changed on 980905 by adb from char * to unsigned char * + unsigned char *samples; + //end changes by adb + unsigned int length; // Length of the sample + unsigned int position; // Position we are at at the moment. +} SoundSlots[MAX_SOUND_SLOTS]; + +static int digi_sounds_initialized = 0; + +//added on 980905 by adb to add rotating/volume based sound kill system +static int digi_max_channels = 16; +static int next_handle = 0; +int SampleHandles[32]; +void reset_sounds_on_channel(int channel); +//end edit by adb + +/* Threading/ALSA stuff */ +#define LOCK() pthread_mutex_lock(&mutex) +#define UNLOCK() pthread_mutex_unlock(&mutex) +void *snd_devhandle; +pthread_t thread_id; +pthread_mutex_t mutex; + + +void digi_reset_digi_sounds(void); + + +/* Audio mixing callback */ +//changed on 980905 by adb to cleanup, add pan support and optimize mixer +static void audio_mixcallback(void *userdata, ubyte *stream, int len) +{ + ubyte *streamend = stream + len; + struct sound_slot *sl; + + for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++) + { + if (sl->playing) + { + ubyte *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length; + ubyte *sp = stream; + signed char v; + fix vl, vr; + int x; + + if ((x = sl->pan) & 0x8000) + { + vl = 0x20000 - x * 2; + vr = 0x10000; + } + else + { + vl = 0x10000; + vr = x * 2; + } + vl = fixmul(vl, (x = sl->volume)); + vr = fixmul(vr, x); + while (sp < streamend) + { + if (sldata == slend) + { + if (!sl->looped) + { + sl->playing = 0; + break; + } + sldata = sl->samples; + } + v = *(sldata++) - 0x80; + *(sp++) = mix8[ *sp + fixmul(v, vl) + 0x80 ]; + *(sp++) = mix8[ *sp + fixmul(v, vr) + 0x80 ]; + } + sl->position = sldata - sl->samples; + } + } +} +//end changes by adb + +void *mixer_thread(void *data) { +// int i=0; + ubyte buffer[512]; + /* Allow ourselves to be asynchronously cancelled */ + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + while (1) { +// printf("i=%d\n",i++); + memset(buffer, 0x80, 512); + LOCK(); + audio_mixcallback(NULL,buffer,512); + UNLOCK(); + snd_pcm_write(snd_devhandle, buffer, 512); + } + return 0; +} + + +/* Initialise audio devices. */ +int digi_init() +{ + int card=0, device=0, err; + snd_pcm_format_t format; + snd_pcm_playback_params_t params; + pthread_attr_t attr; + pthread_mutexattr_t mutexattr; + + //added on 980905 by adb to init sound kill system + memset(SampleHandles, 255, sizeof(SampleHandles)); + //end edit by adb + + /* Open the ALSA sound device */ + if ((err = snd_pcm_open(&snd_devhandle, card, device, + SND_PCM_OPEN_PLAYBACK)) < 0) { + fprintf(stderr, "open failed: %s\n", snd_strerror( err )); + return -1; + } + + memset(&format, 0, sizeof(format)); + format.format = SND_PCM_SFMT_U8; + format.rate = 11025; + format.channels = 2; + if ((err = snd_pcm_playback_format(snd_devhandle, &format)) < 0) { + fprintf(stderr, "format setup failed: %s\n", snd_strerror( err )); + snd_pcm_close( snd_devhandle ); + return -1; + } + + memset(¶ms, 0, sizeof(params)); + params.fragment_size=512; + params.fragments_max=2; + params.fragments_room=1; + if ((err = snd_pcm_playback_params(snd_devhandle, ¶ms)) < 0) { + fprintf(stderr, "params setup failed: %s\n", snd_strerror( err )); + snd_pcm_close( snd_devhandle ); + return -1; + } + + /* Start the mixer thread */ + + /* We really should check the results of these */ + pthread_mutexattr_init(&mutexattr); + pthread_mutex_init(&mutex,&mutexattr); + pthread_mutexattr_destroy(&mutexattr); + + if (pthread_attr_init(&attr) != 0) { + fprintf(stderr, "failed to init attr\n"); + snd_pcm_close( snd_devhandle ); + return -1; + } + + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + pthread_create(&thread_id,&attr,mixer_thread,NULL); + pthread_attr_destroy(&attr); + + atexit(digi_close); + digi_initialised = 1; + return 0; +} + +/* Toggle audio */ +void digi_reset() { } + +/* Shut down audio */ +void digi_close() +{ + if (!digi_initialised) return; + digi_initialised = 0; + snd_pcm_close(snd_devhandle); + pthread_mutex_destroy(&mutex); + pthread_cancel(thread_id); +} + +/* Find the sound which actually equates to a sound number */ +int digi_xlat_sound(int soundno) +{ + if ( soundno < 0 ) return -1; + + if ( digi_lomem ) { + soundno = AltSounds[soundno]; + if ( soundno == 255 ) return -1; + } + return Sounds[soundno]; +} + +static int get_free_slot() +{ + int i; + for (i=0; i= 0) && (SoundSlots[SampleHandles[next_handle]].playing) ) + { + if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries= digi_max_channels ) + next_handle = 0; + ntries++; + goto TryNextChannel; + } + //mprintf(( 0, "[SS:%d]", next_handle )); + SoundSlots[SampleHandles[next_handle]].playing = 0; + SampleHandles[next_handle] = -1; + } + //end edit by adb + + slot = get_free_slot(); + if (slot<0) return -1; + + SoundSlots[slot].soundno = soundnum; + SoundSlots[slot].samples = GameSounds[soundnum].data; + SoundSlots[slot].length = GameSounds[soundnum].length; + SoundSlots[slot].volume = fixmul(digi_volume, volume); + SoundSlots[slot].pan = pan; + SoundSlots[slot].position = 0; + SoundSlots[slot].looped = 0; + SoundSlots[slot].playing = 1; + + //added on 980905 by adb to add sound kill system from original sos digi.c + reset_sounds_on_channel(slot); + SampleHandles[next_handle] = slot; + next_handle++; + if ( next_handle >= digi_max_channels ) + next_handle = 0; + //end edit by adb + UNLOCK(); + return slot; +} + + //added on 980905 by adb to add sound kill system from original sos digi.c +void reset_sounds_on_channel( int channel ) +{ + int i; + + for (i=0; i -1 ) { + *volume = max_volume - fixdiv(path_distance,max_distance); + //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume )); + if (*volume > 0 ) { + angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec); + fix_sincos(angle_from_ear,&sinang,&cosang); + //mprintf( (0, "volume is %.2f\n", f2fl(*volume) )); + if (Config_channels_reversed) cosang *= -1; + *pan = (cosang + F1_0)/2; + } else { + *volume = 0; + } + } + } +} + +int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance ) +{ + int i,volume,pan; + object * objp; + int soundnum; + + soundnum = digi_xlat_sound(org_soundnum); + + if ( max_volume < 0 ) return -1; +// if ( max_volume > F1_0 ) max_volume = F1_0; + + if (!digi_initialised) return -1; + if (soundnum < 0 ) return -1; + if (GameSounds[soundnum].data==NULL) { + Int3(); + return -1; + } + if ((objnum<0)||(objnum>Highest_object_index)) + return -1; + + if ( !forever ) { + // Hack to keep sounds from building up... + digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance ); + digi_play_sample_3d( org_soundnum, pan, volume, 0 ); + return -1; + } + + for (i=0; iorient, &Viewer->pos, Viewer->segnum, + &objp->pos, objp->segnum, SoundObjects[i].max_volume, + &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); + + if (!forever || SoundObjects[i].volume >= MIN_VOLUME) + digi_start_sound_object(i); + + return SoundObjects[i].signature; +} + +int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume ) +{ return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); } + +int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance ) +{ + int i, volume, pan; + int soundnum; + + soundnum = digi_xlat_sound(org_soundnum); + + if ( max_volume < 0 ) return -1; +// if ( max_volume > F1_0 ) max_volume = F1_0; + + if (!digi_initialised) return -1; + if (soundnum < 0 ) return -1; + if (GameSounds[soundnum].data==NULL) { + Int3(); + return -1; + } + + if ((segnum<0)||(segnum>Highest_segment_index)) + return -1; + + if ( !forever ) { + // Hack to keep sounds from building up... + digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance ); + digi_play_sample_3d( org_soundnum, pan, volume, 0 ); + return -1; + } + + for (i=0; iorient, &Viewer->pos, Viewer->segnum, + &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum, + SoundObjects[i].max_volume, + &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); + + if (!forever || SoundObjects[i].volume >= MIN_VOLUME) + digi_start_sound_object(i); + + return SoundObjects[i].signature; +} + +int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume ) +{ + return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 ); +} + +void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum ) +{ + int i,killed; + + soundnum = digi_xlat_sound(soundnum); + + if (!digi_initialised) return; + + killed = 0; + + for (i=0; i 1 ) { + mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum )); + } +} + +void digi_kill_sound_linked_to_object( int objnum ) +{ + int i,killed; + + if (!digi_initialised) return; + + killed = 0; + + for (i=0; i 1 ) { + mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum )); + } +} + +void digi_sync_sounds() +{ + int i; + int oldvolume, oldpan; + + if (!digi_initialised) return; + + for (i=0; iorient, &Viewer->pos, Viewer->segnum, + &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum, + SoundObjects[i].max_volume, + &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); + + } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) { + object * objp; + + objp = &Objects[SoundObjects[i].lo_objnum]; + + if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) { + // The object that this is linked to is dead, so just end this sound if it is looping. + if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) { + LOCK(); + SoundSlots[SoundObjects[i].handle].playing = 0; + UNLOCK(); + } + SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound + continue; // Go on to next sound... + } else { + digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, + &objp->pos, objp->segnum, SoundObjects[i].max_volume, + &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); + } + } + + if (oldvolume != SoundObjects[i].volume) { + if ( SoundObjects[i].volume < MIN_VOLUME ) { + // Sound is too far away, so stop it from playing. + if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) { + LOCK(); + SoundSlots[SoundObjects[i].handle].playing = 0; + UNLOCK(); + SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing + } + } else { + if (!(SoundObjects[i].flags & SOF_PLAYING)) { + digi_start_sound_object(i); + } else { + LOCK(); + SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0); + UNLOCK(); + } + } + } + + if (oldpan != SoundObjects[i].pan) { + if (SoundObjects[i].flags & SOF_PLAYING) { + LOCK(); + SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan; + UNLOCK(); + } + } + } + } +} + +void digi_init_sounds() +{ + int i; + + if (!digi_initialised) return; + + digi_reset_digi_sounds(); + + for (i=0; i SOUND_MAX_VOLUME ) + digi_volume = SOUND_MAX_VOLUME; + else if ( dvolume < 0 ) + digi_volume = 0; + else + digi_volume = dvolume; + + if ( !digi_initialised ) return; + + digi_sync_sounds(); +} +//end edit by adb + +void digi_set_volume( int dvolume, int mvolume ) { } + +int digi_is_sound_playing(int soundno) +{ + int i; + + soundno = digi_xlat_sound(soundno); + + LOCK(); + for (i = 0; i < MAX_SOUND_SLOTS; i++) + //changed on 980905 by adb: added SoundSlots[i].playing && + if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno) + //end changes by adb + { UNLOCK(); return 1; } + UNLOCK(); + return 0; +} + + +void digi_pause_all() { } +void digi_resume_all() { } +void digi_stop_all() { } + + //added on 980905 by adb to make sound channel setting work +void digi_set_max_channels(int n) { + digi_max_channels = n; + + if ( digi_max_channels < 1 ) + digi_max_channels = 1; + if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) ) + digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS); + + if ( !digi_initialised ) return; + + digi_reset_digi_sounds(); +} + +int digi_get_max_channels() { + return digi_max_channels; +} +// end edit by adb + +void digi_reset_digi_sounds() { + int i; + + LOCK(); + for (i=0; i< MAX_SOUND_SLOTS; i++) + SoundSlots[i].playing=0; + UNLOCK(); + + //added on 980905 by adb to reset sound kill system + memset(SampleHandles, 255, sizeof(SampleHandles)); + next_handle = 0; + //end edit by adb +} + + +// MIDI stuff follows. +//added/killed on 11/25/98 by Matthew Mueller +//void digi_set_midi_volume( int mvolume ) { } +//void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {} +//void digi_stop_current_song() +//{ +//#ifdef HMIPLAY +// char buf[10]; +// +// sprintf(buf,"s"); +// send_ipc(buf); +//#endif +//} +//end this section kill - MM diff --git a/arch/linux/findfile.c b/arch/linux/findfile.c new file mode 100644 index 00000000..70ab4edb --- /dev/null +++ b/arch/linux/findfile.c @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include "findfile.h" +#include "u_mem.h" +#include "error.h" + +/* KLUDGE ALERT: evil globals */ +static glob_t glob_a; +static int glob_whichfile; + +int FileFindFirst(char *search_str, FILEFINDSTRUCT *ffstruct) +{ + int r; + char *t; + + Assert(search_str != NULL); + Assert(ffstruct != NULL); + + r = glob(search_str, 0, NULL, &glob_a); + if (r == GLOB_NOMATCH) return -1; + + glob_whichfile = 0; + + t = strrchr(glob_a.gl_pathv[glob_whichfile], '/'); + if (t == NULL) t = glob_a.gl_pathv[glob_whichfile]; else t++; + strncpy(ffstruct->name, t, 255); + ffstruct->size = strlen(ffstruct->name); + + return 0; +} + +int FileFindNext(FILEFINDSTRUCT *ffstruct) +{ + char *t; + + glob_whichfile++; + + if (glob_whichfile >= glob_a.gl_pathc) return -1; + + t = strrchr(glob_a.gl_pathv[glob_whichfile], '/'); + if (t == NULL) t = glob_a.gl_pathv[glob_whichfile]; else t++; + strncpy(ffstruct->name, t, 255); + ffstruct->size = strlen(ffstruct->name); + return 0; +} + +int FileFindClose(void) +{ + globfree(&glob_a); + return 0; +} diff --git a/arch/linux/hmiplay.c b/arch/linux/hmiplay.c new file mode 100644 index 00000000..4002c1df --- /dev/null +++ b/arch/linux/hmiplay.c @@ -0,0 +1,773 @@ +/* HMI midi playing routines by Jani Frilander + * + * External device support by Patrick McCarthy + * + * Ported to d1x/sdl_threads by Matthew Mueller +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "music.h" +#include "cfile.h" + +#include + +//#define WANT_AWE32 1 + +#ifdef WANT_AWE32 +#include +#endif + +//#define WANT_MPU401 1 + +#ifdef WANT_MPU401 +#define MIDI_MESSAGE2(a,b) { \ + SEQ_MIDIOUT(synth_dev,a); \ + SEQ_MIDIOUT(synth_dev,b); \ +} + +#define MIDI_MESSAGE3(a,b,c) { \ + SEQ_MIDIOUT(synth_dev,a); \ + SEQ_MIDIOUT(synth_dev,b); \ + SEQ_MIDIOUT(synth_dev,c); \ +} +#endif + +SEQ_DEFINEBUF(1024); + +int drumflag = 1<<9; +int seqfd; +int synth_dev; +int program[16]; +int stop; +double volume=1; + +int ipc_queue_id = -1; +struct msgbuf *snd; + +SDL_Thread *player_thread=NULL; + +Voice_info *voices; +unsigned char *data=NULL; + +struct synth_info card_info; + +void seqbuf_dump() +{ + if (_seqbufptr) + { + if (write(seqfd, _seqbuf, _seqbufptr) == -1) + { + perror ("Error writing sequencer device"); + SDL_KillThread(player_thread); + } + } + _seqbufptr = 0; +} + +void my_quit() +{ +// printf("goodbye\n");//##### +// exit(0); +} + +int seq_init() +{ + int nrmidis,nrsynths,i; + + if ((seqfd = open(SEQ_DEV, O_WRONLY, 0)) < 0) + { + perror ("Error opening sequencer device"); + return (-1); + } + + if (ioctl(seqfd, SNDCTL_SEQ_NRSYNTHS, &nrsynths) == -1) + { + perror ("There is no soundcard"); + return (-1); + } + + if (ioctl(seqfd, SNDCTL_SEQ_NRMIDIS, &nrmidis) == -1) + { + perror ("There is no soundcard"); + return (-1); + } + + + if(nrsynths < 1 && nrmidis < 1) + { + printf("No synth or midi device!\n"); + return -1; + } + + synth_dev = 0; + + //Check if we have wavetable synth device + for (i=0; i < nrsynths; i++) + { + card_info.device = i; + if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1) + { + perror("cannot get info on soundcard"); + return (-1); + } + + if (card_info.synth_type == SYNTH_TYPE_SAMPLE) + { + synth_dev = i; + break; + } + } + +#ifdef WANT_AWE32 + for (i=0; i < nrsynths; i++) + { + card_info.device = i; + if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1) + { + perror("cannot get info on soundcard"); + return (-1); + } + + if (card_info.synth_type==SYNTH_TYPE_SAMPLE + &&card_info.synth_subtype==SAMPLE_TYPE_AWE32) { + synth_dev = i; + break; + } + } +#endif + +#ifdef WANT_MPU401 + for (i=0; i < nrmidis; i++) + { + struct midi_info cinfo; + cinfo.device = i; + if (ioctl(seqfd, SNDCTL_MIDI_INFO, &cinfo) == -1) + { + perror("cannot get info on soundcard"); + return (-1); + } + + // Just take first available for now. + card_info.synth_type=SYNTH_TYPE_MIDI; + card_info.device=i; + synth_dev=i; + break; + } + + if (card_info.synth_type!=SYNTH_TYPE_MIDI) { +#endif + + card_info.device = synth_dev; + if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1) + { + perror("cannot get info on soundcard"); + return (-1); + } + +#ifdef WANT_MPU401 + } + + if (card_info.synth_type==SYNTH_TYPE_MIDI) { + // Insert some sort of midi reset here later. + } else +#endif +#ifdef WANT_AWE32 + if (card_info.synth_type == SYNTH_TYPE_SAMPLE + && card_info.synth_subtype == SAMPLE_TYPE_AWE32) + { + AWE_SET_CHANNEL_MODE(synth_dev,1); + AWE_DRUM_CHANNELS(synth_dev,drumflag); + } + else +#endif + { + voices = malloc(sizeof(Voice_info)*card_info.nr_voices); + for (i=0;imtype=1; + player_thread=SDL_CreateThread(play_hmi, NULL); +// player_pid = play_hmi(); + } + if (strlen(message) < 16) + { + sprintf(snd->mtext,"%s",message); + msgsnd(ipc_queue_id,snd,16,0); + } +} + +void kill_ipc() +{ +// send_ipc("q"); +// kill(player_pid,SIGTERM); + msgctl( ipc_queue_id, IPC_RMID, 0); + free(snd); + ipc_queue_id = -1; +// player_pid = 0; +} + +int do_ipc(int qid, struct msgbuf *buf, int flags) +{ + int ipc_read; + CFILE *fptr; + int l=0; + + ipc_read = msgrcv(qid,buf,16,0,flags | MSG_NOERROR); + + switch (ipc_read) + { + case -1: + if (errno == ENOMSG) + break; + perror("IPC trouble"); + break; + case 0: + break; + default: + printf ("do_ipc %s\n", buf->mtext);//##########3 + switch (buf->mtext[0]) + { + case 'v': + volume=(double) ((double) buf->mtext[0]/127.0); + break; + case 'p': + fptr=cfopen((buf->mtext+1),"rb"); + if(fptr != NULL) + { + l = cfilelength(fptr); + data=realloc(data,(size_t) l); + cfread(data, l, 1, fptr); + cfclose(fptr); + printf ("good. fpr=%p l=%i data=%p\n", fptr, l, data);//##########3 + } + stop = 0; + break; + case 's': + stop = 2; + break; + case 'q': +// SDL_KillThread(player_thread); + break; + } + } + + return ipc_read; +} + +void play_hmi (void * arg) +{ + int i; + int pos = 0x308; + int n_chunks = 0; + int low_dtime; + int low_chunk; + int csec; +// pid_t loc_pid; + int qid; + int ipc_read = 0; + int k=0; + + struct msgbuf *rcv; + + Track_info *t_info; + + printf ("play_hmi\n");//######### + + stop = 0; + ipc_read=0; +// loc_pid=fork(); + +/* switch (loc_pid) + { + case 0: + break; + case -1: + return -1; + default: + atexit(kill_ipc); + return loc_pid; + }*/ + +// signal(SIGTERM, my_quit); + rcv=malloc(sizeof(long) + 16); + + rcv->mtype=1; + rcv->mtext[0]='0'; + + sleep(2); + + qid=msgget ((key_t) ('l'<<24) | ('d'<<16) | ('e'<<8) | 's', 0660); + if(qid == -1) + { + return; + } + + do + { + ipc_read=do_ipc(qid,rcv,0); + } + while(rcv->mtext[0] != 'p'); + + stop=0; + rcv->mtext[0] = '0'; + + seq_init(); + + n_chunks=data[0x30]; + + t_info = malloc(sizeof(Track_info)*n_chunks); + + while(1) + { + + for(i=0;i 0) && (rcv->mtext[0]=='p')) + { + n_chunks=data[0x30]; + t_info = realloc(t_info,sizeof(Track_info)*n_chunks); + stop = 1; + rcv->mtext[0] = '0'; + stop_all(); + } + } + while(!stop); + SEQ_STOP_TIMER(); + if( stop == 2) + { + stop_all(); + do + { + ipc_read=do_ipc(qid,rcv,0); + } + while(rcv->mtext[0] != 'p'); + rcv->mtext[0] = '0'; + n_chunks=data[0x30]; + t_info = realloc(t_info,sizeof(Track_info)*n_chunks); + stop = 0; + } + pos=0x308; + } + free(data); + free(t_info); + free(rcv); + +} + +void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) { + char buf[128]; + + sprintf(buf,"p%s",filename); + send_ipc(buf); +} +void digi_set_midi_volume( int mvolume ) { + char buf[128]; + + sprintf(buf,"v%i",mvolume); + send_ipc(buf); +} diff --git a/arch/linux/hmistub.c b/arch/linux/hmistub.c new file mode 100644 index 00000000..538f29d0 --- /dev/null +++ b/arch/linux/hmistub.c @@ -0,0 +1,2 @@ +void digi_set_midi_volume( int mvolume ) { } +void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {} diff --git a/arch/linux/include/ipx_bsd.h b/arch/linux/include/ipx_bsd.h new file mode 100644 index 00000000..74212a40 --- /dev/null +++ b/arch/linux/include/ipx_bsd.h @@ -0,0 +1,6 @@ +#ifndef _IPX_BSD_H +#define _IPX_BSD_H +#include "ipx_drv.h" + +extern struct ipx_driver ipx_bsd; +#endif diff --git a/arch/linux/include/ipx_drv.h b/arch/linux/include/ipx_drv.h new file mode 100644 index 00000000..c999cfbc --- /dev/null +++ b/arch/linux/include/ipx_drv.h @@ -0,0 +1,68 @@ +/* + * IPX driver interface + * + * parts from: + * ipx.h header file for IPX for the DOS emulator + * Tim Bird, tbird@novell.com + */ +#ifndef _IPX_DRV_H +#define _IPX_DRV_H +#include + +#define IPX_MANUAL_ADDRESS + +#define MAX_PACKET_DATA 1500 + +typedef struct IPXAddressStruct { + u_char Network[4] __attribute__((packed)); + u_char Node[6] __attribute__((packed)); + u_char Socket[2] __attribute__((packed)); +} IPXAddress_t; + +typedef struct IPXPacketStructure { + u_short Checksum __attribute__((packed)); + u_short Length __attribute__((packed)); + u_char TransportControl __attribute__((packed)); + u_char PacketType __attribute__((packed)); + IPXAddress_t Destination __attribute__((packed)); + IPXAddress_t Source __attribute__((packed)); +} IPXPacket_t; + +typedef struct ipx_socket_struct { +#ifdef DOSEMU + struct ipx_socket_struct *next; + far_t listenList; + int listenCount; + far_t AESList; + int AESCount; + u_short PSP; +#endif + u_short socket; + int fd; +} ipx_socket_t; + +struct ipx_recv_data { + /* all network order */ + u_char src_network[4]; + u_char src_node[6]; + u_short src_socket; + u_short dst_socket; + int pkt_type; +}; + +struct ipx_driver { + int (*GetMyAddress)(void); + int (*OpenSocket)(ipx_socket_t *sk, int port); + void (*CloseSocket)(ipx_socket_t *mysock); + int (*SendPacket)(ipx_socket_t *mysock, IPXPacket_t *IPXHeader, + u_char *data, int dataLen); + int (*ReceivePacket)(ipx_socket_t *s, char *buffer, int bufsize, + struct ipx_recv_data *rec); + int (*PacketReady)(ipx_socket_t *s); +}; + +int ipx_general_PacketReady(ipx_socket_t *s); + +extern unsigned char ipx_MyAddress[10]; + +#endif /* _IPX_DRV_H */ diff --git a/arch/linux/include/ipx_hlpr.h b/arch/linux/include/ipx_hlpr.h new file mode 100644 index 00000000..c4836458 --- /dev/null +++ b/arch/linux/include/ipx_hlpr.h @@ -0,0 +1,28 @@ +#ifndef IPXHELPER_H_ +#define IPXHELPER_H_ +#include +#include "ipx_ld.h" + +#define IPX_MANUAL_ADDRESS + +struct ipx_recv_data { + /* all network order */ + u_char src_network[4]; + u_char src_node[6]; + u_short src_socket; + u_short dst_socket; + int pkt_type; +}; + +struct ipx_helper { + int (*GetMyAddress)(void); + int (*OpenSocket)(ipx_socket_t *sk, int port); + void (*CloseSocket)(ipx_socket_t *mysock); + int (*SendPacket)(ipx_socket_t *mysock, IPXPacket_t *IPXHeader, + u_char *data, int dataLen); + int (*ReceivePacket)(ipx_socket_t *s, char *buffer, int bufsize, + struct ipx_recv_data *rec); + int (*PacketReady)(ipx_socket_t *s); +}; + +#endif /* IPXHELPER_H_ */ diff --git a/arch/linux/include/ipx_kali.h b/arch/linux/include/ipx_kali.h new file mode 100644 index 00000000..05fcd83a --- /dev/null +++ b/arch/linux/include/ipx_kali.h @@ -0,0 +1,6 @@ +#ifndef _IPX_KALI_H +#define _IPX_KALI_H +#include "ipx_drv.h" + +extern struct ipx_driver ipx_kali; +#endif diff --git a/arch/linux/include/ipx_ld.h b/arch/linux/include/ipx_ld.h new file mode 100644 index 00000000..22a5d33b --- /dev/null +++ b/arch/linux/include/ipx_ld.h @@ -0,0 +1,49 @@ +/* + * parts from: + * ipx.h header file for IPX for the DOS emulator + * Tim Bird, tbird@novell.com + */ + +#ifndef _IPX_DOSEMU +#define _IPX_DOSEMU + +#define MAX_PACKET_DATA 1500 + +typedef struct IPXAddressStruct { + u_char Network[4] __attribute__((packed)); + u_char Node[6] __attribute__((packed)); + u_char Socket[2] __attribute__((packed)); +} IPXAddress_t; + +typedef struct IPXPacketStructure { + u_short Checksum __attribute__((packed)); + u_short Length __attribute__((packed)); + u_char TransportControl __attribute__((packed)); + u_char PacketType __attribute__((packed)); + IPXAddress_t Destination __attribute__((packed)); + IPXAddress_t Source __attribute__((packed)); +} IPXPacket_t; + +typedef struct ipx_socket_struct { +#ifdef DOSEMU + struct ipx_socket_struct *next; + far_t listenList; + int listenCount; + far_t AESList; + int AESCount; + u_short PSP; +#endif + u_short socket; + int fd; +} ipx_socket_t; + +#include "mono.h" +#ifndef NMONO +#define n_printf(format, args...) _mprintf(1, format, ## args) +#else +#define n_printf(format, args...) fprintf(stderr,format, ## args) +#endif +#define enter_priv_on() +#define leave_priv_setting() + +#endif diff --git a/arch/linux/include/ipx_lin.h b/arch/linux/include/ipx_lin.h new file mode 100644 index 00000000..5474f2e2 --- /dev/null +++ b/arch/linux/include/ipx_lin.h @@ -0,0 +1,13 @@ +#ifndef IPX_LINUX_H_ +#define IPX_LINUX_H_ +#include +#include "ipx_hlpr.h" +int ipx_linux_GetMyAddress(void); +int ipx_linux_OpenSocket(ipx_socket_t *sk, int port); +void ipx_linux_CloseSocket(ipx_socket_t *mysock); +int ipx_linux_SendPacket(ipx_socket_t *mysock, IPXPacket_t *IPXHeader, + u_char *data, int dataLen); +int ipx_linux_ReceivePacket(ipx_socket_t *s, char *buffer, int bufsize, + struct ipx_recv_data *rd); + +#endif diff --git a/arch/linux/include/ipx_udp.h b/arch/linux/include/ipx_udp.h new file mode 100644 index 00000000..26277890 --- /dev/null +++ b/arch/linux/include/ipx_udp.h @@ -0,0 +1,6 @@ +#ifndef _IPX_UDP_H +#define _IPX_UDP_H +#include "ipx_drv.h" + +extern struct ipx_driver ipx_udp; +#endif diff --git a/arch/linux/include/music.h b/arch/linux/include/music.h new file mode 100644 index 00000000..f5ba340b --- /dev/null +++ b/arch/linux/include/music.h @@ -0,0 +1,33 @@ +#include + +#define SEQ_DEV "/dev/sequencer" + +#define PLAYING 0 +#define STOPPED 1 + +typedef struct +{ + int position; + int status; + int time; +} Track_info; + +typedef struct +{ + signed short note; + signed short channel; +} Voice_info; + +void seqbuf_dump(); +int seq_init(); +void seq_close(); +void set_program(int, int); +void start_note(int, int, int); +void stop_note(int, int, int); +void set_control(int, int, int); +void set_pitchbend(int, int); +void set_chn_pressure(int,int); +void set_key_pressure(int,int,int); +void play_hmi (void * arg); +void send_ipc(char *); +void kill_ipc(); diff --git a/arch/linux/include/serial.h b/arch/linux/include/serial.h new file mode 100644 index 00000000..e31839ae --- /dev/null +++ b/arch/linux/include/serial.h @@ -0,0 +1,18 @@ +// Name: Serial port support for Linux D1X +// Author: dph +// Date: Sun Oct 18, 1998 + +#ifndef _SERIAL_H +#define _SERIAL_H +void com_done(void); +int com_init(void); +int com_read(char *buffer, int len, int timeout_value); +int com_write(char *buffer, int len); +void com_port_hangup(); +int com_getdcd(); +void com_flushbuffers(); +void com_setbaudrate(int rate); +int com_readline(int timeout, char *input_buffer,int len); + +extern int commlib_initialised; +#endif diff --git a/arch/linux/include/ukali.h b/arch/linux/include/ukali.h new file mode 100644 index 00000000..b38ef24f --- /dev/null +++ b/arch/linux/include/ukali.h @@ -0,0 +1,72 @@ +#ifndef __UKALI_H__ +#define __UKALI_H__ + +//added on 10/04/98 by Matt Mueller to show correct ver in kali +#include "vers_id.h" +//end addition -MM + +// 4213 is the port that KaliNix is listening on +// +// char code; // 1 == open, 2 == close, 3 == data, 5 == GetMyAddr +// acks // 6 == open, 7 == close 4 == GetMyAddr + +// net data packets structure for send/recv +// struct { +// char code; == 3 +// char sa_nodenum[6]; +// char dport[2]; +// char sport[2]; +// char data[]; +// } + +// net data packets for open/close socket +// +// process_name is a null terminated 8byte string +// struct { +// char code; // 1/6 == open, 2/7 == close +// char socket[2]; +// char pid[4]; +// char process_name[9]; +// } + +// net myaddress struct which is returned after the GetMyAddress call +// struct { +// char code; == 4 +// char sa_nodenum[6]; +// } + +// net data for GetMyAddress call +// struct { +// char code; == 5 +// } + +typedef struct kaliaddr_ipx_tag { + short sa_family; + char sa_netnum[4]; + char sa_nodenum[6]; + unsigned short sa_socket; +} kaliaddr_ipx; + +// Process name that shows up in /whois and /games list. +// Maximum of 8 characters. +//edited on 10/04/98 by Matt Mueller to show correct ver in kali +#define KALI_PROCESS_NAME "D1X" D1XMAJOR D1XMINOR +//end edit -MM +#define MAX_PACKET_SIZE 1500 + +// struct ipx_helper ipx_kali = { +// ipx_kali_GetMyAddress, +// ipx_kali_OpenSocket, +// ipx_kali_CloseSocket, +// ipx_kali_SendPacket, +// ipx_kali_ReceivePacket, +// ipx_general_PacketReady +// }; + +int KaliGetNodeNum(kaliaddr_ipx *myaddr); +int KaliOpenSocket(unsigned short port); +int KaliCloseSocket(int hand); +int KaliSendPacket(int hand, char *data, int len, kaliaddr_ipx *to); +int KaliReceivePacket(int hand, char *data, int len, kaliaddr_ipx *from); + +#endif __UKALI_H__ diff --git a/arch/linux/init.c b/arch/linux/init.c new file mode 100644 index 00000000..3d4fa7e0 --- /dev/null +++ b/arch/linux/init.c @@ -0,0 +1,46 @@ +// linux init.c - added Matt Mueller 9/6/98 +#include +#include +#include +#include "pstypes.h" +#include "console.h" +#include "text.h" +#include "event.h" +#include "error.h" +#include "joy.h" +#include "args.h" + +extern void arch_sdl_init(); +extern void arch_svgalib_init(); +extern void key_init(); +extern int com_init(); +extern void timer_init(); + +void arch_init_start() +{ + +} + +void arch_init() +{ + // Initialise the library + arch_sdl_init(); +#ifdef __SVGALIB__ + arch_svgalib_init(); +#endif + if (!args_find( "-nojoystick" )) { + con_printf(CON_VERBOSE, "\n%s", TXT_VERBOSE_6); + joy_init(); + } + //added 06/09/99 Matt Mueller - fix nonetwork compile +#ifdef NETWORK + //end addition -MM +//added on 10/19/98 by Victor Rachels to add serial support (from DPH) + if(!(args_find("-noserial"))) + com_init(); +//end this section addition - Victor + //added 06/09/99 Matt Mueller - fix nonetwork compile +#endif + //end addition -MM + key_init(); +} diff --git a/arch/linux/ipx_bsd.c b/arch/linux/ipx_bsd.c new file mode 100644 index 00000000..9e78b861 --- /dev/null +++ b/arch/linux/ipx_bsd.c @@ -0,0 +1,228 @@ +/* IPX driver using BSD style sockets */ +/* Mostly taken from dosemu */ +#include +#ifdef NETWORK + +#include +#include +#include +#include + +#ifdef HAVE_NETIPX_IPX_H +#include +#else +# include +# ifndef IPX_TYPE +# define IPX_TYPE 1 +# endif +#endif + +#include +#include +#include + +#include "pstypes.h" +#include "ipx_drv.h" +#include "ipx_bsd.h" + +#ifndef DOSEMU +#include "mono.h" +#define n_printf(format, args...) mprintf((1, format, ## args)) +#define enter_priv_on() +#define leave_priv_setting() +#endif + +static int ipx_bsd_GetMyAddress( void ) +{ + int sock; + struct sockaddr_ipx ipxs; + struct sockaddr_ipx ipxs2; + int len; + int i; + + sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX); + if(sock==-1) + { + n_printf("IPX: could not open socket in GetMyAddress\n"); + return(-1); + } + + /* bind this socket to network 0 */ + ipxs.sipx_family=AF_IPX; +#ifdef IPX_MANUAL_ADDRESS + memcpy(&ipxs.sipx_network, ipx_MyAddress, 4); +#else + ipxs.sipx_network=0; +#endif + ipxs.sipx_port=0; + + if(bind(sock,(struct sockaddr *)&ipxs,sizeof(ipxs))==-1) + { + n_printf("IPX: could bind to network 0 in GetMyAddress\n"); + close( sock ); + return(-1); + } + + len = sizeof(ipxs2); + if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) { + n_printf("IPX: could not get socket name in GetMyAddress\n"); + close( sock ); + return(-1); + } + + memcpy(ipx_MyAddress, &ipxs2.sipx_network, 4); + for (i = 0; i < 6; i++) { + ipx_MyAddress[4+i] = ipxs2.sipx_node[i]; + } + close( sock ); + return(0); +} + +static int ipx_bsd_OpenSocket(ipx_socket_t *sk, int port) +{ + int sock; /* sock here means Linux socket handle */ + int opt; + struct sockaddr_ipx ipxs; + int len; + struct sockaddr_ipx ipxs2; + + /* DANG_FIXTHIS - kludge to support broken linux IPX stack */ + /* need to convert dynamic socket open into a real socket number */ +/* if (port == 0) { + n_printf("IPX: using socket %x\n", nextDynamicSocket); + port = nextDynamicSocket++; + } +*/ + /* do a socket call, then bind to this port */ + sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX); + if (sock == -1) { + n_printf("IPX: could not open IPX socket.\n"); + return -1; + } + +#ifdef DOSEMU + opt = 1; + /* turn on socket debugging */ + if (d.network) { + enter_priv_on(); + if (setsockopt(sock, SOL_SOCKET, SO_DEBUG, &opt, sizeof(opt)) == -1) { + leave_priv_setting(); + n_printf("IPX: could not set socket option for debugging.\n"); + return -1; + } + leave_priv_setting(); + } +#endif + opt = 1; + /* Permit broadcast output */ + enter_priv_on(); + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, + &opt, sizeof(opt)) == -1) { + leave_priv_setting(); + n_printf("IPX: could not set socket option for broadcast.\n"); + return -1; + } +#ifdef DOSEMU + /* allow setting the type field in the IPX header */ + opt = 1; +#if 0 /* this seems to be wrong: IPX_TYPE can only be set on level SOL_IPX */ + if (setsockopt(sock, SOL_SOCKET, IPX_TYPE, &opt, sizeof(opt)) == -1) { +#else + /* the socket _is_ an IPX socket, hence it first passes ipx_setsockopt() + * in file linux/net/ipx/af_ipx.c. This one handles SOL_IPX itself and + * passes SOL_SOCKET-levels down to sock_setsockopt(). + * Hence I guess the below is correct (can somebody please verify this?) + * -- Hans, June 14 1997 + */ + if (setsockopt(sock, SOL_IPX, IPX_TYPE, &opt, sizeof(opt)) == -1) { +#endif + leave_priv_setting(); + n_printf("IPX: could not set socket option for type.\n"); + return -1; + } +#endif + ipxs.sipx_family = AF_IPX; + ipxs.sipx_network = *((unsigned int *)&ipx_MyAddress[0]); +/* ipxs.sipx_network = htonl(MyNetwork); */ + bzero(ipxs.sipx_node, 6); /* Please fill in my node name */ + ipxs.sipx_port = htons(port); + + /* now bind to this port */ + if (bind(sock, (struct sockaddr *) &ipxs, sizeof(ipxs)) == -1) { + n_printf("IPX: could not bind socket to address\n"); + close( sock ); + leave_priv_setting(); + return -1; + } + + if( port==0 ) { + len = sizeof(ipxs2); + if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) { + n_printf("IPX: could not get socket name in IPXOpenSocket\n"); + close( sock ); + leave_priv_setting(); + return -1; + } else { + port = htons(ipxs2.sipx_port); + n_printf("IPX: opened dynamic socket %04x\n", port); + } + } + leave_priv_setting(); + sk->fd = sock; + sk->socket = port; + return 0; +} + +static void ipx_bsd_CloseSocket(ipx_socket_t *mysock) { + /* now close the file descriptor for the socket, and free it */ + n_printf("IPX: closing file descriptor on socket %x\n", mysock->socket); + close(mysock->fd); +} + +static int ipx_bsd_SendPacket(ipx_socket_t *mysock, IPXPacket_t *IPXHeader, + u_char *data, int dataLen) { + struct sockaddr_ipx ipxs; + + ipxs.sipx_family = AF_IPX; + /* get destination address from IPX packet header */ + memcpy(&ipxs.sipx_network, IPXHeader->Destination.Network, 4); + /* if destination address is 0, then send to my net */ + if (ipxs.sipx_network == 0) { + ipxs.sipx_network = *((unsigned int *)&ipx_MyAddress[0]); +/* ipxs.sipx_network = htonl(MyNetwork); */ + } + memcpy(&ipxs.sipx_node, IPXHeader->Destination.Node, 6); + memcpy(&ipxs.sipx_port, IPXHeader->Destination.Socket, 2); + ipxs.sipx_type = IPXHeader->PacketType; + /* ipxs.sipx_port=htons(0x452); */ + return sendto(mysock->fd, data, dataLen, 0, + (struct sockaddr *) &ipxs, sizeof(ipxs)); +} + +static int ipx_bsd_ReceivePacket(ipx_socket_t *s, char *buffer, int bufsize, + struct ipx_recv_data *rd) { + int sz, size; + struct sockaddr_ipx ipxs; + + sz = sizeof(ipxs); + if ((size = recvfrom(s->fd, buffer, bufsize, 0, + (struct sockaddr *) &ipxs, &sz)) <= 0) + return size; + memcpy(rd->src_network, &ipxs.sipx_network, 4); + memcpy(rd->src_node, ipxs.sipx_node, 6); + rd->src_socket = ipxs.sipx_port; + rd->dst_socket = s->socket; + rd->pkt_type = ipxs.sipx_type; + + return size; +} + +struct ipx_driver ipx_bsd = { + ipx_bsd_GetMyAddress, + ipx_bsd_OpenSocket, + ipx_bsd_CloseSocket, + ipx_bsd_SendPacket, + ipx_bsd_ReceivePacket, + ipx_general_PacketReady +}; +#endif // NETWORK diff --git a/arch/linux/ipx_kali.c b/arch/linux/ipx_kali.c new file mode 100644 index 00000000..16a518d8 --- /dev/null +++ b/arch/linux/ipx_kali.c @@ -0,0 +1,112 @@ +/* IPX driver for KaliNix interface */ +#include +#include +#include /* for htons & co. */ +#include "ipx_drv.h" +#include "ukali.h" + +extern unsigned char ipx_MyAddress[10]; + +static int open_sockets = 0; +static int dynamic_socket = 0x401; +static int last_socket = 0; + +int have_empty_address() { + int i; + for (i = 0; i < 10 && !ipx_MyAddress[i]; i++) ; + return i == 10; +} + +int ipx_kali_GetMyAddress(void) { + + kaliaddr_ipx mKaliAddr; + + if (!have_empty_address()) + return 0; + + if (KaliGetNodeNum(&mKaliAddr) < 0) + return -1; + + memset(ipx_MyAddress, 0, 4); + memcpy(ipx_MyAddress + 4, mKaliAddr.sa_nodenum, sizeof(mKaliAddr.sa_nodenum)); + + return 0; +} + +int ipx_kali_OpenSocket(ipx_socket_t *sk, int port) { + printf("IPX_kali: OpenSocket on port(%d)\n", port); + + if (!open_sockets) { + if (have_empty_address()) { + if (ipx_kali_GetMyAddress() < 0) { + printf("IPX_kali: Error communicating with KaliNix\n"); + return -1; + } + } + } + if (!port) + port = dynamic_socket++; + + if ((sk->fd = KaliOpenSocket(htons(port))) < 0) { + printf("IPX_kali: OpenSocket Failed on port(%d)\n", port); + sk->fd = -1; + return -1; + } + open_sockets++; + last_socket = port; + sk->socket = port; + return 0; +} + +void ipx_kali_CloseSocket(ipx_socket_t *mysock) { + if (!open_sockets) { + printf("IPX_kali: close w/o open\n"); + return; + } + printf("IPX_kali: CloseSocket on port(%d)\n", mysock->socket); + KaliCloseSocket(mysock->fd); + if (--open_sockets) { + printf("IPX_kali: (closesocket) %d sockets left\n", open_sockets); + return; + } +} + +int ipx_kali_SendPacket(ipx_socket_t *mysock, IPXPacket_t *IPXHeader, + u_char *data, int dataLen) { + kaliaddr_ipx toaddr; + int i; + + memcpy(toaddr.sa_nodenum, IPXHeader->Destination.Node, sizeof(toaddr.sa_nodenum)); + memcpy(&toaddr.sa_socket, IPXHeader->Destination.Socket, sizeof(toaddr.sa_socket)); + + if ((i = KaliSendPacket(mysock->fd, (char *)data, dataLen, &toaddr)) < 0) + return -1; + + return i; +} + +int ipx_kali_ReceivePacket(ipx_socket_t *s, char *outbuf, int outbufsize, + struct ipx_recv_data *rd) { + int size; + kaliaddr_ipx fromaddr; + + if ((size = KaliReceivePacket(s->fd, outbuf, outbufsize, &fromaddr)) < 0) + return -1; + + rd->dst_socket = s->socket; + rd->src_socket = ntohs(fromaddr.sa_socket); + memcpy(rd->src_node, fromaddr.sa_nodenum, sizeof(fromaddr.sa_nodenum)); + memset(rd->src_network, 0, 4); + rd->pkt_type = 0; + + return size; +} + +struct ipx_driver ipx_kali = { + ipx_kali_GetMyAddress, + ipx_kali_OpenSocket, + ipx_kali_CloseSocket, + ipx_kali_SendPacket, + ipx_kali_ReceivePacket, + ipx_general_PacketReady +}; diff --git a/arch/linux/ipx_lin.c b/arch/linux/ipx_lin.c new file mode 100644 index 00000000..91ab95a3 --- /dev/null +++ b/arch/linux/ipx_lin.c @@ -0,0 +1,214 @@ +#include +#ifdef NETWORK +#include +#include +#include +#include + +#ifdef HAVE_NETIPX_IPX_H +#include +#else +# include +# ifndef IPX_TYPE +# define IPX_TYPE 1 +# endif +#endif + +#include +#include +#include +#include "pstypes.h" + +#include "ipx_ld.h" +#include "ipx_hlpr.h" +#include "ipx_lin.h" + +extern unsigned char ipx_MyAddress[10]; + +int +ipx_linux_GetMyAddress( void ) +{ + int sock; + struct sockaddr_ipx ipxs; + struct sockaddr_ipx ipxs2; + int len; + int i; + + sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX); + if(sock==-1) + { + n_printf("IPX: could not open socket in GetMyAddress\n"); + return(-1); + } + + /* bind this socket to network 0 */ + ipxs.sipx_family=AF_IPX; +#ifdef IPX_MANUAL_ADDRESS + memcpy(&ipxs.sipx_network, ipx_MyAddress, 4); +#else + ipxs.sipx_network=0; +#endif + ipxs.sipx_port=0; + + if(bind(sock,(struct sockaddr *)&ipxs,sizeof(ipxs))==-1) + { + n_printf("IPX: could bind to network 0 in GetMyAddress\n"); + close( sock ); + return(-1); + } + + len = sizeof(ipxs2); + if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) { + n_printf("IPX: could not get socket name in GetMyAddress\n"); + close( sock ); + return(-1); + } + + memcpy(ipx_MyAddress, &ipxs2.sipx_network, 4); + for (i = 0; i < 6; i++) { + ipx_MyAddress[4+i] = ipxs2.sipx_node[i]; + } + close( sock ); + return(0); +} + +int +ipx_linux_OpenSocket(ipx_socket_t *sk, int port) +{ + int sock; /* sock here means Linux socket handle */ + int opt; + struct sockaddr_ipx ipxs; + int len; + struct sockaddr_ipx ipxs2; + + /* DANG_FIXTHIS - kludge to support broken linux IPX stack */ + /* need to convert dynamic socket open into a real socket number */ +/* if (port == 0) { + n_printf("IPX: using socket %x\n", nextDynamicSocket); + port = nextDynamicSocket++; + } +*/ + /* do a socket call, then bind to this port */ + sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX); + if (sock == -1) { + n_printf("IPX: could not open IPX socket.\n"); + return -1; + } + +#ifdef DOSEMU + opt = 1; + /* turn on socket debugging */ + if (d.network) { + enter_priv_on(); + if (setsockopt(sock, SOL_SOCKET, SO_DEBUG, &opt, sizeof(opt)) == -1) { + leave_priv_setting(); + n_printf("IPX: could not set socket option for debugging.\n"); + return -1; + } + leave_priv_setting(); + } +#endif + opt = 1; + /* Permit broadcast output */ + enter_priv_on(); + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, + &opt, sizeof(opt)) == -1) { + leave_priv_setting(); + n_printf("IPX: could not set socket option for broadcast.\n"); + return -1; + } +#ifdef DOSEMU + /* allow setting the type field in the IPX header */ + opt = 1; +#if 0 /* this seems to be wrong: IPX_TYPE can only be set on level SOL_IPX */ + if (setsockopt(sock, SOL_SOCKET, IPX_TYPE, &opt, sizeof(opt)) == -1) { +#else + /* the socket _is_ an IPX socket, hence it first passes ipx_setsockopt() + * in file linux/net/ipx/af_ipx.c. This one handles SOL_IPX itself and + * passes SOL_SOCKET-levels down to sock_setsockopt(). + * Hence I guess the below is correct (can somebody please verify this?) + * -- Hans, June 14 1997 + */ + if (setsockopt(sock, SOL_IPX, IPX_TYPE, &opt, sizeof(opt)) == -1) { +#endif + leave_priv_setting(); + n_printf("IPX: could not set socket option for type.\n"); + return -1; + } +#endif + ipxs.sipx_family = AF_IPX; + ipxs.sipx_network = *((unsigned int *)&ipx_MyAddress[0]); +/* ipxs.sipx_network = htonl(MyNetwork); */ + bzero(ipxs.sipx_node, 6); /* Please fill in my node name */ + ipxs.sipx_port = htons(port); + + /* now bind to this port */ + if (bind(sock, (struct sockaddr *) &ipxs, sizeof(ipxs)) == -1) { + n_printf("IPX: could not bind socket to address\n"); + close( sock ); + leave_priv_setting(); + return -1; + } + + if( port==0 ) { + len = sizeof(ipxs2); + if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) { + n_printf("IPX: could not get socket name in IPXOpenSocket\n"); + close( sock ); + leave_priv_setting(); + return -1; + } else { + port = htons(ipxs2.sipx_port); + n_printf("IPX: opened dynamic socket %04x\n", port); + } + } + leave_priv_setting(); + sk->fd = sock; + sk->socket = port; + return 0; +} + +void ipx_linux_CloseSocket(ipx_socket_t *mysock) { + /* now close the file descriptor for the socket, and free it */ + n_printf("IPX: closing file descriptor on socket %x\n", mysock->socket); + close(mysock->fd); +} + +int ipx_linux_SendPacket(ipx_socket_t *mysock, IPXPacket_t *IPXHeader, + u_char *data, int dataLen) { + struct sockaddr_ipx ipxs; + + ipxs.sipx_family = AF_IPX; + /* get destination address from IPX packet header */ + memcpy(&ipxs.sipx_network, IPXHeader->Destination.Network, 4); + /* if destination address is 0, then send to my net */ + if (ipxs.sipx_network == 0) { + ipxs.sipx_network = *((unsigned int *)&ipx_MyAddress[0]); +/* ipxs.sipx_network = htonl(MyNetwork); */ + } + memcpy(&ipxs.sipx_node, IPXHeader->Destination.Node, 6); + memcpy(&ipxs.sipx_port, IPXHeader->Destination.Socket, 2); + ipxs.sipx_type = IPXHeader->PacketType; + /* ipxs.sipx_port=htons(0x452); */ + return sendto(mysock->fd, data, dataLen, 0, + (struct sockaddr *) &ipxs, sizeof(ipxs)); +} + +int ipx_linux_ReceivePacket(ipx_socket_t *s, char *buffer, int bufsize, + struct ipx_recv_data *rd) { + int sz, size; + struct sockaddr_ipx ipxs; + + sz = sizeof(ipxs); + if ((size = recvfrom(s->fd, buffer, bufsize, 0, + (struct sockaddr *) &ipxs, &sz)) <= 0) + return size; + memcpy(rd->src_network, &ipxs.sipx_network, 4); + memcpy(rd->src_node, ipxs.sipx_node, 6); + rd->src_socket = ipxs.sipx_port; + rd->dst_socket = s->socket; + rd->pkt_type = ipxs.sipx_type; + + return size; +} +#endif // NETWORK diff --git a/arch/linux/ipx_udp.c b/arch/linux/ipx_udp.c new file mode 100644 index 00000000..c369a284 --- /dev/null +++ b/arch/linux/ipx_udp.c @@ -0,0 +1,591 @@ +/* IPX driver for native Linux TCP/IP networking (UDP implementation) + * Version 0.99.2 + * Contact Jan [Lace] Kratochvil for assistance + * (no "It somehow doesn't work! What should I do?" complaints, please) + * Special thanks to Vojtech Pavlik for testing. + * + * Also you may see KIX - KIX kix out KaliNix (in Linux-Linux only): + * http://atrey.karlin.mff.cuni.cz/~short/sw/kix.c.gz + * + * Primarily based on ipx_kali.c - "IPX driver for KaliNix interface" + * which is probably mostly by Jay Cotton . + * Parts shamelessly stolen from my KIX v0.99.2 and GGN v0.100 + * + * Changes: + * -------- + * 0.99.1 - now the default broadcast list also contains all point-to-point + * links with their destination peer addresses + * 0.99.2 - commented a bit :-) + * - now adds to broadcast list each host it gets some packet from + * which is already not covered by local physical ethernet broadcast + * - implemented short-signature packet format + * - compatibility mode for old D1X releases due to the previous bullet + * + * Configuration: + * -------------- + * No network server software is needed, neither KIX nor KaliNIX. + * + * Add command line argument "-udp". In default operation D1X will send + * broadcasts too all the local interfaces found. But you may also use + * additional parameter specified after "-udp" to modify the default + * broadcasting style and UDP port numbers binding: + * + * ./d1x -udp [@SHIFT]=HOST_LIST Broadcast ONLY to HOST_LIST + * ./d1x -udp [@SHIFT]+HOST_LIST Broadcast both to local ifaces & to HOST_LIST + * + * HOST_LIST is a comma (',') separated list of HOSTs: + * HOST is an IPv4 address (so-called quad like 192.168.1.2) or regular hostname + * HOST can also be in form 'address:SHIFT' + * SHIFT sets the UDP port base offset (e.g. +2), can be used to run multiple + * clients on one host simultaneously. This SHIFT has nothing to do + * with the dynamic-sockets (PgUP/PgDOWN) option in Descent, it's another + * higher-level differentiation option. + * + * Examples: + * --------- + * ./d1x -udp + * - Run D1X to participate in normal local network (Linux only, of course) + * + * ./d1x -udp @1=localhost:2 & ./d1x -udp @2=localhost:1 + * - Run two clients simultaneously fighting each other (only each other) + * + * ./d1x -udp =192.168.4.255 + * - Run distant Descent which will participate with remote network + * 192.168.4.0 with netmask 255.255.255.0 (broadcast has 192.168.4.255) + * - You'll have to also setup hosts in that network accordingly: + * ./d1x -udp +UPPER_DISTANT_MACHINE_NAME + * + * Have fun! + */ + +#include +#ifdef NETWORK +#include +#include +#include /* for htons & co. */ +#include +#include +#include +#include +#include +#include +#include + +#include "ipx_drv.h" +#include "args.h" + +extern unsigned char ipx_MyAddress[10]; + +// #define UDPDEBUG + +#define UDP_BASEPORT 28342 +#define PORTSHIFT_TOLERANCE 0x100 +#define MAX_PACKETSIZE 8192 + +/* Packet format: first is the signature { 0xD1,'X' } which can be also + * { 'D','1','X','u','d','p'} for old-fashioned packets. + * Then follows virtual socket number (as changed during PgDOWN/PgUP) + * in network-byte-order as 2 bytes (u_short). After such 4/8 byte header + * follows raw data as communicated with D1X network core functions. + */ + +// Length HAS TO BE 6! +#define D1Xudp "D1Xudp" +// Length HAS TO BE 2! +#define D1Xid "\xD1X" + +static int open_sockets = 0; +static int dynamic_socket = 0x401; +static const int val_one=1; + +/* OUR port. Can be changed by "@X[+=]..." argument (X is the shift value) + */ + +static int baseport=UDP_BASEPORT; + +/* Have we some old D1X in network and have we to maintain compatibility? + * FIXME: Following scenario is braindead: + * A (NEW) , B (OLD) , C (NEW) + * host A) We start new D1X. A-newcomm, B-none , C-none + * host B) We start OLD D1X. A-newcomm, B-oldcomm, C-none + * Now host A hears host B and switches: A-oldcomm, B-oldcomm, C-none + * host C) We start new D1X. A-oldcomm, B-oldcomm, C-newcomm + * Now host C hears host A/B and switches: A-oldcomm, B-oldcomm, C-oldcomm + * Now host B finishes: A-oldcomm, B-none , C-oldcomm + * + * But right now we have hosts A and C, both new code equipped but + * communicating wastefully by the OLD protocol! Bummer. + */ + +static char compatibility=0; + +static int have_empty_address() { + int i; + for (i = 0; i < 10 && !ipx_MyAddress[i]; i++) ; + return i == 10; +} + +#define MSGHDR "IPX_udp: " + +static void msg(const char *fmt,...) +{ +va_list ap; + fputs(MSGHDR,stdout); + va_start(ap,fmt); + vprintf(fmt,ap); + va_end(ap); + putchar('\n'); +} + +static void chk(void *p) +{ + if (p) return; + msg("FATAL: Virtual memory exhausted!"); + exit(EXIT_FAILURE); +} + +#define FAIL(m...) do { msg(#m); return -1; } while (0) + +/* Find as much as MAX_BRDINTERFACES during local iface autoconfiguration. + * Note that more interfaces can be added during manual configuration + * or host-received-packet autoconfiguration + */ + +#define MAX_BRDINTERFACES 16 + +/* We require the interface to be UP and RUNNING to accept it. + */ + +#define IF_REQFLAGS (IFF_UP|IFF_RUNNING) + +/* We reject any interfaces declared as LOOPBACK type. + */ +#define IF_NOTFLAGS (IFF_LOOPBACK) + +static struct sockaddr_in *broads,broadmasks[MAX_BRDINTERFACES]; +static int broadnum,masksnum,broadsize; + +/* We'll check whether the "broads" array of destination addresses is now + * full and so needs expanding. + */ + +static void chkbroadsize(void) +{ + if (broadnumsin_family!=AF_INET || sinmp->sin_family!=AF_INET) continue; + broads[j]=*sinp; + broads[j].sin_port=UDP_BASEPORT; //FIXME: No possibility to override from cmdline + broadmasks[j]=*sinmp; + j++; + } + broadnum=j; + masksnum=j; + return(0); +} + +#define addreq(a,b) ((a).sin_port==(b).sin_port&&(a).sin_addr.s_addr==(b).sin_addr.s_addr) + +/* Previous function addiflist() can (and probably will) report multiple + * same addresses. On some Linux boxes is present both device "eth0" and + * "dummy0" with the same IP addreesses - we'll filter it here. + */ + +static void unifyiflist(void) +{ +int d=0,s,i; + + for (s=0;s=s) broads[d++]=broads[s]; + } + broadnum=d; +} + +static unsigned char qhbuf[6]; + +/* Parse PORTSHIFT numeric parameter + */ + +static void portshift(const char *cs) +{ +long port; +unsigned short ports=0; + + port=atol(cs); + if (port<-PORTSHIFT_TOLERANCE || port>+PORTSHIFT_TOLERANCE) + msg("Invalid portshift in \"%s\", tolerance is +/-%d",cs,PORTSHIFT_TOLERANCE); + else ports=htons(port); + memcpy(qhbuf+4,&ports,2); +} + +/* Do hostname resolve on name "buf" and return the address in buffer "qhbuf". + */ +static unsigned char *queryhost(char *buf) +{ +struct hostent *he; +char *s; +char c=0; + + if ((s=strrchr(buf,':'))) { + c=*s; + *s='\0'; + portshift(s+1); + } + else memset(qhbuf+4,0,2); + he=gethostbyname((char *)buf); + if (s) *s=c; + if (!he) { + msg("Error resolving my hostname \"%s\"",buf); + return(NULL); + } + if (he->h_addrtype!=AF_INET || he->h_length!=4) { + msg("Error parsing resolved my hostname \"%s\"",buf); + return(NULL); + } + if (!*he->h_addr_list) { + msg("My resolved hostname \"%s\" address list empty",buf); + return(NULL); + } + memcpy(qhbuf,(*he->h_addr_list),4); + return(qhbuf); +} + +/* Dump raw form of IP address/port by fancy output to user + */ +static void dumpraddr(unsigned char *a) +{ +short port; + printf("[%u.%u.%u.%u]",a[0],a[1],a[2],a[3]); + port=(signed short)ntohs(*(unsigned short *)(a+4)); + if (port) printf(":%+d",port); +} + +/* Like dumpraddr() but for structure "sockaddr_in" + */ + +static void dumpaddr(struct sockaddr_in *sin) +{ +unsigned short ports; + + memcpy(qhbuf+0,&sin->sin_addr,4); + ports=htons(((short)ntohs(sin->sin_port))-UDP_BASEPORT); + memcpy(qhbuf+4,&ports,2); + dumpraddr(qhbuf); +} + +/* Startup... Uninteresting parsing... + */ + +static int ipx_udp_GetMyAddress(void) { + +char buf[256]; +int i; +char *s,*s2,*ns; + + if (!have_empty_address()) + return 0; + + if (!((i=args_find("-udp")) && (s=Args[i+1]) && (*s=='=' || *s=='+' || *s=='@'))) s=NULL; + + if (gethostname(buf,sizeof(buf))) FAIL("Error getting my hostname"); + if (!(queryhost(buf))) FAIL("Querying my own hostname \"%s\"",buf); + + if (s) while (*s=='@') { + portshift(++s); + while (isdigit(*s)) s++; + } + + memset(ipx_MyAddress+0,0,4); + memcpy(ipx_MyAddress+4,qhbuf,6); + baseport+=(short)ntohs(*(unsigned short *)(qhbuf+4)); + + if (!s || (s && !*s)) addiflist(); + else { + if (*s=='+') addiflist(); + s++; + for (;;) { +struct sockaddr_in *sin; + while (isspace(*s)) s++; + if (!*s) break; + for (s2=s;*s2 && *s2!=',';s2++); + chk(ns=malloc(s2-s+1)); + memcpy(ns,s,s2-s); + ns[s2-s]='\0'; + if (!queryhost(ns)) msg("Ignored broadcast-destination \"%s\" as being invalid",ns); + free(ns); + chkbroadsize(); + sin=broads+(broadnum++); + sin->sin_family=AF_INET; + memcpy(&sin->sin_addr,qhbuf+0,4); + sin->sin_port=htons(((short)ntohs(*(unsigned short *)(qhbuf+4)))+UDP_BASEPORT); + s=s2+(*s2==','); + } + } + + unifyiflist(); + + printf(MSGHDR "Using TCP/IP address "); + dumpraddr(ipx_MyAddress+4); + putchar('\n'); + if (broadnum) { + printf(MSGHDR "Using %u broadcast-dest%s:",broadnum,(broadnum==1?"":"s")); + for (i=0;ifd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0) { + sk->fd = -1; + FAIL("socket() creation failed on port %d: %m",port); + } + if (setsockopt(sk->fd,SOL_SOCKET,SO_BROADCAST,&val_one,sizeof(val_one))) { + if (close(sk->fd)) msg("close() failed during error recovery: %m"); + sk->fd=-1; + FAIL("setsockopt(SO_BROADCAST) failed: %m"); + } + sin.sin_family=AF_INET; + sin.sin_addr.s_addr=htonl(INADDR_ANY); + sin.sin_port=htons(baseport); + if (bind(sk->fd,(struct sockaddr *)&sin,sizeof(sin))) { + if (close(sk->fd)) msg("close() failed during error recovery: %m"); + sk->fd=-1; + FAIL("bind() to UDP port %d failed: %m",baseport); + } + + open_sockets++; + sk->socket = port; + return 0; +} + +/* The same comment as in previous "ipx_udp_OpenSocket"... + */ + +static void ipx_udp_CloseSocket(ipx_socket_t *mysock) { + if (!open_sockets) { + msg("close w/o open"); + return; + } + msg("CloseSocket on D1X socket port %d",mysock->socket); + if (close(mysock->fd)) + msg("close() failed on CloseSocket D1X socket port %d: %m",mysock->socket); + mysock->fd=-1; + if (--open_sockets) { + msg("(closesocket) %d sockets left", open_sockets); + return; + } +} + +/* Here we'll send the packet to our host. If it is unicast packet, send + * it to IP address/port as retrieved from IPX address. Otherwise (broadcast) + * we'll repeat the same data to each host in our broadcasting list. + */ + +static int ipx_udp_SendPacket(ipx_socket_t *mysock, IPXPacket_t *IPXHeader, + u_char *data, int dataLen) { + struct sockaddr_in toaddr,*dest; + int i=dataLen; + int bcast; + char *buf; + +#ifdef UDPDEBUG + msg("SendPacket enter, dataLen=%d",dataLen); +#endif + if (dataLen<0 || dataLen>MAX_PACKETSIZE) return -1; + chk(buf=alloca(8+dataLen)); + if (compatibility) memcpy(buf+0,D1Xudp,6),buf+=6; + else memcpy(buf+0,D1Xid ,2),buf+=2; + memcpy(buf+0,IPXHeader->Destination.Socket,2); + memcpy(buf+2,data,dataLen); + + toaddr.sin_family=AF_INET; + memcpy(&toaddr.sin_addr,IPXHeader->Destination.Node+0,4); + toaddr.sin_port=htons(((short)ntohs(*(unsigned short *)(IPXHeader->Destination.Node+4)))+UDP_BASEPORT); + + for (bcast=(toaddr.sin_addr.s_addr==htonl(INADDR_BROADCAST)?0:-1);bcast=0) dest=broads+bcast; + else dest=&toaddr; + +#ifdef UDPDEBUG + printf(MSGHDR "sendto((%d),Node=[4] %02X %02X,Socket=%02X %02X,s_port=%u,", + dataLen, + IPXHeader->Destination.Node [4],IPXHeader->Destination.Node [5], + IPXHeader->Destination.Socket[0],IPXHeader->Destination.Socket[1], + ntohs(dest->sin_port)); + dumpaddr(dest); + puts(")."); +#endif + i=sendto(mysock->fd,buf-(compatibility?6:2),(compatibility?8:4)+dataLen, + 0,(struct sockaddr *)dest,sizeof(*dest)); + if (bcast==-1) return (i<8?-1:i-8); + } + return(dataLen); +} + +/* Here we will receive new packet to the given buffer. Both formats of packets + * are supported, we fallback to old format when first obsolete packet is seen. + * If the (valid) packet is received from unknown host, we will add it to our + * broadcasting list. FIXME: For now such autoconfigured hosts are NEVER removed. + */ + +static int ipx_udp_ReceivePacket(ipx_socket_t *s, char *outbuf, int outbufsize, + struct ipx_recv_data *rd) { + int size; + struct sockaddr_in fromaddr; + int fromaddrsize=sizeof(fromaddr); + unsigned short ports; + size_t offs; + int i; + + if ((size=recvfrom(s->fd,outbuf,outbufsize,0,(struct sockaddr *)&fromaddr,&fromaddrsize))<0) + return -1; +#ifdef UDPDEBUG + printf(MSGHDR "recvfrom((%d-8=%d),",size,size-8); + dumpaddr(&fromaddr); + puts(")."); +#endif + if (fromaddr.sin_family!=AF_INET) return -1; + if (size<4) return -1; + if (memcmp(outbuf+0,D1Xid,2)) { + if (size<8 || memcmp(outbuf+0,D1Xudp,6)) return -1; + if (!compatibility) { + compatibility=1; + fputs(MSGHDR "Received obsolete packet from ",stdout); + dumpaddr(&fromaddr); + puts(", upgrade that machine.\n" MSGHDR "Turning on compatibility mode..."); + } + offs=6; + } + else offs=2; + + /* Lace: (dst_socket & src_socket) should be network-byte-order by comment in include/ipx_drv.h */ + /* This behaviour presented here is broken. It is not used anywhere, so why bother? */ + rd->src_socket = ntohs(*(unsigned short *)(outbuf+offs)); + if (rd->src_socket != s->socket) { +#ifdef UDPDEBUG + msg(" - pkt was dropped (dst=%d,my=%d)",rd->src_socket,s->socket); +#endif + return -1; + } + rd->dst_socket = s->socket; + + for (i=0;i=masksnum) { + if (addreq(fromaddr,broads[i])) break; + } + else { + if (fromaddr.sin_port==broads[i].sin_port + &&( fromaddr.sin_addr.s_addr & broadmasks[i].sin_addr.s_addr) + ==(broads[i].sin_addr.s_addr & broadmasks[i].sin_addr.s_addr)) break; + } + } + if (i>=broadnum) { + chkbroadsize(); + broads[broadnum++]=fromaddr; + fputs(MSGHDR "Adding host ",stdout); + dumpaddr(&fromaddr); + puts(" to broadcasting address list"); + } + + memmove(outbuf,outbuf+offs+2,size-(offs+2)); + size-=offs+2; + + memcpy(rd->src_node+0,&fromaddr.sin_addr,4); + ports=htons(ntohs(fromaddr.sin_port)-UDP_BASEPORT); + memcpy(rd->src_node+4,&ports,2); + memset(rd->src_network, 0, 4); + rd->pkt_type = 0; +#ifdef UDPDEBUG + printf(MSGHDR "ReceivePacket: size=%d,from=",size); + dumpraddr(rd->src_node); + putchar('\n'); +#endif + + return size; +} + +struct ipx_driver ipx_udp = { + ipx_udp_GetMyAddress, + ipx_udp_OpenSocket, + ipx_udp_CloseSocket, + ipx_udp_SendPacket, + ipx_udp_ReceivePacket, + ipx_general_PacketReady +}; +#endif // NETWORK diff --git a/arch/linux/linuxnet.c b/arch/linux/linuxnet.c new file mode 100644 index 00000000..c06b938b --- /dev/null +++ b/arch/linux/linuxnet.c @@ -0,0 +1,366 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +#include + +#ifdef NETWORK +#include +#include +#include +#include +#include +#include /* for htons & co. */ + +#include "pstypes.h" +#include "config.h" +#include "args.h" + +#include "ipx_drv.h" +#include "ipx_bsd.h" +#include "ipx_kali.h" +#include "ipx_udp.h" +//added 05/17/99 Matt Mueller - needed to redefine FD_* so that no asm is used +//#include "checker.h" +//end addition -MM +#define MAX_IPX_DATA 576 + +int ipx_fd; +ipx_socket_t ipx_socket_data; +ubyte ipx_installed=0; +ushort ipx_socket = 0; +uint ipx_network = 0; +ubyte ipx_MyAddress[10]; +int ipx_packetnum = 0; /* Sequence number */ +//int ipx_packettotal=0,ipx_lastspeed=0; + +/* User defined routing stuff */ +typedef struct user_address { + ubyte network[4]; + ubyte node[6]; + ubyte address[6]; +} user_address; +#define MAX_USERS 64 +int Ipx_num_users = 0; +user_address Ipx_users[MAX_USERS]; + +#define MAX_NETWORKS 64 +int Ipx_num_networks = 0; +uint Ipx_networks[MAX_NETWORKS]; + +void ipx_close(void); + +int ipx_general_PacketReady(ipx_socket_t *s) { + fd_set set; + struct timeval tv; + + FD_ZERO(&set); + FD_SET(s->fd, &set); + tv.tv_sec = tv.tv_usec = 0; + if (select(s->fd + 1, &set, NULL, NULL, &tv) > 0) + return 1; + else + return 0; +} + +struct ipx_driver *driver = &ipx_bsd; + +ubyte * ipx_get_my_server_address() +{ + return (ubyte *)&ipx_network; +} + +ubyte * ipx_get_my_local_address() +{ + return (ubyte *)(ipx_MyAddress + 4); +} + +//--------------------------------------------------------------- +// Initializes all IPX internals. +// If socket_number==0, then opens next available socket. +// Returns: 0 if successful. +// -1 if socket already open. +// -2 if socket table full. +// -3 if IPX not installed. +// -4 if couldn't allocate low dos memory +// -5 if error with getting internetwork address +int ipx_init( int socket_number, int show_address ) +{ + int i; + +/* DPH: killed kali for now + if (args_find("-kali")) { + printf("Using Kali for network games\n"); + driver = &ipx_kali; +//added on 12/20/98 by Jan Kratochvil for direct TCP/IP games + } else*/ if (args_find("-udp")) { + printf("Using native TCP/IP (UDP) for network games\n"); + driver = &ipx_udp; +//end this section addition - JK + } else { + printf("Using real IPX for network games\n"); + driver = &ipx_bsd; + } + if ((i = args_find("-ipxnetwork")) && Args[i + 1]) { + unsigned long n = strtol(Args[i + 1], NULL, 16); + ipx_MyAddress[0] = n >> 24; ipx_MyAddress[1] = (n >> 16) & 255; + ipx_MyAddress[2] = (n >> 8) & 255; ipx_MyAddress[3] = n & 255; + printf("IPX: Using network %08x\n", (unsigned int)n); + } + if (driver->OpenSocket(&ipx_socket_data, socket_number)) { + return -3; + } + driver->GetMyAddress(); + memcpy(&ipx_network, ipx_MyAddress, 4); + Ipx_num_networks = 0; + memcpy( &Ipx_networks[Ipx_num_networks++], &ipx_network, 4 ); + ipx_installed = 1; + atexit(ipx_close); + return 0; +} + +void ipx_close() +{ + if (ipx_installed) + driver->CloseSocket(&ipx_socket_data); + ipx_installed = 0; +} + +int ipx_get_packet_data( ubyte * data ) +{ + struct ipx_recv_data rd; + char buf[MAX_IPX_DATA]; +//killed 6-15-99 to get rid of compile warnings - OE +// uint best_id = 0; +// uint pkt_num; +//end kill - OE + int size; + int best_size = 0; +//edited 04/12/99 Matt Mueller - duh, we don't want to throw all that data away! + //--killed-- Like the original, only take latest packet, throw away rest + //do _NOT_ throw them away! + while (driver->PacketReady(&ipx_socket_data)) { + if ((size = + driver->ReceivePacket(&ipx_socket_data, buf, + sizeof(buf), &rd)) > 4) { + if (!memcmp(rd.src_network, ipx_MyAddress, 10)) + continue; /* don't get own pkts */ +//--killed-- pkt_num = *(uint *)buf; +//--killed-- if (pkt_num >= best_id) { + memcpy(data, buf + 4, size - 4); + return size-4; +//--killed-- best_id = pkt_num; +//--killed-- best_size = size - 4; +//--killed-- } +//end edit -MM + } + } + return best_size; +} + +void ipx_send_packet_data( ubyte * data, int datasize, ubyte *network, ubyte *address, ubyte *immediate_address ) +{ + u_char buf[MAX_IPX_DATA]; + IPXPacket_t ipx_header; + + memcpy(ipx_header.Destination.Network, network, 4); + memcpy(ipx_header.Destination.Node, immediate_address, 6); + *(u_short *)ipx_header.Destination.Socket = htons(ipx_socket_data.socket); + ipx_header.PacketType = 4; /* Packet Exchange */ + *(uint *)buf = ipx_packetnum++; + //ipx_packettotal+=datasize+4; + //if (f2i(Players[Player_num].time_level) && (f2i(Players[Player_num].time_level)%10!=ipx_lastspeed)) + //{ + // ipx_lastspeed=f2i(Players[Player_num].time_level)%10; + // printf("tot=%i,t2=%i,time=%i,avg=%i,a2=%i\n",ipx_packetnum,ipx_packettotal,(int)f2i(Players[Player_num].time_level), + // ipx_packetnum/(int)f2i(Players[Player_num].time_level), + // ipx_packettotal/(int)f2i(Players[Player_num].time_level)); + //} + memcpy(buf + 4, data, datasize); + driver->SendPacket(&ipx_socket_data, &ipx_header, buf, datasize + 4); +} + +void ipx_get_local_target( ubyte * server, ubyte * node, ubyte * local_target ) +{ + // let's hope Linux knows how to route it + memcpy( local_target, node, 6 ); +} + +void ipx_send_broadcast_packet_data( ubyte * data, int datasize ) +{ + int i, j; + ubyte broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + ubyte local_address[6]; + + // Set to all networks besides mine + for (i=0; iCloseSocket(&ipx_socket_data); + if (driver->OpenSocket(&ipx_socket_data, socket_number)) { + return -3; + } + return 0; +} + +void ipx_read_user_file(char * filename) +{ + FILE * fp; + user_address tmp; + char temp_line[132], *p1; + int n, ln=0, x; + + if (!filename) return; + + Ipx_num_users = 0; + + fp = fopen( filename, "rt" ); + if ( !fp ) return; + + printf( "Broadcast Users:\n" ); + + while (fgets(temp_line, 132, fp)) { + ln++; + p1 = strchr(temp_line,'\n'); if (p1) *p1 = '\0'; + p1 = strchr(temp_line,';'); if (p1) *p1 = '\0'; +#if 1 // adb: replaced sscanf(..., "%2x...", (char *)...) with better, but longer code + if (strlen(temp_line) >= 21 && temp_line[8] == '/') { + for (n = 0; n < 4; n++) { + if (sscanf(temp_line + n * 2, "%2x", &x) != 1) + break; + tmp.network[n] = x; + } + if (n != 4) + continue; + for (n = 0; n < 6; n++) { + if (sscanf(temp_line + 9 + n * 2, "%2x", &x) != 1) + break; + tmp.node[n] = x; + } + if (n != 6) + continue; + } else + continue; +#else + n = sscanf( temp_line, "%2x%2x%2x%2x/%2x%2x%2x%2x%2x%2x", &tmp.network[0], &tmp.network[1], &tmp.network[2], &tmp.network[3], &tmp.node[0], &tmp.node[1], &tmp.node[2],&tmp.node[3], &tmp.node[4], &tmp.node[5] ); + if ( n != 10 ) continue; +#endif + if ( Ipx_num_users < MAX_USERS ) { + ubyte * ipx_real_buffer = (ubyte *)&tmp; + ipx_get_local_target( tmp.network, tmp.node, tmp.address ); + Ipx_users[Ipx_num_users++] = tmp; + printf( "%02X%02X%02X%02X/", ipx_real_buffer[0],ipx_real_buffer[1],ipx_real_buffer[2],ipx_real_buffer[3] ); + printf( "%02X%02X%02X%02X%02X%02X\n", ipx_real_buffer[4],ipx_real_buffer[5],ipx_real_buffer[6],ipx_real_buffer[7],ipx_real_buffer[8],ipx_real_buffer[9] ); + } else { + printf( "Too many addresses in %s! (Limit of %d)\n", filename, MAX_USERS ); + fclose(fp); + return; + } + } + fclose(fp); +} + + +void ipx_read_network_file(char * filename) +{ + FILE * fp; + user_address tmp; + char temp_line[132], *p1; + int i, n, ln=0, x; + + if (!filename) return; + + fp = fopen( filename, "rt" ); + if ( !fp ) return; + + printf( "Using Networks:\n" ); + for (i=0; i= 8) { + for (n = 0; n < 4; n++) { + if (sscanf(temp_line + n * 2, "%2x", &x) != 1) + break; + tmp.network[n] = x; + } + if (n != 4) + continue; + } else + continue; +#else + n = sscanf( temp_line, "%2x%2x%2x%2x", &tmp.network[0], &tmp.network[1], &tmp.network[2], &tmp.network[3] ); + if ( n != 4 ) continue; +#endif + if ( Ipx_num_networks < MAX_NETWORKS ) { + int j; + for (j=0; j= Ipx_num_networks ) { + memcpy( &Ipx_networks[Ipx_num_networks++], tmp.network, 4 ); + printf(" %02x%02x%02x%02x\n", tmp.network[0], tmp.network[1], tmp.network[2], tmp.network[3] ); + } + } else { + printf( "Too many networks in %s! (Limit of %d)\n", filename, MAX_NETWORKS ); + fclose(fp); + return; + } + } + fclose(fp); +} +#endif //NETWORK diff --git a/arch/linux/mono.c b/arch/linux/mono.c new file mode 100644 index 00000000..4ce1715d --- /dev/null +++ b/arch/linux/mono.c @@ -0,0 +1,20 @@ +#include +#include + +#define MONO_IS_STDERR +//added 05/17/99 Matt Mueller - needed for editor build +int minit(void){return -1;} +//end addition -MM +void mopen( short n, short row, short col, short width, short height, char * title ) {} +void mclose(short n) {} + +void _mprintf( short n, char * format, ... ) +#ifdef MONO_IS_STDERR +{ + va_list args; + va_start(args, format ); + vfprintf(stderr, format, args); +} +#else +{} +#endif diff --git a/arch/linux/serial.c b/arch/linux/serial.c new file mode 100644 index 00000000..9a3af0d0 --- /dev/null +++ b/arch/linux/serial.c @@ -0,0 +1,216 @@ +//added 06/09/99 Matt Mueller - fix nonetwork compile +#ifdef NETWORK +//end addition -MM +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "serial.h" +//added 02/06/99 Matt Mueller - allow selection of different devices +#include "args.h" +//end addition +//added 05/17/99 Matt Mueller - needed to redefine FD_* so that no asm is used +//#include "checker.h" +//end addition + +#define BAUDRATE B38400 +#define MODEMDEVICE "/dev/modem" +#define FALSE 0 +#define TRUE 1 + +//edited 03/05/99 Matt Mueller - allow reading from different device +static int fd,rfd; +//end edit -MM +static struct termios oldtio, newtio; + +void com_done(void) +{ + if (!commlib_initialised) return; + commlib_initialised=0; + tcsetattr(fd, TCSANOW, &oldtio); + close(fd); +} + +int com_init(void) +{ +//edited 02/06/99 Matt Mueller - allow selection of different devices + char *modem=MODEMDEVICE; + int t; + if ((t = FindArg( "-serialdevice" ))) { + modem=Args[t+1]; + } + //edited 03/05/99 Matt Mueller - allow reading from different device + if ((t = FindArg( "-serialread" ))) { + char *readpipe=NULL; + readpipe=Args[t+1]; + rfd=open(readpipe, O_RDONLY | O_NOCTTY | O_NONBLOCK); + if (rfd < 0) { perror(readpipe); return -1; } + }else + rfd=-1; + + if (commlib_initialised) return -1; + + fd=open(modem, (rfd<0?O_RDWR:O_WRONLY) | O_NOCTTY); + if (fd < 0) { perror(modem); return -1; } + if (rfd<0) + rfd=fd; + //end edit -MM +//end edit -MM + + tcgetattr(fd, &oldtio); + bzero(&newtio, sizeof(newtio)); + + newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; + newtio.c_iflag = IGNPAR; + newtio.c_oflag = 0; + + /* set input mode (non-canonical, no echo,...) */ + newtio.c_lflag = 0; + + newtio.c_cc[VTIME] = 0; /* inter-character timer unused */ + newtio.c_cc[VMIN] = 0; /* don't block on reads */ + + tcflush(fd, TCIFLUSH); + tcsetattr(fd, TCSANOW, &newtio); + + atexit(com_done); + commlib_initialised=1; + return 0; +} + +//edited 03/05/99 Matt Mueller - allow reading from different device +int com_read(char *buffer, int len, int timeout_value) +{ + struct timeval timeout; + fd_set set; + int i; + + if (!commlib_initialised) return -1; + if (timeout_value==0) return read(rfd,buffer,len); + + /* Initialise the file descriptor set */ + FD_ZERO(&set); + FD_SET (rfd, &set); + + /* Initialise the timeout timer value */ + timeout.tv_sec=timeout_value / 1000; +//edited 02/06/99 Matt Mueller - microseconds, not milliseconds + timeout.tv_usec=(timeout_value % 1000) * 1000; +//end edit -MM + + i=select(FD_SETSIZE, &set, NULL, NULL, &timeout); + if (i>0) { + i=read(rfd,buffer,len); + return i; + } + return i; +} + +int com_write(char *buffer, int len) +{ + if (!commlib_initialised) return -1; + return write(fd,buffer,len); +} +//end edit -MM + +/* Hangup by dropping speed down to 0 and raising it again */ +//edited 02/06/99 Matt Mueller - added the standard ath stuff, since the baud=0 didn't work for my modem +void com_port_hangup() +{ + struct termios save, temp; + + if (!commlib_initialised) return; + + com_write("+++",3); + tcgetattr(fd, &save); + tcgetattr(fd, &temp); + cfsetispeed(&temp, B0); + cfsetospeed(&temp, B0); + tcsetattr(fd, TCSANOW, &temp); + sleep(1); + tcsetattr(fd, TCSANOW, &save); + com_write("ath0\r\n",5); + com_flushbuffers();//this should (hopefully?) clear out the OK and such. +//end edit -MM +} + +/* Get the status of the DCD (Data Carrier Detect) line */ +int com_getdcd() +{ + int msr; + if (!commlib_initialised) return -1; + ioctl(fd, TIOCMGET, &msr); + return ((msr&TIOCM_CAR)?1:0); +} + +void com_flushbuffers() +{ + if (!commlib_initialised) return; + ioctl(fd, TCFLSH, 2); +} + +void com_setbaudrate(int rate) +{ + int speed; + struct termios temp; + + if (!commlib_initialised) return; + switch(rate) { + case 9600: speed=B9600; break; + case 19200: speed=B19200; break; + case 38400: speed=B38400; break; + default: speed=B19200; break; + } + tcgetattr(fd, &temp); + cfsetispeed(&temp, speed); + cfsetospeed(&temp, speed); + tcsetattr(fd, TCSANOW, &temp); +} + +int com_readline(int timeout_value, char *input_buffer,int len) +{ + char c; + int j; + int i=0; + struct timeval timeout; + fd_set set; + + if (timeout_value>0) { + /* Initialise the file descriptor set */ + FD_ZERO(&set); +//edited 03/05/99 Matt Mueller - allow reading from different device + FD_SET (rfd, &set); +//end edit -MM + + /* Initialise the timeout timer value */ + timeout.tv_sec=timeout_value / 1000; +//edited 02/06/99 Matt Mueller - microseconds, not milliseconds + timeout.tv_usec=(timeout_value % 1000) * 1000; +//end edit -MM + + j=select(FD_SETSIZE, &set, NULL, NULL, &timeout); + if (j==0) return 0; + } + + do { +// j=com_read(&c,1,0); + j=com_read(&c,1,timeout_value); + if (isprint(c) && (j>0)) { + input_buffer[i++]=c; + if (i>=len) return i; + } + } while (c!='\n'); + input_buffer[i]=0; + return i; +} + +//added 06/09/99 Matt Mueller - fix nonetwork compile +#endif +//end addition -MM diff --git a/arch/linux/stHqFIq1 b/arch/linux/stHqFIq1 new file mode 100644 index 0000000000000000000000000000000000000000..dfc33ca765774cb1139886d6312cf0c42bfef22f GIT binary patch literal 86016 zcmeFa3t(MEoj*P|4W*V!TLA$D2~eP|rOmr(0+`3WO(SU%@@NYPmo&L)Qt~4A-cp3h zg@O=b5!}VMYr!X|D~LQq)F3Psaed$m6?ZGky3uy`SFwu~S@QpUzTcU1=H8^xqW^vN zv^VE-zVn@#@63GXapug-_vEuWN4k2?nZ2wa`&v=DqGWkRS$Pr2h2rG@Ehwlcsjwa{ znQe?&Xv~b8!e1e1)BQe>XAFP)%1z{bKl%UtmshgU*dJ3F?;Gq(#gnPdk(3FZP1n$1 zJk>jrNcIl(cbmT9&GG)e!Sv>MeIm8`ikj|jxFkJt^KfFYZK&(gM9L%9^$#TzQ>bl; z!S0sM9M;xESE6rI!qTTkzCPJKjY#S4VTrD95aRduCsfd6D92zTb@|Z9rNT5UaSo;j zOaoGbdpw;?j3k36%d4r{kQhviboR$ppw>iZ_Z6ml1QL!&SQ`?l_`nr$_y;B4>1Bs? z=^yHXZ{Hz1*O=!Lk_sE|?o4&6Br35=(Zvi5BGd#ZD+?rvjEv_J8NWu30>y(yLeBLg zL!I4Soyk;|ALfPTLl9)&U@9?Ub0dqF99_MggBud@?nF;#x*uv2=Jg0NNrH;^^!2OM zLUJJm)Shm$5*#c02D?}GjU-dSQ&VDd_#nz-3^Qu!P*@M829}nVm!qB)6&9lU1%Jy+ zOYu}xQc^5+@RHeA#~N2gA`w(Xy&`6Y37?D^KSSxIa$9JQG)I_@(SLs8(QTV}-@1F& z#7mQtlUpC#+e;4nFz@>D^od&^dug)ls@ECQI|nWsBjV;5=wV*Ahr>dKCmx-}&~QxMHUwM?(;nB@w_pgvfU-IEfzd!V-96_o6uPz#%vN?CiriGoy!x&eA_+29SWWjZUPZ7LM@Tr0a1)nDP-GZqh#(Y#THOZKJ1s4l`QgDgj zX9cUa|4FdQeAGjb|^a8z)S;F#cg!7ByF1=kDSBzTqJ_X=(h{7J!0f}az7p5T`Rw+cQ1 z6)a=g1eXYI7ksYZHG;bYpD*}I!9#){7d#^P8Nq46F9^O;@LaSD8FQ83#e%OE921-o zyk78D!CM4hC-}pHZxH+?!5Bc`dQ$Kdit|U0Nnsbtx)X zb!n~O1>*No!KVqnTJY(DZxeim;JXAb7W@stO9lT>ue1d?>&MS3BFfwEwGbworme@WcG2=>AN652D=!N34O|Z5(B)D)s;f3SV$A$mf;`eF6PYQls@OK3J{B!1pGTiUsW$1KW zUd24@`}Oe^;K`T^^IQZ@&QE%Nzv5xv@4tHVljk#>1{X|_-g==I3Vj2xlkF-G-{#>b zg#WmR3&_dy4?@>E`v<`bgk|0v7_ZjZ#e%iY($V>ig6`t=>6?ZBlM>GR1Pe5KJe)j+ z;qMWLF~Nt6YUj}!ca;Hi1?OVFJRF9?sYn-Nrlj5$Fc@Ym(xji5VzIy(A?_d|bZKlC4X^xt`S zCd75&p9q{WnwCPr5D?c&!2-<{f=|>3{B`n>;P5t&|Bc5pOx43O!RqzPf-B_V2Od3v zF{ta8{V=Zs-O1_GKMeW;bF>DEztJqL^3!nvei(L`F9|;)v{%&l_|1-ta8AOAT(77p zz>~u#8y&?ku2am4fPO|WK91t$yCtBXX*w*X4DZ12G00G0-fF2j#_r~myl`}xWxYcK ziDlixz010bH_MOj#>?a-c$s6`(A8BO?;08y#_LS?QczQssfC40iWZ$cBDbo-!eYFm z*b7fZ%Y&=R;8kiw_=}alcu`ehRZ;QsD$_qSxS_y>R&rpWr3aIJ8wL~IfxlAEpA!Lh zNKq09;o_R&x$Gc3XGvQgdgP1Q)T^p6jNL;v(Gu1aX_kk9`TA{1b< z0`K4bm7GgpF0$qmMdnWIFB^BiWnB7`dymUp`(qcb$goap>eeX=f zS!(61+>p9-k-40uY>6mI5K9)B?!HYzDi*%tC2&YqT$Ub6`Nc4j7|1Dw{?H#veqk}f z_xzPC(&DrJ@aRe}JFk%X)D^>1vt@l>D#zs@lOK<#Iq}2Rs={VKQPCnpveY4=YaXC9 zN!G@z0$E~ni$p4iup)KHt}JP|FAhSf$=W+=3h*W4=JiehXpfYim+BZ04!!KsaDyXXQ z_`p!NDsaV;VkXQo4?^uPb?i)+r4RM=II5;fBJB6bOp}#)IFO@Q3sCYt8Ppj>sYNLC zk^a5`7q%u*1SC1gv0_c7q&*DWOJq+nAeU$=OOUE$MLfQVEgn*V#B{n&xT>g%D#2P* zUWzs^jycq@7)msSB3zeG*Cdu8O^e~ZnAw=>8*tfJqG^(hNnXCb-(_QoDyGmef7=z% zRWXI$(;Xk^OkOHFU!saBX$3u*(5g^s3y;Y{2NRF?bSLAi$V^>nR_aQSJfwI9(^phj ztSP)SafQw0QZIdd!(H*PxJp$qMfH(@uECV^qU9*EszXpTrA)Rh_?~38FRwVAQ|Qkt z(w-#dg1y+ZU_}j_Q{b;m^FdW%a44j!7KoE*1yOPh%S1w$i9eo-U^_Rh{Lg zd12#84X0c!EemuyXako^8_1T>gbm)V}=`kj-m2~+M&0D6~)&AvZ&_o(Ax;6!3Yi6QpF|P3d zQFD_0aL`JCYEy$WhK&Ts%t9oRskBuPL`@RfCKJlU5ePYe>hD}Z3b%8I;w`GkE9 zsM^XP9ioKVS%R#M42oLmw)caAGT)^46MoytfzAw(VUEyk^#Wbf2L&2QZ0JkkLy$S)z6x-HF6O!$s zwX+lj>6%*s>Ot%NvY*@^tZ|F|cnj-3+<3A`}&s zBUxO!nX#irge6(bf|Q=Jw4$n0otKoNIj*RZVuBNdDk`tSSMRv>jusLF@`@_X3}j1F zm0cG21dY$WPHzvg4T;M{0{W^Re0WD2Q7kPu-Xl;$7vqV|bPt4w4reJJ-jMo+USpgG z*Vf^CveYiTOm$(Lg#`gg5wt`!wzz~U%8?R#l9dgOF(#r&-HPb8IT>$gj*Cln5|C42 z65N|#ydD`c*we>24^B>fWxE{BqGqJ4{b+0vXxOqAmx*wN&=Bijn?E?Pwn<*Y2ODkM zV8SJ6%dJc3Cuq_SPF$O<$eLiZSgehJW+gLipmXHX#0V>)Gz4g>;)D2D4*f;F68#`u z-xA}=_30jQfk4n4=Dn?v@!=tiADJ#&Au$$qMS`%Ul#)fLM?L+W8yu(9JF>~we5vH9 zplA%W@d{i}HD%-t7p?7q%lghFYP@>VDo>}&NBUBUxbJ3be(2~$X6t|G=0#_l0lFdS zSwR*vgNm!1ljo_pOd21$Bs(`{3sPJmO_2D)s*&_?R+uHlL6(S5FVK=QX^?DrAqS;= zmXuVe6nKa38?;5Uq?FwbMB}=M!692LrD%&tL}ShOCr7Q&7}+RcgvECR9a=3ZL(@e5 zuJj11OMiL*!Ak>IRtg;|uZnLXvTO5X5RA%4B%9o=>LQ{tSDbHHPVOa8(WRF?sG~UYoaPuLR;-If=a96 zLLaocYg>h|A@gF51EnLHju}YC&5i`_6kkNJq7I}SHhF%glc5*{N@gjjsdC{kVgvnGNrV#K7*VmO` zh|*^zi^`S4Wo+xwF=(4E<%9)k$-W_J1`wTwjym2GaB1Vr^>6FbsT5RzzO|?-sz~nK zoN%OtNVrXIph1Cj61~VKc}OWj*)+A9hcc2av;$PB8z`8Hs(!AH%c8RR=FGt%mr-W+X-Pg~{bFBdzcKZ7b(IAR>zg_j73d6jfqb?qDk?8n z7)`9l8(aY#mo;*Zd=b`BZ>Z{iez2m()Cy?x^!?Tm7o`T zB!eRUg=dh4lowwT2A~kZhq(g){9?$D&ND49zYWT_Jo}t)?>?^^KnOvC5LN#{M#trifm3`M^CG9B~qV_N-mRHNLk0nJ?uXS&O$ z=bPV6`aIbyK^eXu1D{!&vXmSR(uO2PwS(QJ9jyVFIdG8G+rvPq9yZC!iMp@Z`A+TJ+M37NjosoxiK~Q-Ufg|f6=@q0SQCww`2L)VZ>C6-IpU*p%i(Jh6 zQJTgG6utn@yg!DuY7x}6y}YBITn9`#*F0m`5G+A{we`ovd`_6~_m$UU~92 zU%(^QF!$_;?a4Q{({VJm7f;U{!?5OUi|uJ?)4(2QU@uRmXEU&BaPB%|N9-AD2ROII zo@v<@+i7{hdHwj7#bnID-HR0qo;5g$epk`9FUz8vvDkB;0HY~->g&91TRm}8{_Gp0 zZ_KaV`r={l`hDQ5Xnb4ZTNhp&uDd>K?V7f+EpzshZV`1H0q$A?Q6m5dX=6Tx-8ge& zBurQV6NaVQ$R%)j@@g)94L-B82&@}tZj0?}k-R~ANB8wS@~v4tqp{~H%XIm6gyb87 z-?ikH>nGElJ7P}}BSYWX47_nLc_lJr6=n4r>HY zJbH`BQ-C5&&lh_@f^FnulNT@bT!jT$pEjc!P(p1iseF$=e+k-{{dl=HdH1?DKzjKXjkx zUp$^S=To-3Y;0k?%RqPXbO}$x6rLMAp4&a_$Ms|JTOfXS3qD!!4D<&XbBf^O1fME+ zso>KDuM{lJlzE3>_9Vt61s4k*6Rhi4?+~ml^;ZQ;qicRBm?J!6b_-@tgnkqQv5Z}r zcA{WiJAbxd_EN^Q3D&jJeS+U6^s5C|3%*Tojo{A4;5xxS7aSG*JHau*hhxy0 zF)Ib1B)DF1xnTB?#xx7o{O=arBy?Rzf1conh2ARo8NqFWe=oRQ@DUieWXu}DrwV3| zYfP2kA;Iq!JR{cgc`3f>|3F2TC4{Bwf;UFd%+_{cXUwZWU$An?7^6*t2exHZ$@$mON?1#TUyz3zO_ZQA=EdS0Jt-rbtfSks> z2XvP|cM8vm>VUs44<8k}l8?g+V8(L1-^0n{Li#yaM(%jN>ETHaufoKJi+8<;8MKSn z$6LVT!u081@#u3g0p)nk60C3DbKXKa-{$pl;V&u(Wq6y1$>n&G`=Q_L(eLu`xQ7ic z7tVp;y`JAA(FAAc3D@6yxb_s%b=2G=Sb0uB(Pm7uJVXU6{fmOv$isI%Itfm;fdyec z+~8rK=c^w52Ojo$4nsF^EeZB=;hzF}#uN*6gIJt7Jt6pf!Pf}Ze&l0Wmoh5k;#qk`WjcuX+=xV-wD(3RZ1h~ewi^41Vv z?%`9Hg!DT-eEOLo{hh$q+Hh|5=+Aoit>}_nT<`HPy*b%-f$qZb>9dxFetmiy=#Ib7 z!#>Xq`=Ni;qdyItp(kA5Mz@g>WXy3G$~#PwlN0OkgLr-VN{{|d@wh=-r?uZjkc`mLadIF_xPFdKGX6 zDc^(n%T$hA{^SAPbdMfyY2c@X|1b{8&r9yJ$&{t?JfZMEtyi}OH#7&v3@l`^9DasIK_PTc92 z7t>Ds1o#)2$4N31z}wB=N!p*cm}!sHDIKrAW}e{3gYTeG>zDqc=G*udqE{5}Sz&s= zYfq^l&-YAK!1H~3vHbSDa&AgSQn_*JsMQ)kAwkq@5C3u8BD>RMOs$O!hrzy+d(dtvYlffg?mde&YT zP#_R@QDL34E;@ddtuPw$p`9>)xt%alI=MSxq+tGA?Sz3uuf7uoOnCbcO*`J1B;&xu#UTGr?o!J2Jj%u=>jWBd&E#@6nWIr2W=*o>Syd&XLHo{0l za3K3&-1cxe;6%4DWp4${+8dKKK;=ePH$DwUns#Sz&Q^R-*=9i?yWJV@i`;A_G&G07 zW_%FYP-XAN2a##b-Hs13k`A)JA0I?+!^Tb)Y{LmQNw(=iV;t_vCtcI#Z_6iD6UTk|ZVNuCnmTU}K8c#P>`nNjYx20K zCESHix+W02zP)Yuq}%QJNVwaF52`zf1l(C=>TR5sfwOL#W_BXJgX=l;CB$vSXPnym zp|paX_@pueb-%mLBap_-lgkAr-hO=2nSWphzc_f|>sEafyuTwKUhGzVOGTVpk=D~p!MQ?$Mn55@Y>TC=vY#KP$6%2I`G zvGZDL>duX|SC%QkKA|_yIlv$&eIA2^a!Gc^dpZaD`t>NG5+@*3km8XE+v&KElNGf* z;Kq(PvSJ919mt?^V;6P;vzztmZ&8WeWDMoT2@BX|=mN!-k)e^!4czYtPtbd91(MiR zBGP1qkG3Nj@9f6`ecYRh4$=+qNgsxcvTGILpn(n>kD{U#Hg;^=TTxz!*b6i|G}wvN zZT0cy=33-2QA;d#E^?SK+T7IM+T76|L*DYauD!LRsjjj@`C6OTonML6&_x~auHn3` zt!ZelL}Yx9HMdrB_aZUrHI0px+>g%Zl?_dm+|^Coc79VOPjr%pj@J6h;zH~Xr%P*F zdu3@M_89UZ*4lbrN30`OS;3v~q%<|RHPkoNG(sBgJ+CqY$ql`(w9xh77!Oe5y2%&& zP~GlKOM^;Ec?BCt$=o-Djh7G_{S)4#kkuHtY{pj8O*r7hZvC}v;vI$Rw*QihJ&CCi z>`3OW*F`8MC{1yd=Meg_JN@bAA43qF_0a{FAT1mxK|4r`he60jSWDZKa7Q58-KJ!f zY9-yZl^myUkRE6%2U?-FoT&$hX@Wdm;jk;wR<}Cd+EBl$y^VDe4|T1vXsoHdp{B77 zY7>tOt+}ZwR@aW&S!L2)BMI&fW*(wOKzxkODmg;M&`jT3aki2YN}W36ye6eU2;IS( zQ+GR)1Ix70a1E+!<(x~O91w#BYJ(mnf#_McD*EF?gBY0mn~2%837h7T=3JE-ay69F zvw(A|y**kbtJY(z<7cJTdK4Sl23zf=;-Q0MUasnBkGDoE3zrC5i)x~%H40pe%tLmf z5v++uTjMpT5Gl&RP7^mICS8i=z&1_sIMh`J?V_&k03MH_Gi7;D=fNYR_RYz_KaT0N zvj}0BotulxtS7ApNQBgb&=)wS`orEh6^9BdaZ$s($h!NddP=|si}i)fQC~=_=L;ND zy3q3N;fUSyg?;c-G9~SDlEZkFFgs7u z)8u5RAv|?Ud~xXRMHOlY^|`LOsjYn)t(IXul#+w^Y4n<-NCeK#cZ%GBVsktx5>!mX z6bhG8Om1~+b1iHgh7L{w7B!p#v z*8ydNvZ!P^4ZQB7b&dOhjj(YBiM|+5Gsu^1xh^=@SJ?R%?$|BPb;~}B_sq;+80pAR8b=u+r@4oj zhi|kq8cju(Q1%cx41EG`BcaIRssj7Yq1f#CA>)1`O)*laq{c0RVTvL#($m>BRX8Xm z27#|2oIP@cfk89F{IUo5AO|2R#&MDo9Ma5lWZlVb(z`Qz7(S20!zmLoybuSTsUZ=2 z2`j>BLP5%=m0D7V7Kj3IS`8uV`C#tQH_*}YB#YtF)r0f@(y1XFzQ>aUIg}8u>9#mDV@V-N! zEPOY?D>p(;G_~aF4O3x*8C|AX*wQ&s7)-UDwRK#SwGP2PeE>RUvp@U9(Om zQgk*41&5Mn!8NzG$76M?nkywWe2O--)z#olQ{*F|?fka(n)XV3ySDt%n)BNmR>vxf zB!03q#oCoeA|z!c^F8p<9%}?kB_^tE5N%8#&WyB=46ZHKx+d0IiIb!(v8g5?mP%GI z+_kHk8`^Af@tNV21zy@2ZFwMh>)T_M%L7NuAJrp*<$-g1`}vIxP3Klt1T1YGEm0`f zia@Z~x>%hRj8jimvc~56hNgfVB&u$8G$4xZP{7#AHb=y`$Ocf`uyQ5U)(aB}b9`aG z%8Z&Lhu&K?v!Xf$X2a|NU*J#%Yao~tz)OXli{$Bv=zB{sBgn}~R&w`xM7DB|j{~5h za?;Wm6v{MXx~M#@EEPgR+m=1C_;=$>M#DiGSz!5QmN(S_-LP&v3k=&v94(5btK0TAHqa{NIZse zQ(uE*B-A$?9~#Ed`t1wLXCZ@4esm&I>$pihSLe%9Cs;2|guq|60BHN$yUW%BaQVT|&qL}BDeIL9_p z#(mj3;R+XIPpbVEYs1Y?X3-U?Xf6E5hOP?+Yb-R<#7#qxtdy>#9Sed_?%FO6;$Z+$Xnwc@g0cI zEv;Bw1y}Tde3Y+CkeP9!Pauhl+u9l~h}AZ5uA5WYHpT2^G0n{xS(jiu)vao1jLI`Y z@%B1?O5syeJ(~TNHkV>hnpZ*Vm#wZStEPhxPA_4W70upQd=9^&j(%=i*}%(>e0!F6S-TFIu%*+ zXjN--Q*%d~kPq$F+CW*GR_txhB{V>Q#twE+K!@=P;oA-q$9RE zj#0^Kt2rt^p5tq38ar$SvgOfGFQ3KKx28dgR|zV5ZC$*!rp@|Oxj~9HtX3u!8x)Kd z8!ea0O&Tg+lNC;-uWN2>jIWK!*B}W1Z{ZX=c3wxr8dLxjl9Dwov2`u27*%5Wml=ZL zA9< zKCa~GO(>dz;kB#7H$jr?wg_Xs|9s75w4uc^dqg!Afx zbDze`RZu^sxPB)u59Ey_J~SSv0_CCLLTe-~l%BNJmE|gYJF5E{DT;EHynPj#7&JHK zD!D$Q8Cn^Ouf&&O)>JrZQtD&v^{w$%v_%(a0b>ZyB!J$s)~7Gmq{;X@9u)C%O%;ao z9!=9@qm8mV=%{ONZjCn}gKISQ<(fXrb8hT>Rl()9LP!FTb66n|UyX0i%WX=PZqp}8 z#uOdJwE@+%w<9U^#*cA)0h!iO>hf~U0PAzQ))%iUo_A?w8k$zc&`4L}?DJeF+YI7+ zceYb=9a_V9o3wP56`D6qU?#b_wT+#{%E}7O51-!L)Yw#s@8pc9Wfd|=TA|7c&5D{e zK20;BraiWg7YoNJp~qn4nuuC9$Y+JOS60vJfs1+i9i!-Xm+Izn5)ifpHj zZXOvTa@mgEQW!A@HwdF`72mTdy6et`ARH=chZl+p+YzM3cI6!+zJ{XGc6i}hVH-J4 zQXUn!sWIM&&R$5i{{{)`IFzDU3rdqdTfJ^X+t{uYtI>@p^L3V_BCo4$D~mTYwqP=^ zdF4vHffivlf~n1RsBOUb2cQ1}m&O)Mx4}m_%G!3_;-j$ztaMNxzN$3F>TBw-{KfX; zs!?wIg&~r!=ZJmG7(3^@wQWeGUioo-@#}5V;RkGe5rghO3U(-5q<%M&|In;aFgZ|OW1R~ip{Xx>%OHNO_gZ@F(sY^~F z+k^f=1^(MM5O{QT&6Cui%Xav}p7~GJ;nfgj%ROMCeFbb69 ztVo?(d!!=ZjkTgmBWRZ|R!YWDt)eQLz=8XNo$?Wn(qKUjhDs~Sk+Ad#PT;q+BFvhC zD9O-}Tq-!{4S$$ZX5MoG1-7Q}={Cr7PM}mM-H9t%(u4Iq)JQu^!&m>nKj*6vC?~~n z!*cE%Wg5T&o`Zg&)x9>M9UqKRsC@i9nj1deadQntVC+KeIaosxP*0s-!gNe%8~~-L z$K|V`2!stiT)a@?2q$j>LlK};{lz&;)qDGgxonX+Hz-y zjzQ?5db0@lDHz<@1*OW1d7&ISgonOiDkJ;^>PfJrq8uoABY2pw7v( zVfDAFti%eP5uI(qUgVH46bc4O#V10i8mKUS zS&1}o9k@bbu_C!g3IGW`zh3d#gyi@{#C9R$i(Rd0o zl5GQX@rHp3g?XD(05(b4+Tya<<*=~^NQSw!1Iym=DAtW^UXOGuW1uuxUo5%Cq{C6- z#@>9Jn$4h169Rz=lVEcL9u36bzxJ6|fW% zG#y^xtD-vrCOaI@|9Z@=7Nmv>?DCU>!UGAx^UwG(vT@OKLh;o@$nh`ogJuI+I=#?d z5_0^*tdxr%T8?Eb1wBI}1?xwKI=j2@(RXTiIsPRNZ2loD>_qe{NRi`zn)HJsthrM{ z68}tfqPw8`3glT|mrKBDg{7OP@Ow!YsPUuW#A>Gkn&B$wP9(cV`i8Omya36!X*rD{ z{ZBTL@@Ax##~<;W8(!7;$vHH9z{T@;c%6*j>jdeavv6otH9X4MJs{=d$Mdsr44{O^ zqilFx;($I1A0f{~BENIqA743m4#&@3h~YbLq!Bi}20a7W z&?}hr{B-Pbd1D!m8je!ncd$F<`^Xw9z>IL$rk;_Zfn3WkEc-lE*af)LzRP0Xq4>*4 z$Khc0e4cA?5+9zCS(ot{d}Dl`Z*U5pK5yq8{ys%I{QWKO2>db9;r~f{f6mfpqpTV4 z3Al@089t)`-fo|1pNQdgkdE*+@)_Y=$!8o?_5t1@&z+=0o^SCP^8D03|B`q3f0lIk z-^DxRnF&20{~X@oJ|B0wS6X_trN=D2g?ISdL^|TXhtD`f@;Tnoj!|c5zox+6Z-h*= zZ*w&KL~xdMAs8ZPJFnyYSYtAfJ%Xb-w}VE1RF?J0?rgg^6)+rGP*A|*w!FXPrKJT0 z#ibR+xZ!$ryEjWNfKa$fW+qVJ#Pm!|!owjXmfo@#0`)IWOZQEk=VAiJv_Hwp; z%)B%?srHRfgl!x1#7@!J$0q(XISG3>ym-dyJg6tz3)+w2#W5H!U|PwKgqZ@i0kuSo%}@q5C|$Jf6ey!!TC>PiHe{wa^PBhHk+p3%*kDDS~eie5&A2 z3qDQo*9D(0_(y_^1n&}DELd&k=xM`mLO+zTt#gUsGT}K_Fh}dq5y2ILuM)gM@NI(i zWX}5ppDpw!1w+|z{YtQo&i){{TIjFG;5=h$1TPRwt%D8l|ruhs@M^)A3)ZrDk6@1cjJaKKx8VB( z_X_@w-~qw^BzREpi-NUW=Az-dR;V}&7I-=vEEOIPSzW&M3x7s@X9Qm(_%^{B>SqOi zR_I?Be5c?a3BF74Zv}r&Fo!`I8KL4`RPYytUMTo(!K(z{Blr@*_X@rO*rnyY9;Ty{ z*~fQzJdb(U=lMsE{vxom!E!9dr_J=jUEH zKK&2E|84O*_ejd{q~Jw@za!Y^uLIr5bCHLAo?AWo=RNH6?DXhIW327MJlDfldziL~ z9M6|M{FI0N@b`!R?I8L07tZT3_IEZ|P7_Q{W8MqwL3uua9r^{QC6AJo=mP{*s|1u6n`i1Rslc zqUmg~l;R!9$?$d$)030oUHhSb$fMuq;U_)phjSo!((`*fChRiwgzLv1e)|ce>xgVn zu<|TGu{j$oje?c_fMD&Xe&W&T>e85gOPCMu^{~(Ls7L>qhhKjZ9~7)(gC7a575W~*^@8UVP@Z!IFB04+xL)vT z!3n{wg0~9RzWd{X<3j(c;7bJmRPcJizZcvicpkdUjOiDArr-g=Zx=iyc!OZ=->(*Y zwa`B(cvSG+g2x2&&m9&$A#{DX7Ts{h(g)G?I((alYtRil`VJ3A(Iq?j2Z67(;e64f z!{kK3)8OH|JWOv+w%08R!|~~-gPtM5UXK4VkN*Y_lg;sbYCrU!dGr^6GdApr#UU=o z@YK=i?80mU{aVZK)4M(T2gUEEfXn&y`S14l|IWkz=;0SV?E5_sd{lWT=MvxyW&?TE z2|h;fTES?{aP%O=kT%N0gjdh)+BuzwzfEs;w#NYHPQ`3w#7eZd?*ZLQoC@Vwvrb$~wriy(T@ z*2;YW{+M|%z<=Y}WBE8NZ8-kz<`)6J-TXGdpD@1<@Tbg+0sgc(ETRul*wH;Ez@Ia3 z4)EvATLSzAvk>^($lGe<^WpIN6Tz)gzRv<@Oq-PBZo%zR)_)Y-AvRcMoJF2BQ*5xz z2fZ43;;wN3mxnt&OuCbwbRSbTUepcZ6ANVCn|1sI@<-_#V#&%a;sW zta_2>i@|pNxtscV0pxx9E9^tuibbw_%;=Vy^*s6o*nXS=wZlEZ8hmhi;*Sfm%tg= zexXeydKu>*d+o&iLW`Mp;@^UQ0c@vm-tTZkvfVr(X`gQ~(@uL_q+?ibmI?lL@U4}0 zSKJjv3xd}kxoB%edm-k@Q=Sc$A9^-ee&pF;`7yN5`TdD!gXIUoH#S;{+5nb1$WRS= zW&*Dk{B0@Ib-;YTqYai$p+9MuCj&zN&VKWRVe(?05Wf@r1-90W34SY`&F#Pokg9w% zeD?uwM=nUaWHIyV+rZc1P99#-AQy<=s6?S3@8LJe_gNC6(9{C!LOWm_?e0XF8T!Rc zE}h2t$6h;e*AcPG?{GKh%PE8VD03ioWBBprklh#@%6rIe%$eL!i*?*MdTua@gA%b^ z##-vY3MwoRla*A5?8dxCyD{Fm)LF~O|9smqZlRjp8%%!TJV|gOU*rY5(uDuO{VEqy*7oT%^s<2*`?(EhT z(Xy;t4(o`=Jt~&3f*Y%(#XgE2^`d8KLkz6?LwtzN(XogX+$tW(_Sh0#5G`l3D0@KX zVpez%xxsIbGC?w->y4lpqSt)Qv z`mm~06Nm$QoU5!3x0%%Ea!Ah7=CXQ(g<~EaudMb~YTuxqA&vrJ%6Q@-c!Pt%L1w~i z5aGe#vMx5DyR+9p)l^A@!J*|KGfh@zcV0NC_H-P^m<$vNbS*;3%fMa>$eKhEkmMl8 z6%16?~W_6Aq)>8w|UMJ?w}u%G0Dr<_v1(_)p#b#(y>gYE1;`l3V&#?1(GsZ zwlW0AMWfVg;W1fgl4;{58E55Y>UiW_m^vPAE#dG)2%G?mSK4^oov03GEkVirzTvKT zSX?}94pEEhBLU8W3cP4Jimd7o6iq3UZ4169neEFfPUjT*WAbg0_9U@@(u++CR@A^b z1^&u3A5;|vheEn)v3P>EhIH0W(N7jvJc*;1J6(k<^K>~CPiMPnUf6h2?nEF+9O!gl zNkFZopypziP0#?UwG_lmBC0=>p;)&bP)7nY0&2|wS-i*uO`wx|SYcD274r7HOVM%Si5Y|TvHegKG?lUe2icv_qKM;gOM0%T?( z63JBBDhQ(16xt4O4F`zKH*g~HPUAq-Bzg7(K+`0ldYiD#0NExA?P*wBLAI>`f(0a_Fo5&%)v4(VgJAbMd9 z20&U+wC4h!)ie|tsJ4RwSsNN;E~vH_0#%zC6c4CY`$5%42I&wT3_{j61|_ZZAZ%$o z_4qLAY!G@0b58ng-+ln}S<{EEY$UM(2WKR-YQZ6BWU_MlzlHUHB00++$wBhbFZFG} z5=CjO;lT9Z2I;kxmF@!sXmoZ1E9Wf+?Q2#dJ$2&wh1h?F100Znuf=)*Hkhi?W?2sa zRjcE{SPwv)-!oo8@RU-dMlgh z{)TEnsK+xMfHY)P-UBin08gk9+5~u}1HAA#pmnAL z(DP$Apzfs;dSE&L;h_G6EysRL2Y?OD_y1cc~EpiP!B6^;{%U@pRx;1Skbs zVkk;zML>d(1Q>woxmXcEU*is=79#?9#yMH4*J48e zgkT45&enQoC?FA>j^$<`oJ)=g0mhBG@mfs?sJW+X%OM=N^f=*wjYNA;esP($`>LIA#H$j>`6Wg5L!69TBjucX*&LI8nGb9%kAhQTOYoTy{U0u0RM72B>{HZ>tYE@Y(B&1tyAgaFxG7D5@PVY4O#z^En! z0HAzR8L=M*)+)&6svlHsDqEmhYC?daO_K&SA;7=_1$3>pmmz9GfLy4ul2V>WpPL`n zgaFxG89-T-EvJG1KVm|FnJztgwg~}m3>w&3wJwk5ji6Lqxz#WGImtgRsE^?FPFJ`I(Zh( z&4J8uqdSV;w<-W9Xg!?J9db4=%c=kzsfg2B6@VMGkRCmMb}kTZRGVq73cw9oLw}qQ zoF+z&G2v_zmSt4{emSOuD=J3lH;k17O}Juai2;X){L`amj7z3>#y=f3du&p?BmU`T z^Ct|`i%+wMQ=U^JwAtg5nG>UCkV{8Sl$t}nV;HB*HoG*sPX&;3daD9-&`e=l5?U1? zU30_=@2m>YAy5_`n_Gf+C%mrUSo1?x1#r@+%ZLB|Rs~RSDEUKH1^(|?6+nrjPKQ8+NW$0SuF6_J)?WLaPEFdDuB?P207aU3&DhTCCs;1vMK;xYGkfe0YBJms{-nxnUiHz03nIa z=2{iV35t_lVpYHo=m4z>APQ6i%hRe`Js0;>W_)f4P;UTS5Ow_mFQ@W`=Ewp9TT z<)vH)zW)QP3Y6+#frs$_AF(Qc6tkD*iL{5T3LLU3fODDc`NXRaSrvfgZ#k;@kX3<0 zRt0E1;E+{;n&`APT@G0lph=xWRt4gRtO`hn@qgB;07jE|U;59mDgYxnI+cp~$*dKH z&JI8pQQlpqb@>Zg6@ZbQKqPBb03@BgCFnjh7aGjJhK9zWWU%}VHLH^c;Gm2wJHD>L><2S;+vYV;DyyQDgZ7B6LMjVym0Nu zrU2ME$BY}&gR_41kaFLq0Gu!zlVwwYt1>xX5}FhcicWn@wJ6}E%r+<>)T#CaL?9%{ zwV!ntn^}u`~zxsLk-6J@Ao=XHNioCz)9GFi!v}&<1KzDlh>BD~Y z4o@zHtx51fX_OD@VEJ?=#5=rHIiU^8iEJ0nX^+ikn8Ix7*<8U|J((7?Fw*SZuzw)KFd#nCy^)r(?BQLx3b_6qiIC4!To z$XHnW0<+D~Did0X(2sWFEE01{-!6Fl1i*3Am$tk0Xb*<^UE)NhG+Ix+C=2|LlZj1 zvH+5XuYx(21=#$(M#BPO&WlW0X9YX4l2gqJh+@5>Spf*jzV2Y{3S`RzivkP>sheVG zfXZg#-9zz#VL5GCg+=BErWJYyQV?7vo!)+nwUU6AjGqdQ~I)94V%CX`?5oJ z3qrdMhwK*o7uqctN%Sve^*2k`Cvgf3>{uks(qyW0y;({pMf{5fAEY7W?HU>wNDQV# zn-A>Io56-7L*$$Y`l!ZF&P3n?E}mz>i|22=PLTe&5l4FM0en4v^q-F(&w1b}5PY^r zJDAM??))E+g^%|l{QU4XUxG7qL1TFI>%yx7X1FfATO0t57x{Qqnao>Yy zmO1MNZ6Cax zoYe(J|EgvdrdU+4W)cE(2sRNC;|5r`8R_hgdseox2OwrsQb!#^wvaX@pi8Jc3vj1x zfqLFSWF5~tD#vC5GWx@o?=HHdt@(=OAGi0PSvt#t;m$)DFx(~7aU5xLj(xs>cf@lk z>Bky#1Mi6ML)QI4J|n&z_L;U37~k{u`4rRxhFgj|=@;-B;oZh(D9pEbKi-%E)VI77 z(LVA176^rlwhO2?yt6&#o$Vy=)DzyRQxSA1a>sLlr9X$phVH{)(%r+^HWNxq%PU|NVLF=$B`eAf*k(e-7=*-CDu1W7nNT#I!Qn!< z((|P@R&U++x~peq&YEXZd$;bJJ@>E2Pn(466OW4Bfuq~TE}Df?XB#jTfOK%0WQ-r@m_@H z;#{(JP1}yxODt2G0FYEzQD53Pe`B6K9Dg)6vGuWn>&LeoN$D;D_is88%Plxke_QOO zmfng{njDyDajCq1JblDi?4`)~*73a2*h_$q>^y8Vws+BEqdT`CAK|o2940Az zsjc@7^xrYjYW*Xo^xQv~u3ooee!(_tnh3{vME-H~Gi5Ja{ZZdI64ksTs(P7B86$ z^vr1jt%h9N?ne-2;sgINIjQz1uEFCiqko*Sdf&G5=k;v8VqRXlX$(~c8CNrJG{1PP zE`KyyoIh4K3%6Ngb#ri=)3YO5oOk~qIL11j8_gq6t+3PzN9~-g-<&tv@!ZzO=S{|T zZ{1Na8QU`!+fx;LY3{YZWA=6I9zBLCHhRng=GFMN#J4WIIBs?S1l1jiP{f?B5^dZv zGKR(kUbgHVeWB=u(LX-&tNd+iBcmPrcIDl&a>dJAP8@w6dWrlxDz9fn^oYFlZ^xoX z z+w*q4u4l(#3`r`O`cWT;-PAF8<58?B2yRX9PVnqnv32vTy!6bio9E=Glw1Hocbzg; zJ#UN^eBMLsCC1DrcpLrxF0?T4dI@+Y24KB{1r*9_+orv9@2{KDf*S<( z{sa?=#P?FPi7SIP=9=AeK!B=DeEh}9$?M1GUiWzfPR8vnk{}PqN0{}% zlhHIIZmma!c>D%q`6>lPRLe5wRHqk%bLEWo%{8fTD4w?)<$Nf{$V8u0@MG# z>jyi~r|NY(L-+*4k}MpphgM5jGebTYIZRsR7g95Cnt9!LdiKN^WcW=4Ue0=J`ml*D zcw)F=LeyQ*uO}S4jel>-yKX#{f7X)pZy`JW zk9~~PMZXvAW6_T8SUd5FKS~ip(c9Lnl>&b}zlyoPc4DEVl}+t@WbWEtjsqsn5Pql? z7#POH%^-|P8-PkXL)x23spmaA^74%20Gbr$S(x<0?jMA$9BR~PZQhtjpE+mA-0P1- zfWMi=P#=b}B97im7^kY?UhO<#}NXsLsp;VD|;XaVcg(^Y?;8#ijzrzViK(z@8X zP$2EgSbEM@J6JevV*C$O@6-tsha*UIl}9mwk3p>8906IhJx9=}=@j+r;D(^rzmT3Y zRz?+?r2P_aj2^zNJ`Y(t)^T*}WO|;CV6+&<+GdY-pk||L)g9Tx#x|^1vFAma zq9;~-GnF^`$mo++;|E6n;gMhGU;m4%W;+$%H3MaaL~fkdveDdh36 zmTmPf<7vjW`WIVZIBIfO)rkFN!PY;)WYXx6={etEc6|j+wt4BZ=J%gY4Z`*Cxi{ZvU75{a;cL9Orc<^6(kmW6OkP)zZms>j zEh&YM`|TE@M-oCt7@14e@kZ`T|dZ{vw^k9Eu$Tm9VJ2lD5$7*JGb*k+Hd zp4C$oNzGBUSOv8heL4SzG zgS^rF`50l3M(5{`#rEMg3xg=!=4k64W?XHUIeS_AC-z9&QNTL6E_6fN^3vEvKYHs$ z&$W%kp3#Bs939V(UNnK2##SFaT7wQU_PnTaFm4#FnZ-9)49;t)HGGZOmUvLwT0Y_( z5lsdapH~Y?aRC~o>t2WV$Jyvf-2{?4%eyKe11v0BT3BSUF|iq6YC2@2D}(&tbtSr> zYZc1hJ1oA@qkqi9_j#DCj{m#+q5C}l;_=s-hI3Jb8*=;&eFlW2*E+SaFx;DY*2wm-RamLdawaZm4_%`9G5&U_< zwSpfLTqpSFf}?_eCpaef@WUy?O2H=y=4_TR<$_lUZWgTh-z^vw2iGSBpC|ZX!L5Ry z5!@#D_k!C6AAx$xGthaRDj1X2xT*xJZI5>g9ufLS1*ZkyFZfEq-xJK4T%64<_-et2 zp$*93AFopcZxwvD;OhimAovEsBZ76tc1-X#p?_NN&4Rxv_*TLEb~#e7Dd~l`uapc!A&t1)nDPDZ!@;<{u}|ZqQx4KD_|# zVa9w?_$vhqG#~Kr@kf$pk2n+x)>+^V!JLi6l#*bT`F6qXr2J5Z9YR;VeFk_sd0rHr zpGlZU&Yhlz@ws#@^mxwku+KBHANn?rey4}O;bA`gXG^|n3sCtT;pM%|Gxdup8`E&RBtB)pFwZtWx)#t z(}r$FzU06zvEX8%*9g`&cAa2tV}}H<5T17nt`>ZUU~Lb-A-GoP&j_v;{71p(3O@EI z#@i^kOz>*KZGu|`UnW@Ft8Icg+Yfuhf-e#LcY@ao{*~Y!!7mH$7yRa<8P|Z|3c*8y zI|OT+M%!H(qix!|1&<2P-v}NP%s;M?By*mKB1vj9LV18TANWEa6-wc&Xr91#A9)MzHo%UlXkT&W{AI68_zSHE;P{BO_l- z@O@ZtxA2@PxL0sYu;$f8f(M137Ca(&4A`ap<3iW+rK8KA`#c_>{u|-XkYrvKe2w6v z@ognzLtQBNZ-rhX_=|!s5PY}bq~Lo5zen)BfDOTEa$KF_WDq5qwPsXF;f!5UEgo5C==fiq&6MBQAxv>}&KlKG*B&%^g8M_+nE zi2vx}EhmQbhdew3-@05{PV_LNaq;@N0z57*pPusQXBLD!$Db17Y7g)B@CdTQh57$H zT(=;U?E+xO^EnUi^>7EOwBs?jocvz~{aO<2<>)`y5B~{h4jg~6hw0tFmP%Bj_$(pFX!Zq}Ksw%qBX^<^1x&;R`+f_X_{R%Ixuc%Hw&+ z!$0(}ALikxPMIK-Fs}8WJDIQYu>m<~FDkuFNK@2V}lNDk3ewZaI z!f+n+@JW>+{oNk^xrhC5?!oJalYfVYeV#vo?)vD`vxv(?&OyNf&50NSW)zwa1G_Nq z_As4Yx_tbc_`NXCdJlNsa84M`Lg0*LI2Er$4*!#fd#XJ;h60XfU2TXNgp=VTpkGS@ zt}lD|dmjFchsk#b|JZ9foQE#(TI+raaK_>rJWP`FJ1-jY`*a^K^LV1b89Lg_h4XJ7 z4@{f|JhuwQKmgYlJo>toxaDPB>mxS@S;9i-p`HA4ovc6y!@B-Kva~JK6xhra}bPzUyuJZ5}bCP|E z!V26H;KLe>srLBC18%HC045Kw1^5vk3H}9UtKc^QZ%4{zkpWi}bazF~^_~r_cS|mw z3I6NA&}f;W<`h#9;8O#uc~Mj6*?fwMh0S{F_ws=MCZV4PdNpL2Vd>-cev!~`m_n!X zPRqmFxQBNF>&RDm9A?^yFGZLOVC#A_@a4eU&3nAGZv$1YsJYoexO{-J@c6Wf8X32;HMC( zUQzSIzzSFtmII#)=s)&k{)ss{;`o1RiUa(#tO24+)co9>8_<7gE(!2I$a)~<`A73t z0sUF?qNf9YqM25?qUI&619131jP}ON^B1K)(0$dc~8|oJ&|BsQf`>Nn$B_F;k_&6z-r-3u(_z0@qB)yOGkG;lm zKg;5sxV!X@d)TKF>zlEb3-L~bzrd77zJ+pm9(cPc^U9^%E0>DMZ1D4nniY{V6#`dA zbfigomE`kF2&Wq1STzr1o{3JZ8h)+UfX?Tgj%cwfFX|8ReE3~pY9jn5a0>8tQ|-xF z6NDKx(a7s;Sg<1-!8Dd!QL{2~N`UJ<{aGbCvrJ^G<}ydQ#_gTA{o$Q-wAZ);xbO7v zxQBguE_Qm$^b(&X>0KS+cQjtGW$UG}*~4ufUK7FVx?EASE`nmP`25IlfG>=EAi(d4 z+!f%9B3};h#gV51+!^_Y0I!ei32=8L&&C`zJrP%fqh>?oq=4QR;pz@vQM1v*mqw}r zdVeGq;DJa_fCnSj2Y4tF_M5|z4+QkfB3xUm;g3Wf32-v>j^Lc;IMs?5oA2ZC?O85N|J3Sc(c6vg( z!=$^iBi&)rU0IOs@|l?V%!};+@o`Aw0`tBIzoi!gZwF=(#VnpfW?WIw6%pSSInq8v z&HE$A2KWP!f&hOg;`)xL`H0t6d^B=i!1Fheivs*{uOHkVxhkOF5qVF5KM}bzz@Lmf z8Q@QO?a5~%&jj?(MxG7uosr)J_^yZ>6-LeHBKoC^>H2&m9D9Eu;(8LigG5~G7&Z4q zT#FbrUy7^=>ifNsIPiJMw`$}S`=)nTJQKJVID^sobhd}b;qGMK>EZp+|G)OGB{t5h z3jhCASkXd(@DeO6lmuL*#E(g0k5ws-XX;wwqOvOv3b)1#pIseo3B^!1eb{8W;kr{Nvo7ime^;QulWcl%$Z zndiTjc0K*;^pl?cP5K#6|2BQr(>K$vdHQ$h3!eUcy6fpbr>}bYR;oW)W#4Y5?kA`f z{11%}TMH`5U&Qy0!p3vS%Q99cKwnK>5uYgu{}s_bFZ54kU%DXltD^se&_8?A{m|Ka z4gGTTjfg%h-<54kyEpw@yjeZeck7EjK)R2z$CBGAe}Ct*pr1?rCO+^bOLI=2w={j= zTSDKCeBickx03ulqF;~bBZg)9sU&YTA=bOkJgRK)?>9A1zs;*@CzcQzp&F|T?42hA-{51FuEeaIZKmQ|8t zhQEZ!PbE2S`2QP}K4H##de}5Peaz&ZK5lkAeZqXg(;qeAE_BL#+4D!tS3Esx+{&vU z@(*{Oaq}myQ!;L5D!8?{*{CFE&HIh(=cEaDp0YXa`BNs`a~?M5JilUQJzX_5&_97c zT*bWe-Qc>=|B&_aN1N{Iv`o>-G@3t(*fgi3Z((i*ULy3;mFzAmY&x?H0(nI+6q|jeac%Rv@G=CNGs-@{m zUl7`){N;9j+W7PA{rJoM$E<_krt?2=-NQ}4hnqe!JarE@eFXVb`n`>Ac4de_-$U*G z)>GXK>0yu^1{rV!IDX;|anm>3oj!8d6!Kx+J!bkLVO}FZYo@yq1O(~Pf$M1v)?mfH z{5ePyg8C%$m4(MES}K{p?grDHi0p*Gz+@=aEv5vCNyv8i?E)bKn~;TsY`_$VvL^Wg zZULDVzg+-bpek6&5n!=^w}6i%FA;vb0;%l9Zx{R&=rYd=sz!5)RjXhpu6tlxunoaE zfj&@hRo(NMdH2r&prs5%gP#VG~ysP>Le_ zcJS3E8JK|I4nB3E_fk$>_6M4~SE7qa#;pfO_*UXW_N+jsegEApDw_9_gkHl)S z;$0ShKTi#vxqP%V5iqD+GCyh!vR1nZOrA2=lusAuB|s#160O@yo@(VtC#QupJs(BS z3_6=xGnU!xaX}b0W|3rrENX6a5+HFf84m-{cb~xUm^i)dKC}%v5t5 zNuRozFU5TjLSzn{fSWwsA8a~T!D0@_!iXk1gCedCQ{tA=Z8?z9eYnNxv)cX8A8aru z&x~LPEKN1H*0=Jk&9r?y-lLi=@EkPHjT|2>*jymu zZpg-Q0Ibq}xfei5J;`aw^@M6zCIz)T%Pu#)7FRK~utaR4J!udJQ=SDaZgJFt;Z|!E zOUNO*LnzZw+~VX?ne$?eG>$!NPwviuG^+ougxdgJlGpz@RwSIe(^}u#EzOwwh9Ve_ z-P;v79P6D|GES39g=?xL1N}?=9f!>4`-hf);S?B?HQ2hnn@0 ziPMqnP_^DMaRiec>eef!h0g0{tvvKxZF!+vn-{5T)TMYA}=z~jW@h$qhm z{b1^`fZly<3s)?w$yt_gB6K2K-&Lz21!gUA z5j8Z$%_Xu<08j5!#lIznPI>^{^=xYw%nea8D^c4ptyp}a5;YF)mAG)2x@sLJEQwUr zHiWZDh>@wR=JC95`!JMzH4tHH62epR)kcJ=$>nUvb=w8~&@RmBW~Z0ou;4$cs*gq( zPP8YQhukx_!o=DI04ulLa}fGx9p5f*^^3^g=`425LRVcKQ=wkuHb6*p8(=Lg;Z`dI z-q}UqmMR45?N~O0Yz+yfvw=5BCP=+&TpF{gq{=7u>?TQM)t@$T_yu#5bmZ7>Ma7Zjp+-0j;1r;$X1ZNT#;$> ziOub14h9N4)HiU}1IyvEg*OPomg&mED1*(5H&(HLVqsAly8;U8orF_m)i8><#9_^7Rn_h z>($3DPS0GZ0#`^G_8TtZZ-hF>K5<*Xfafh7BfU;n7kx=rvOHlrCG8t_DgZ=!Z8#ZK z6>$Ju$)rsi3XV5w(?25`z|qgh#Z?L@fc~JhW(~)>)Q71&x4kLU&j-L}tJ_&asD{lI zL6bV3@Hb#cXMGI?N_!wGM<;DehTwYg%m`X1el66nsI!IoY;$SpJjR&R#cK5eMwnz} zX|YjTT5eP^w){TRs4XwflqXcLw)DiMGOVFQ1?Y+^_W1N%qm0J*y}DE@Gdd?t{`CBO znE^DvKQgyiW*ADkerd7HMJZpFYqRCC5d^f9)anfYW+D3Lmuju{*m8BbTApC&PR`;| zeQtJfdLF%DusoIY^0lYigdTu}*qnfJ4o-8u)k91i01zBcvcf|XbEtz!L8reh_ z1BthVXDYmdJlx#i0@AF6_m;Pvp;2D8tSQ2lWu;vExY889_f%dt!yfsN?2%}T21UNY zBRZ?kEHrC#vyV3FT$A`RQ>#|0i;cPI`8wRD3A8`(mKGPQGYzcHsbp(qkhOIx7%rpx zILQHcimp2#0UY?sz{7^l0PYdWK_|4!d)96%@15cT3j3EkT%4pMnV7 z(QWqE5mVbylCkR|)E2dP;{X5v literal 0 HcmV?d00001 diff --git a/arch/linux/svgalib/event.c b/arch/linux/svgalib/event.c new file mode 100644 index 00000000..21fa607b --- /dev/null +++ b/arch/linux/svgalib/event.c @@ -0,0 +1,25 @@ +// SDL Event related stuff + +#include +#include + +#include +#include + +void key_handler(int scancode, int press); +//added on 10/17/98 by Hans de Goede for mouse functionality +//extern void mouse_button_handler(SDL_MouseButtonEvent *mbe); +//extern void mouse_motion_handler(SDL_MouseMotionEvent *mme); +//end this section addition - Hans + +void event_poll() +{ + keyboard_update(); + mouse_update(); +} + +/*int event_init() +{ + initialised = 1; + return 0; +}*/ diff --git a/arch/linux/svgalib/gr.c b/arch/linux/svgalib/gr.c new file mode 100644 index 00000000..2aee9776 --- /dev/null +++ b/arch/linux/svgalib/gr.c @@ -0,0 +1,309 @@ +#include +#include +#include +#include +#include +#include "gr.h" +#include "grdef.h" +#include "palette.h" +#include "u_mem.h" +#include "error.h" +#ifdef SVGALIB_INPUT +#include +#endif + +#include "gamefont.h" + +int gr_installed = 0; +int usebuffer; + +extern void mouse_handler (int button, int dx, int dy, int dz, int drx, int dry, int drz); + +GraphicsContext *physicalscreen, *screenbuffer; + +void gr_update() +{ + if (usebuffer) + gl_copyscreen(physicalscreen); +} + +int gr_set_mode(u_int32_t mode) +{ + unsigned int w, h; + char vgamode[16]; + vga_modeinfo *modeinfo; + int modenum, rowsize; + void *framebuffer; + +#ifdef NOGRAPH + return 0; +#endif + if (mode<=0) + return 0; + + w=SM_W(mode); + h=SM_H(mode); + + gr_palette_clear(); + + sprintf(vgamode, "G%dx%dx256", w, h); + modenum = vga_getmodenumber(vgamode); + vga_setmode(modenum); +#ifdef SVGALIB_INPUT + mouse_seteventhandler(mouse_handler); +#endif + modeinfo = vga_getmodeinfo(modenum); + + if (modeinfo->flags & CAPABLE_LINEAR) + { + usebuffer = 0; + + vga_setlinearaddressing(); + + // Set up physical screen only + gl_setcontextvga(modenum); + physicalscreen = gl_allocatecontext(); + gl_getcontext(physicalscreen); + screenbuffer = physicalscreen; + + framebuffer = physicalscreen->vbuf; + rowsize = physicalscreen->bytewidth; + } + else + { + usebuffer = 1; + + // Set up the physical screen + gl_setcontextvga(modenum); + physicalscreen = gl_allocatecontext(); + gl_getcontext(physicalscreen); + + // Set up the virtual screen + gl_setcontextvgavirtual(modenum); + screenbuffer = gl_allocatecontext(); + gl_getcontext(screenbuffer); + + framebuffer = screenbuffer->vbuf; + rowsize = screenbuffer->bytewidth; + } + + memset(grd_curscreen, 0, sizeof(grs_screen)); + grd_curscreen->sc_mode = mode; + grd_curscreen->sc_w = w; + grd_curscreen->sc_h = h; + grd_curscreen->sc_aspect = fixdiv(grd_curscreen->sc_w*3,grd_curscreen->sc_h*4); + grd_curscreen->sc_canvas.cv_bitmap.bm_x = 0; + grd_curscreen->sc_canvas.cv_bitmap.bm_y = 0; + grd_curscreen->sc_canvas.cv_bitmap.bm_w = w; + grd_curscreen->sc_canvas.cv_bitmap.bm_h = h; + grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize = rowsize; + grd_curscreen->sc_canvas.cv_bitmap.bm_type = BM_LINEAR; + grd_curscreen->sc_canvas.cv_bitmap.bm_data = framebuffer; + gr_set_current_canvas(NULL); + + gamefont_choose_game_font(w,h); + + return 0; +} + +int gr_init(int mode) +{ + int retcode; + // Only do this function once! + if (gr_installed==1) + return -1; + MALLOC(grd_curscreen,grs_screen, 1); + memset(grd_curscreen, 0, sizeof(grs_screen)); + + vga_init(); + + if ((retcode=gr_set_mode(mode))) + return retcode; + + grd_curscreen->sc_canvas.cv_color = 0; + grd_curscreen->sc_canvas.cv_drawmode = 0; + grd_curscreen->sc_canvas.cv_font = NULL; + grd_curscreen->sc_canvas.cv_font_fg_color = 0; + grd_curscreen->sc_canvas.cv_font_bg_color = 0; + gr_set_current_canvas( &grd_curscreen->sc_canvas ); + + gr_installed = 1; + atexit(gr_close); + return 0; +} + +void gr_close () +{ + if (gr_installed==1) + { + gr_installed = 0; + free(grd_curscreen); + gl_freecontext(screenbuffer); + gl_freecontext(physicalscreen); + } +} + +// Palette functions follow. + +static int last_r=0, last_g=0, last_b=0; + +void gr_palette_clear () +{ + int colors[768]; + + memset (colors, 0, 768 * sizeof(int)); + vga_setpalvec (0, 256, colors); + + gr_palette_faded_out = 1; +} + + +void gr_palette_step_up (int r, int g, int b) +{ + int i = 0; + ubyte *p = gr_palette; + int temp; + + int colors[768]; + + if (gr_palette_faded_out) return; + + if ((r==last_r) && (g==last_g) && (b==last_b)) return; + + last_r = r; + last_g = g; + last_b = b; + + while (i < 768) + { + temp = (int)(*p++) + r + gr_palette_gamma; + if (temp<0) temp=0; + else if (temp>63) temp=63; + colors[i++] = temp; + temp = (int)(*p++) + g + gr_palette_gamma; + if (temp<0) temp=0; + else if (temp>63) temp=63; + colors[i++] = temp; + temp = (int)(*p++) + b + gr_palette_gamma; + if (temp<0) temp=0; + else if (temp>63) temp=63; + colors[i++] = temp; + } + vga_setpalvec (0, 256, colors); +} + +//added on 980913 by adb to fix palette problems +// need a min without side effects... +#undef min +static inline int min(int x, int y) { return x < y ? x : y; } +//end changes by adb + +void gr_palette_load (ubyte *pal) +{ + int i; + int colors[768]; + + for (i = 0; i < 768; i++) + { + gr_current_pal[i] = pal[i]; + if (gr_current_pal[i] > 63) gr_current_pal[i] = 63; + colors[i] = (min(gr_current_pal[i] + gr_palette_gamma, 63)); + } + + vga_setpalvec (0, 256, colors); + + gr_palette_faded_out = 0; + init_computed_colors(); +} + + + +int gr_palette_fade_out (ubyte *pal, int nsteps, int allow_keys) +{ + int i, j; + ubyte c; + fix fade_palette[768]; + fix fade_palette_delta[768]; + + int fade_colors[768]; + + if (gr_palette_faded_out) return 0; + + if (pal==NULL) pal=gr_current_pal; + + for (i=0; i<768; i++) + { + gr_current_pal[i] = pal[i]; + fade_palette[i] = i2f(pal[i]); + fade_palette_delta[i] = fade_palette[i] / nsteps; + } + + for (j=0; j i2f(pal[i] + gr_palette_gamma)) + fade_palette[i] = i2f(pal[i] + gr_palette_gamma); + c = f2i(fade_palette[i]); + if (c > 63) c = 63; + fade_colors[i] = c; + } + vga_setpalvec (0, 256, fade_colors); + } + + gr_palette_faded_out = 1; + return 0; +} + + + +int gr_palette_fade_in (ubyte *pal, int nsteps, int allow_keys) +{ + int i, j; + ubyte c; + fix fade_palette[768]; + fix fade_palette_delta[768]; + + int fade_colors[768]; + + if (!gr_palette_faded_out) return 0; + + for (i=0; i<768; i++) + { + gr_current_pal[i] = pal[i]; + fade_palette[i] = 0; + fade_palette_delta[i] = i2f(pal[i] + gr_palette_gamma) / nsteps; + } + + for (j=0; j i2f(pal[i] + gr_palette_gamma)) + fade_palette[i] = i2f(pal[i] + gr_palette_gamma); + c = f2i(fade_palette[i]); + if (c > 63) c = 63; + fade_colors[i] = c; + } + vga_setpalvec (0, 256, fade_colors); + } + + gr_palette_faded_out = 0; + return 0; +} + + + +void gr_palette_read (ubyte *pal) +{ + int colors[768]; + int i; + + vga_getpalvec (0, 256, colors); + + for (i = 0; i < 768; i++) + pal[i] = colors[i]; +} + diff --git a/arch/linux/svgalib/include/event.h b/arch/linux/svgalib/include/event.h new file mode 100644 index 00000000..1aeaedbd --- /dev/null +++ b/arch/linux/svgalib/include/event.h @@ -0,0 +1,9 @@ +// Event header file + +#ifndef _EVENT_H +#define _EVENT_H + +int event_init(); +void event_poll(); + +#endif diff --git a/arch/linux/svgalib/include/key.h b/arch/linux/svgalib/include/key.h new file mode 100644 index 00000000..f7d5514b --- /dev/null +++ b/arch/linux/svgalib/include/key.h @@ -0,0 +1,271 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/arch/linux/svgalib/include/key.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:15 $ + * + * Header for keyboard functions + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:01:46 donut + * Import of d1x 1.37 source. + * + * Revision 1.19 1994/10/24 13:58:12 john + * Hacked in support for pause key onto code 0x61. + * + * Revision 1.18 1994/10/21 15:17:10 john + * Added KEY_PRINT_SCREEN + * + * Revision 1.17 1994/08/31 12:22:13 john + * Added KEY_DEBUGGED + * + * Revision 1.16 1994/08/24 18:53:50 john + * Made Cyberman read like normal mouse; added dpmi module; moved + * mouse from assembly to c. Made mouse buttons return time_down. + * + * Revision 1.15 1994/08/18 14:56:16 john + * *** empty log message *** + * + * Revision 1.14 1994/08/08 10:43:24 john + * Recorded when a key was pressed for key_inkey_time. + * + * Revision 1.13 1994/06/17 17:17:28 john + * Added keyd_time_last_key_was_pressed or something like that. + * + * Revision 1.12 1994/04/29 12:14:19 john + * Locked all memory used during interrupts so that program + * won't hang when using virtual memory. + * + * Revision 1.11 1994/02/17 15:57:14 john + * Changed key libary to C. + * + * Revision 1.10 1994/01/31 08:34:09 john + * Fixed reversed lshift/rshift keys. + * + * Revision 1.9 1994/01/18 10:58:17 john + * *** empty log message *** + * + * Revision 1.8 1993/10/16 19:24:43 matt + * Added new function key_clear_times() & key_clear_counts() + * + * Revision 1.7 1993/10/15 10:17:09 john + * added keyd_last_key_pressed and released for use with recorder. + * + * Revision 1.6 1993/10/06 16:20:37 john + * fixed down arrow bug + * + * Revision 1.5 1993/10/04 13:26:42 john + * changed the #defines for scan codes. + * + * Revision 1.4 1993/09/28 11:35:20 john + * added key_peekkey + * + * Revision 1.3 1993/09/20 18:36:43 john + * *** empty log message *** + * + * Revision 1.1 1993/07/10 13:10:39 matt + * Initial revision + * + * + */ + +#ifndef _KEY_H +#define _KEY_H + +#include "fix.h" +#include "types.h" +#include // For 'toupper' + +//========================================================================== +// This installs the int9 vector and initializes the keyboard in buffered +// ASCII mode. key_close simply undoes that. +extern void key_init(); +extern void key_close(); + +//========================================================================== +// These are configuration parameters to setup how the buffer works. +// set keyd_buffer_type to 0 for no key buffering. +// set it to 1 and it will buffer scancodes. +extern unsigned char keyd_buffer_type; +extern unsigned char keyd_repeat; // 1=allow repeating, 0=dont allow repeat + +// keyd_editor_mode... 0=game mode, 1=editor mode. +// Editor mode makes key_down_time always return 0 if modifiers are down. +extern unsigned char keyd_editor_mode; + +// Time in seconds when last key was pressed... +extern volatile int keyd_time_when_last_pressed; + +//========================================================================== +// These are the "buffered" keypress routines. Use them by setting the +// "keyd_buffer_type" variable. + +extern void key_flush(); // Clears the 256 char buffer +extern int key_checkch(); // Returns 1 if a char is waiting +extern int key_getch(); // Gets key if one waiting other waits for one. +extern int key_inkey(); // Gets key if one, other returns 0. +extern int key_inkey_time(fix *time); // Same as inkey, but returns the time the key was pressed down. +extern int key_peekkey(); // Same as inkey, but doesn't remove key from buffer. + +extern unsigned char key_to_ascii(int keycode ); +extern char *key_name(int keycode); // Convert keycode to the name of the key + +extern void key_debug(); // Does an INT3 + +//========================================================================== +// These are the unbuffered routines. Index by the keyboard scancode. + +// Set to 1 if the key is currently down, else 0 +extern volatile unsigned char keyd_pressed[]; +extern volatile unsigned char keyd_last_pressed; +extern volatile unsigned char keyd_last_released; + +// Returns the seconds this key has been down since last call. +extern fix key_down_time(int scancode); + +// Returns number of times key has went from up to down since last call. +extern unsigned int key_down_count(int scancode); + +// Returns number of times key has went from down to up since last call. +extern unsigned int key_up_count(int scancode); + +// Clears the times & counts used by the above functions +// Took out... use key_flush(); +//void key_clear_times(); +//void key_clear_counts(); + +extern char * key_text[256]; + +#define KEY_SHIFTED 0x100 +#define KEY_ALTED 0x200 +#define KEY_CTRLED 0x400 +#define KEY_DEBUGGED 0x800 + +#define KEY_0 11 +#define KEY_1 2 +#define KEY_2 3 +#define KEY_3 4 +#define KEY_4 5 +#define KEY_5 6 +#define KEY_6 7 +#define KEY_7 8 +#define KEY_8 9 +#define KEY_9 10 + +#define KEY_A 30 +#define KEY_B 48 +#define KEY_C 46 +#define KEY_D 32 +#define KEY_E 18 +#define KEY_F 33 +#define KEY_G 34 +#define KEY_H 35 +#define KEY_I 23 +#define KEY_J 36 +#define KEY_K 37 +#define KEY_L 38 +#define KEY_M 50 +#define KEY_N 49 +#define KEY_O 24 +#define KEY_P 25 +#define KEY_Q 16 +#define KEY_R 19 +#define KEY_S 31 +#define KEY_T 20 +#define KEY_U 22 +#define KEY_V 47 +#define KEY_W 17 +#define KEY_X 45 +#define KEY_Y 21 +#define KEY_Z 44 + +#define KEY_MINUS 12 +#define KEY_EQUAL 13 +#define KEY_DIVIDE 43 +#define KEY_SLASH 28 +#define KEY_COMMA 51 +#define KEY_PERIOD 52 +#define KEY_SEMICOL 39 + +#define KEY_LBRACKET 26 +#define KEY_RBRACKET 27 + +#define KEY_RAPOSTRO 40 +#define KEY_LAPOSTRO 41 + +#define KEY_ESC 1 +#define KEY_ENTER 28 +#define KEY_BACKSP 14 +#define KEY_TAB 15 +#define KEY_SPACEBAR 57 + +#define KEY_NUMLOCK 69 +#define KEY_SCROLLOCK 70 +#define KEY_CAPSLOCK 58 + +#define KEY_LSHIFT 42 +#define KEY_RSHIFT 54 + +#define KEY_LALT 56 +#define KEY_RALT 100 + +#define KEY_LCTRL 29 +#define KEY_RCTRL 97 + +#define KEY_F1 59 +#define KEY_F2 60 +#define KEY_F3 61 +#define KEY_F4 62 +#define KEY_F5 63 +#define KEY_F6 64 +#define KEY_F7 65 +#define KEY_F8 66 +#define KEY_F9 67 +#define KEY_F10 68 +#define KEY_F11 87 +#define KEY_F12 88 + +#define KEY_PAD0 82 +#define KEY_PAD1 79 +#define KEY_PAD2 80 +#define KEY_PAD3 81 +#define KEY_PAD4 75 +#define KEY_PAD5 76 +#define KEY_PAD6 77 +#define KEY_PAD7 71 +#define KEY_PAD8 72 +#define KEY_PAD9 73 +#define KEY_PADMINUS 74 +#define KEY_PADPLUS 78 +#define KEY_PADPERIOD 83 +#define KEY_PADDIVIDE 98 +#define KEY_PADMULTIPLY 55 +#define KEY_PADENTER 96 + +#define KEY_INSERT 110 +#define KEY_HOME 102 +#define KEY_PAGEUP 104 +#define KEY_DELETE 111 +#define KEY_END 107 +#define KEY_PAGEDOWN 109 +#define KEY_UP 103 +#define KEY_DOWN 108 +#define KEY_LEFT 105 +#define KEY_RIGHT 106 + +#define KEY_PRINT_SCREEN 99 +#define KEY_PAUSE 119 + +#endif diff --git a/arch/linux/svgalib/include/mouse.h b/arch/linux/svgalib/include/mouse.h new file mode 100644 index 00000000..32f37bf9 --- /dev/null +++ b/arch/linux/svgalib/include/mouse.h @@ -0,0 +1,127 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/arch/linux/svgalib/include/mouse.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:15 $ + * + * Header for mouse functions + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:01:46 donut + * Import of d1x 1.37 source. + * + * Revision 1.10 1995/02/02 10:22:29 john + * Added cyberman init parameter. + * + * Revision 1.9 1994/11/18 23:18:09 john + * Changed some shorts to ints. + * + * Revision 1.8 1994/09/13 12:33:49 john + * Added functions to get down count and state. + * + * Revision 1.7 1994/08/29 20:52:20 john + * Added better cyberman support; also, joystick calibration + * value return funcctiionn, + * + * Revision 1.6 1994/08/24 17:54:35 john + * *** empty log message *** + * + * Revision 1.5 1994/08/24 17:51:43 john + * Added transparent cyberman support + * + * Revision 1.4 1993/07/27 09:32:22 john + * *** empty log message *** + * + * Revision 1.3 1993/07/26 10:46:44 john + * added definition for mouse_set_pos + * + * Revision 1.2 1993/07/22 13:07:59 john + * added header for mousesetlimts + * + * Revision 1.1 1993/07/10 13:10:40 matt + * Initial revision + * + * + */ + +#ifndef MOUSE_H +#define MOUSE_H + +#include "types.h" +#include "fix.h" + +#define MOUSE_MAX_BUTTONS 8 + +#define MB_LEFT 0 +#define MB_RIGHT 1 +#define MB_MIDDLE 2 +#define MB_Z_UP 3 +#define MB_Z_DOWN 4 +#define MB_PITCH_BACKWARD 5 +#define MB_PITCH_FORWARD 6 +#define MB_BANK_LEFT 7 +#define MB_BANK_RIGHT 8 +#define MB_HEAD_LEFT 9 +#define MB_HEAD_RIGHT 10 + +#define MOUSE_LBTN 1 +#define MOUSE_RBTN 2 +#define MOUSE_MBTN 4 + +#undef NOMOUSE +#ifndef NOMOUSE + +//======================================================================== +// Check for mouse driver, reset driver if installed. returns number of +// buttons if driver is present. + +extern int mouse_set_limits( int x1, int y1, int x2, int y2 ); +extern void mouse_flush(); // clears all mice events... + +//======================================================================== +extern void mouse_get_pos( int *x, int *y); +extern void mouse_get_delta( int *dx, int *dy ); +extern int mouse_get_btns(); +extern void mouse_set_pos( int x, int y); +extern void mouse_get_cyberman_pos( int *x, int *y ); + +// Returns how long this button has been down since last call. +extern fix mouse_button_down_time(int button); + +// Returns how many times this button has went down since last call. +extern int mouse_button_down_count(int button); + +// Returns 1 if this button is currently down +extern int mouse_button_state(int button); + +#else +// 'Neutered' functions... :-) +#define mouse_init(a) -1 +#define mouse_set_limits(a,b,c,d) -1 +#define mouse_flush() +#define mouse_close() +#define mouse_get_pos(a,b) +#define mouse_get_delta(a,b) +#define mouse_get_btns() 0 +#define mouse_set_pos(a,b) +#define mouse_get_cyberman_pos(a,b) +#define mouse_button_down_time(a) 0 +#define mouse_button_down_count(a) 0 +#define mouse_button_state(a) 0 + +#endif + +#endif + diff --git a/arch/linux/svgalib/init.c b/arch/linux/svgalib/init.c new file mode 100644 index 00000000..3ad24423 --- /dev/null +++ b/arch/linux/svgalib/init.c @@ -0,0 +1,9 @@ +#include "args.h" + +extern void d_mouse_init(); + +void arch_svgalib_init() +{ + if (!FindArg("-nomouse")) + d_mouse_init(); +} diff --git a/arch/linux/svgalib/key.c b/arch/linux/svgalib/key.c new file mode 100644 index 00000000..191eb3be --- /dev/null +++ b/arch/linux/svgalib/key.c @@ -0,0 +1,383 @@ +/// SDL keyboard input support + +#include +#include + +#include + +#include "event.h" +#include "error.h" +#include "key.h" +#include "timer.h" + +//added on 9/3/98 by Matt Mueller to free some cpu instead of hogging during menus and such +#include "d_delay.h" +//end this section addition - Matt Mueller + +#define KEY_BUFFER_SIZE 16 + +static unsigned char Installed = 0; + +//-------- Variable accessed by outside functions --------- +unsigned char keyd_buffer_type; // 0=No buffer, 1=buffer ASCII, 2=buffer scans +unsigned char keyd_repeat; +unsigned char keyd_editor_mode; +volatile unsigned char keyd_last_pressed; +volatile unsigned char keyd_last_released; +volatile unsigned char keyd_pressed[256]; +volatile int keyd_time_when_last_pressed; + +typedef struct Key_info { + ubyte state; // state of key 1 == down, 0 == up + ubyte last_state; // previous state of key + int counter; // incremented each time key is down in handler + fix timewentdown; // simple counter incremented each time in interrupt and key is down + fix timehelddown; // counter to tell how long key is down -- gets reset to 0 by key routines + ubyte downcount; // number of key counts key was down + ubyte upcount; // number of times key was released +} Key_info; + +typedef struct keyboard { + unsigned short keybuffer[KEY_BUFFER_SIZE]; + Key_info keys[256]; + fix time_pressed[KEY_BUFFER_SIZE]; + unsigned int keyhead, keytail; +} keyboard; + +static /*volatile*/ keyboard key_data; + +char * key_text[256] = { +"","ESC","1","2","3","4","5","6","7","8","9","0","-", +"=","BSPC","TAB","Q","W","E","R","T","Y","U","I","O", +"P","[","]","ƒ","LCTRL","A","S","D","F", +"G","H","J","K","L",";","'","`", +"LSHFT","\\","Z","X","C","V","B","N","M",",", +".","/","RSHFT","PAD*","LALT","SPC", +"CPSLK","F1","F2","F3","F4","F5","F6","F7","F8","F9", +"F10","NMLCK","SCLK","PAD7","PAD8","PAD9","PAD-", +"PAD4","PAD5","PAD6","PAD+","PAD1","PAD2","PAD3","PAD0", +"PAD.","","","","F11","F12","","","","","","","","","", +"","","","","","","","","","","","","","","","","","","","", +"","","","","","","","","","","","","","","","","","","","", +"","","","","","","","","","","","","","","","","","", +"PADƒ","RCTRL","","","","","","","","","","","","","", +"","","","","","","","","","","PAD/","","","RALT","", +"","","","","","","","","","","","","","HOME","‚","PGUP", +"","","","","","END","€","PGDN","INS", +"DEL","","","","","","","","","","","","","","","","","", +"","","","","","","","","","","","","","","","","","","","", +"","","","","","","" }; + +unsigned char ascii_table[128] = +{ 255, 255, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=',255,255, + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 255, 255, + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', 39, '`', + 255, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 255,'*', + 255, ' ', 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255,255, + 255, 255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255 }; + +unsigned char shifted_ascii_table[128] = +{ 255, 255, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+',255,255, + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 255, 255, + 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', + 255, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 255,255, + 255, ' ', 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255,255, + 255, 255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255 }; + +//killed on 10/03/98 by Matt Mueller +//unsigned char key_to_ascii(int a) +//{ +// if (!isprint(a)) return 255; +// if (a & KEY_SHIFTED) { +// return (toupper((unsigned char) a)); +// } else { +// return ((unsigned char) a); +// } +//} +//end kill -MM + +//added on 10/03/98 by Matt Mueller to fix shifted keys (copied from dos/key.c) +unsigned char key_to_ascii(int keycode) +{ + int shifted; + + shifted = keycode & KEY_SHIFTED; + keycode &= 0xFF; + + if ( keycode>=127 ) + return 255; + + if (shifted) + return shifted_ascii_table[keycode]; + else + return ascii_table[keycode]; +} +//end addition -MM + +void key_handler(int scancode, int press) +{ + ubyte state, key_state; + int i, keycode, event_key; + Key_info *key; + unsigned char temp; + + if (press == KEY_EVENTPRESS) + key_state = 1; + else if (press == KEY_EVENTRELEASE) + key_state = 0; + else + return; + + event_key = scancode; + + //===================================================== + //Here a translation from win keycodes to mac keycodes! + //===================================================== + + for (i = 255; i >= 0; i--) { + + keycode = i; + key = &(key_data.keys[keycode]); + if (i == event_key) + state = key_state; + else + state = key->last_state; + + if ( key->last_state == state ) { + if (state) { + key->counter++; + keyd_last_pressed = keycode; + keyd_time_when_last_pressed = timer_get_fixed_seconds(); + } + } else { + if (state) { + keyd_last_pressed = keycode; + keyd_pressed[keycode] = 1; + key->downcount += state; + key->state = 1; + key->timewentdown = keyd_time_when_last_pressed = timer_get_fixed_seconds(); + key->counter++; + } else { + keyd_pressed[keycode] = 0; + keyd_last_released = keycode; + key->upcount += key->state; + key->state = 0; + key->counter = 0; + key->timehelddown += timer_get_fixed_seconds() - key->timewentdown; + } + } + if ( (state && !key->last_state) || (state && key->last_state && (key->counter > 30) && (key->counter & 0x01)) ) { + if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT]) + keycode |= KEY_SHIFTED; + if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT]) + keycode |= KEY_ALTED; + if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL]) + keycode |= KEY_CTRLED; + if ( keyd_pressed[KEY_DELETE] ) + keycode |= KEY_DEBUGGED; + temp = key_data.keytail+1; + if ( temp >= KEY_BUFFER_SIZE ) temp=0; + if (temp!=key_data.keyhead) { + key_data.keybuffer[key_data.keytail] = keycode; + key_data.time_pressed[key_data.keytail] = keyd_time_when_last_pressed; + key_data.keytail = temp; + } + } + key->last_state = state; + } +} + +void key_close() +{ + Installed = 0; + keyboard_close(); +} + +void key_init() +{ + if (keyboard_init()) + Error ("SVGAlib Keyboard Init Failed"); + Installed=1; + + keyboard_seteventhandler (key_handler); + keyd_time_when_last_pressed = timer_get_fixed_seconds(); + keyd_buffer_type = 1; + keyd_repeat = 1; + +// Clear the keyboard array + key_flush(); + atexit(key_close); +} + +void key_flush() +{ + int i; + fix curtime; + + if (!Installed) + key_init(); + + key_data.keyhead = key_data.keytail = 0; + + //Clear the keyboard buffer + for (i=0; i= KEY_BUFFER_SIZE ) n=0; + return n; +} + +int key_checkch() +{ + int is_one_waiting = 0; + event_poll(); + if (key_data.keytail!=key_data.keyhead) + is_one_waiting = 1; + return is_one_waiting; +} + +int key_inkey() +{ + int key = 0; + if (!Installed) + key_init(); + event_poll(); + if (key_data.keytail!=key_data.keyhead) { + key = key_data.keybuffer[key_data.keyhead]; + key_data.keyhead = add_one(key_data.keyhead); + } +//added 9/3/98 by Matt Mueller to free cpu time instead of hogging during menus and such +// else d_delay(1); +//end addition - Matt Mueller + return key; +} + +int key_inkey_time(fix * time) +{ + int key = 0; + + if (!Installed) + key_init(); + event_poll(); + if (key_data.keytail!=key_data.keyhead) { + key = key_data.keybuffer[key_data.keyhead]; + *time = key_data.time_pressed[key_data.keyhead]; + key_data.keyhead = add_one(key_data.keyhead); + } + return key; +} + +int key_peekkey() +{ + int key = 0; + event_poll(); + if (key_data.keytail!=key_data.keyhead) + key = key_data.keybuffer[key_data.keyhead]; + + return key; +} + +int key_getch() +{ + int dummy=0; + + if (!Installed) + return 0; +// return getch(); + + while (!key_checkch()) + dummy++; + return key_inkey(); +} + +unsigned int key_get_shift_status() +{ + unsigned int shift_status = 0; + + if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT] ) + shift_status |= KEY_SHIFTED; + + if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT] ) + shift_status |= KEY_ALTED; + + if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL] ) + shift_status |= KEY_CTRLED; + +#ifndef NDEBUG + if (keyd_pressed[KEY_DELETE]) + shift_status |=KEY_DEBUGGED; +#endif + + return shift_status; +} + +// Returns the number of seconds this key has been down since last call. +fix key_down_time(int scancode) +{ + fix time_down, time; + + event_poll(); + if ((scancode<0)|| (scancode>255)) return 0; + + if (!keyd_pressed[scancode]) { + time_down = key_data.keys[scancode].timehelddown; + key_data.keys[scancode].timehelddown = 0; + } else { + time = timer_get_fixed_seconds(); + time_down = time - key_data.keys[scancode].timewentdown; + key_data.keys[scancode].timewentdown = time; + } + + return time_down; +} + +unsigned int key_down_count(int scancode) +{ + int n; + event_poll(); + if ((scancode<0)|| (scancode>255)) return 0; + + n = key_data.keys[scancode].downcount; + key_data.keys[scancode].downcount = 0; + + return n; +} + +unsigned int key_up_count(int scancode) +{ + int n; + event_poll(); + if ((scancode<0)|| (scancode>255)) return 0; + + n = key_data.keys[scancode].upcount; + key_data.keys[scancode].upcount = 0; + + return n; +} + diff --git a/arch/linux/svgalib/mouse.c b/arch/linux/svgalib/mouse.c new file mode 100644 index 00000000..4e528c67 --- /dev/null +++ b/arch/linux/svgalib/mouse.c @@ -0,0 +1,197 @@ +#include +#include +#include +#include "fix.h" +#include "timer.h" +#include "event.h" +#include "mouse.h" + +ubyte installed = 0; + +struct mousebutton { + ubyte pressed; + fix time_went_down; + fix time_held_down; + uint num_downs; + uint num_ups; +}; + +static struct mouseinfo { + struct mousebutton buttons[MOUSE_MAX_BUTTONS]; +//added on 10/17/98 by Hans de Goede for mouse functionality + int min_x, min_y; + int max_x, max_y; + int delta_x, delta_y; + int x,y; +//end this section addition - Hans +} Mouse; + +void mouse_handler (int button, int dx, int dy, int dz, int drx, int dry, int drz) +{ + int i; + for (i = 0; i < 8; i++) + { + if (button & (1 << i)) + { + Mouse.buttons[i].pressed = 1; + Mouse.buttons[i].time_went_down = timer_get_fixed_seconds(); + Mouse.buttons[i].num_downs++; + } + else + { + Mouse.buttons[i].pressed = 0; + Mouse.buttons[i].time_held_down += timer_get_fixed_seconds() - Mouse.buttons[i].time_went_down; + Mouse.buttons[i].num_ups++; + } + } + Mouse.delta_x += dx; + Mouse.delta_y += dy; + Mouse.x += dx; + Mouse.y += dy; + if (Mouse.x > Mouse.max_x) Mouse.x = Mouse.max_x; + else if (Mouse.x < Mouse.min_x) Mouse.x = Mouse.min_x; + if (Mouse.y > Mouse.max_y) Mouse.y = Mouse.max_y; + else if (Mouse.y < Mouse.min_y) Mouse.y = Mouse.min_y; +} + +void d_mouse_close(void) +{ + if (installed) + vga_setmousesupport(0); + installed = 0; +} + +void d_mouse_init(void) +{ + memset(&Mouse,0,sizeof(Mouse)); + vga_setmousesupport(1); + if (!installed) + atexit(d_mouse_close); + installed = 1; +} + +int mouse_set_limits( int x1, int y1, int x2, int y2 ) +{ + event_poll(); + Mouse.min_x = x1; + Mouse.min_y = y1; + Mouse.max_x = x2; + Mouse.max_y = y2; + return 0; +} + +void mouse_flush() // clears all mice events... +{ + int i; + fix current_time; + + event_poll(); + + current_time = timer_get_fixed_seconds(); + for (i=0; i Mouse.max_x) Mouse.x = Mouse.max_x; + else if (Mouse.x < Mouse.min_x) Mouse.x = Mouse.min_x; + if (Mouse.y > Mouse.max_y) Mouse.y = Mouse.max_y; + else if (Mouse.y < Mouse.min_y) Mouse.y = Mouse.min_y; +//end this section change - Hans +} + +void mouse_get_cyberman_pos( int *x, int *y ) +{ + // Shrug... + event_poll(); +} + +// Returns how long this button has been down since last call. +fix mouse_button_down_time(int button) +{ + fix time_down, time; + + event_poll(); + + if (!Mouse.buttons[button].pressed) { + time_down = Mouse.buttons[button].time_held_down; + Mouse.buttons[button].time_held_down = 0; + } else { + time = timer_get_fixed_seconds(); + time_down = time - Mouse.buttons[button].time_held_down; + Mouse.buttons[button].time_held_down = time; + } + return time_down; +} + +// Returns how many times this button has went down since last call +int mouse_button_down_count(int button) +{ + int count; + + event_poll(); + + count = Mouse.buttons[button].num_downs; + Mouse.buttons[button].num_downs = 0; + + return count; +} + +// Returns 1 if this button is currently down +int mouse_button_state(int button) +{ + event_poll(); + return Mouse.buttons[button].pressed; +} + + diff --git a/arch/linux/timer.c b/arch/linux/timer.c new file mode 100644 index 00000000..3e62162f --- /dev/null +++ b/arch/linux/timer.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include "maths.h" + +static struct timeval tv_old; + +fix timer_get_fixed_seconds(void) +{ + fix x; + struct timeval tv_now; + gettimeofday(&tv_now, NULL); + x=i2f(tv_now.tv_sec - tv_old.tv_sec) + fixdiv(i2f((tv_now.tv_usec - tv_old.tv_usec)/1000), i2f(1000)); + return x; +} + +void timer_init(void) +{ + gettimeofday(&tv_old, NULL); +} diff --git a/arch/linux/ukali.c b/arch/linux/ukali.c new file mode 100644 index 00000000..30cd7ffc --- /dev/null +++ b/arch/linux/ukali.c @@ -0,0 +1,257 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ukali.h" +//added 05/17/99 Matt Mueller - needed to redefine FD_* so that no asm is used +//#include "checker.h" +//end addition -MM +int g_sockfd = -1; +struct sockaddr_in kalinix_addr; +char g_mynodenum[6]; + +int knix_newSock(void) { + + int tempsock; + struct sockaddr_in taddr; + + taddr.sin_family = AF_INET; + taddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + taddr.sin_port = 0; + + if ((tempsock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return -1; + + fcntl(tempsock, F_SETFL, fcntl(tempsock, F_GETFL) | O_NONBLOCK); + + if ((bind(tempsock, (struct sockaddr *)&taddr, sizeof(taddr))) < 0) { + close(tempsock); + return -1; + } + return tempsock; +} + +int knix_Send(int hand, char *data, int len) { + int i = 0, t; + + while ((t = sendto(hand, data, len, 0, (struct sockaddr *)&kalinix_addr, + sizeof(kalinix_addr))) < 0) { + i++; + if (i > 10) + return 0; + } + + return t; +} + +int knix_Recv(int hand, char *data, int len) { + struct sockaddr_in taddr; + int tlen; + + tlen = sizeof(taddr); + + return recvfrom(hand, data, len, 0, (struct sockaddr *)&taddr, &tlen); + +} + +int knix_WaitforSocket(int hand, int timems) { + fd_set set; + struct timeval tv; + + FD_ZERO(&set); + FD_SET(hand, &set); + tv.tv_sec = 0; + // 100ms + tv.tv_usec = timems * 1000; + return select(hand + 1, &set, NULL, NULL, &tv); +} + +int knix_ReceivePacket(int hand, char *outdata, int *outlen, kaliaddr_ipx *from) { + static char data[MAX_PACKET_SIZE]; + int len; + + len = knix_Recv(hand, data, sizeof(data)); + + if (len <= 0) return 0; + + switch (data[0]) { +// case 1: // open socket +// break; +// case 2: // close socket +// break; + case 3: // received data packet + if (len < 11) break; + if (!outdata) + break; + from->sa_family = AF_IPX; + memcpy(from->sa_nodenum, &data[1], sizeof(from->sa_nodenum)); + memset(from->sa_netnum, 0, sizeof(from->sa_netnum)); + memcpy(&from->sa_socket, &data[9], sizeof(unsigned short)); + memcpy(outdata, &data[11], len-11 > *outlen ? *outlen : len-11); + *outlen = len-11; + break; + case 4: // myipxaddress + if (len < 7) break; + memcpy(g_mynodenum, &data[1], 6); + break; +// case 5: // Init KaliNix connection +// break; + case 6: // open response + case 7: // close response + if (len < 3) break; +// memcpy(g_LastPort, &data[1], sizeof(g_LastPort)) + break; + } + + return data[0]; + +} + +int knix_GetMyAddress(void) { + char initdata[1]; + + if (g_sockfd < 0) { + kalinix_addr.sin_family = AF_INET; + kalinix_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + kalinix_addr.sin_port = htons(4213); + + g_sockfd = knix_newSock(); + } + + initdata[0] = 5; // Get Address + knix_Send(g_sockfd, initdata, sizeof(initdata)); + + return 0; + +} + +int KaliSendPacket(int hand, char *data, int len, kaliaddr_ipx *to) { + static char sendbuf[MAX_PACKET_SIZE+11]; +// char code; == 3 +// char sa_nodenum[6]; +// char dport[2]; +// char sport[2]; +// char data[]; + + sendbuf[0] = 3; + memcpy(&sendbuf[1], to->sa_nodenum, sizeof(to->sa_nodenum)); + memcpy(&sendbuf[7], &to->sa_socket, sizeof(to->sa_socket)); + memset(&sendbuf[9], 0, sizeof(to->sa_socket)); + len = len > MAX_PACKET_SIZE ? MAX_PACKET_SIZE : len; + memcpy(&sendbuf[11], data, len); + + if (!knix_Send(hand, sendbuf, len+11)){ + return -1; + } + return len; + +} + +int KaliReceivePacket(int hand, char *data, int len, kaliaddr_ipx *from) { + int newlen; + int t; + + newlen = len; + + t = knix_ReceivePacket(hand, data, &newlen, from); + + while (t != 0 && t != 3) + t = knix_ReceivePacket(hand, data, &newlen, from); + + if (t == 3) + return newlen; + else return -1; + +} + +int KaliGetNodeNum(kaliaddr_ipx *myaddr) { + int tcount = 0; + + if (g_sockfd < 0 && knix_GetMyAddress()) + return -1; + + while (tcount < 5) { + if (knix_WaitforSocket(g_sockfd, 100) > 0) { + if (knix_ReceivePacket(g_sockfd, NULL, 0, NULL) == 4) + break; + continue; + } + knix_GetMyAddress(); + tcount++; + } + if (tcount == 5) + return -1; + + close(g_sockfd); + g_sockfd = -1; + memcpy(myaddr->sa_nodenum, g_mynodenum, sizeof(g_mynodenum)); + + return 0; + +} + +int KaliCloseSocket(int hand) { + char opendata[3] = {2, 0, 0}; + int tcount = 0; + + knix_Send(hand, opendata, sizeof(opendata)); + + while (tcount < 5) { + + if (knix_WaitforSocket(hand, 100) > 0) { + if (knix_ReceivePacket(hand, NULL, 0, NULL) == 7) + break; + continue; + } + knix_Send(hand, opendata, sizeof(opendata)); + tcount++; + } + close(hand); + return 0; + +} + +int KaliOpenSocket(unsigned short port) { + char opendata[16]; + int hand; + int tcount = 0; + long pid; + + opendata[0] = 1; // open socket + memcpy(&opendata[1], &port, sizeof(port)); + pid = (int)htonl(getpid()); + memcpy(&opendata[3], &pid, sizeof(pid)); + strncpy(&opendata[7], KALI_PROCESS_NAME, sizeof(KALI_PROCESS_NAME)); + opendata[15] = 0; + + if ((hand = knix_newSock()) < 0) + return -1; + + knix_Send(hand, opendata, sizeof(opendata)); + + while (tcount < 5) { + + if (knix_WaitforSocket(hand, 100) > 0) { + if (knix_ReceivePacket(hand, NULL, 0, NULL) == 6) + break; + continue; + } + knix_Send(hand, opendata, sizeof(opendata)); + tcount++; + } + + if (tcount == 5) { + close(hand); + return -1; + } + + return hand; +} + diff --git a/arch/ogl/include/loadgl.h b/arch/ogl/include/loadgl.h new file mode 100644 index 00000000..40361dd8 --- /dev/null +++ b/arch/ogl/include/loadgl.h @@ -0,0 +1,1935 @@ +//loadgl.h - dynamic opengl loading - curtousy (sp) of Jeff Slutter + +#ifndef __LOADGL_H__ +#define __LOADGL_H__ + +#ifndef WIN32 +#ifdef __WINDOWS__ +#define WIN32 +#endif +#endif + +#if defined(WIN32) +#include +#define OGLFUNCCALL __stdcall +#else +#define OGLFUNCCALL +#endif + +#include +#include "types.h" + +#ifdef _cplusplus +#define OEXTERN extern "C" +#else +#define OEXTERN extern +#define true 1 +#define false 0 +#endif + +#ifdef DECLARE_VARS +#define DEFVAR +#else +#define DEFVAR OEXTERN +#endif + +#define glAccum dglAccum +#define glAlphaFunc dglAlphaFunc +#define glAreTexturesResident dglAreTexturesResident +#define glArrayElement dglArrayElement +#define glBegin dglBegin +#define glBindTexture dglBindTexture +#define glBitmap dglBitmap +#define glBlendFunc dglBlendFunc +#define glCallList dglCallList +#define glCallLists dglCallLists +#define glClear dglClear +#define glClearAccum dglClearAccum +#define glClearColor dglClearColor +#define glClearDepth dglClearDepth +#define glClearIndex dglClearIndex +#define glClearStencil dglClearStencil +#define glClipPlane dglClipPlane +#define glColor3b dglColor3b +#define glColor3bv dglColor3bv +#define glColor3d dglColor3d +#define glColor3dv dglColor3dv +#define glColor3f dglColor3f +#define glColor3fv dglColor3fv +#define glColor3i dglColor3i +#define glColor3iv dglColor3iv +#define glColor3s dglColor3s +#define glColor3sv dglColor3sv +#define glColor3ub dglColor3ub +#define glColor3ubv dglColor3ubv +#define glColor3ui dglColor3ui +#define glColor3uiv dglColor3uiv +#define glColor3us dglColor3us +#define glColor3usv dglColor3usv +#define glColor4b dglColor4b +#define glColor4bv dglColor4bv +#define glColor4d dglColor4d +#define glColor4dv dglColor4dv +#define glColor4f dglColor4f +#define glColor4fv dglColor4fv +#define glColor4i dglColor4i +#define glColor4iv dglColor4iv +#define glColor4s dglColor4s +#define glColor4sv dglColor4sv +#define glColor4ub dglColor4ub +#define glColor4ubv dglColor4ubv +#define glColor4ui dglColor4ui +#define glColor4uiv dglColor4uiv +#define glColor4us dglColor4us +#define glColor4usv dglColor4usv +#define glColorMask dglColorMask +#define glColorMaterial dglColorMaterial +#define glColorPointer dglColorPointer +#define glCopyPixels dglCopyPixels +#define glCopyTexImage1D dglCopyTexImage1D +#define glCopyTexImage2D dglCopyTexImage2D +#define glCopyTexSubImage1D dglCopyTexSubImage1D +#define glCopyTexSubImage2D dglCopyTexSubImage2D +#define glCullFace dglCullFace +#define glDeleteLists dglDeleteLists +#define glDeleteTextures dglDeleteTextures +#define glDepthFunc dglDepthFunc +#define glDepthMask dglDepthMask +#define glDepthRange dglDepthRange +#define glDisable dglDisable +#define glDisableClientState dglDisableClientState +#define glDrawArrays dglDrawArrays +#define glDrawBuffer dglDrawBuffer +#define glDrawElements dglDrawElements +#define glDrawPixels dglDrawPixels +#define glEdgeFlag dglEdgeFlag +#define glEdgeFlagPointer dglEdgeFlagPointer +#define glEdgeFlagv dglEdgeFlagv +#define glEnable dglEnable +#define glEnableClientState dglEnableClientState +#define glEnd dglEnd +#define glEndList dglEndList +#define glEvalCoord1d dglEvalCoord1d +#define glEvalCoord1dv dglEvalCoord1dv +#define glEvalCoord1f dglEvalCoord1f +#define glEvalCoord1fv dglEvalCoord1fv +#define glEvalCoord2d dglEvalCoord2d +#define glEvalCoord2dv dglEvalCoord2dv +#define glEvalCoord2f dglEvalCoord2f +#define glEvalCoord2fv dglEvalCoord2fv +#define glEvalMesh1 dglEvalMesh1 +#define glEvalMesh2 dglEvalMesh2 +#define glEvalPoint1 dglEvalPoint1 +#define glEvalPoint2 dglEvalPoint2 +#define glFeedbackBuffer dglFeedbackBuffer +#define glFinish dglFinish +#define glFlush dglFlush +#define glFogf dglFogf +#define glFogfv dglFogfv +#define glFogi dglFogi +#define glFogiv dglFogiv +#define glFrontFace dglFrontFace +#define glFrustum dglFrustum +#define glGenLists dglGenLists +#define glGenTextures dglGenTextures +#define glGetBooleanv dglGetBooleanv +#define glGetClipPlane dglGetClipPlane +#define glGetDoublev dglGetDoublev +#define glGetError dglGetError +#define glGetFloatv dglGetFloatv +#define glGetIntegerv dglGetIntegerv +#define glGetLightfv dglGetLightfv +#define glGetLightiv dglGetLightiv +#define glGetMapdv dglGetMapdv +#define glGetMapfv dglGetMapfv +#define glGetMapiv dglGetMapiv +#define glGetMaterialfv dglGetMaterialfv +#define glGetMaterialiv dglGetMaterialiv +#define glGetPixelMapfv dglGetPixelMapfv +#define glGetPixelMapuiv dglGetPixelMapuiv +#define glGetPixelMapusv dglGetPixelMapusv +#define glGetPointerv dglGetPointerv +#define glGetPolygonStipple dglGetPolygonStipple +#define glGetString dglGetString +#define glGetTexEnvfv dglGetTexEnvfv +#define glGetTexEnviv dglGetTexEnviv +#define glGetTexGendv dglGetTexGendv +#define glGetTexGenfv dglGetTexGenfv +#define glGetTexGeniv dglGetTexGeniv +#define glGetTexImage dglGetTexImage +#define glGetTexLevelParameterfv dglGetTexLevelParameterfv +#define glGetTexLevelParameteriv dglGetTexLevelParameteriv +#define glGetTexParameterfv dglGetTexParameterfv +#define glGetTexParameteriv dglGetTexParameteriv +#define glHint dglHint +#define glIndexMask dglIndexMask +#define glIndexPointer dglIndexPointer +#define glIndexd dglIndexd +#define glIndexdv dglIndexdv +#define glIndexf dglIndexf +#define glIndexfv dglIndexfv +#define glIndexi dglIndexi +#define glIndexiv dglIndexiv +#define glIndexs dglIndexs +#define glIndexsv dglIndexsv +#define glIndexub dglIndexub +#define glIndexubv dglIndexubv +#define glInitNames dglInitNames +#define glInterleavedArrays dglInterleavedArrays +#define glIsEnabled dglIsEnabled +#define glIsList dglIsList +#define glIsTexture dglIsTexture +#define glLightModelf dglLightModelf +#define glLightModelfv dglLightModelfv +#define glLightModeli dglLightModeli +#define glLightModeliv dglLightModeliv +#define glLightf dglLightf +#define glLightfv dglLightfv +#define glLighti dglLighti +#define glLightiv dglLightiv +#define glLineStipple dglLineStipple +#define glLineWidth dglLineWidth +#define glListBase dglListBase +#define glLoadIdentity dglLoadIdentity +#define glLoadMatrixd dglLoadMatrixd +#define glLoadMatrixf dglLoadMatrixf +#define glLoadName dglLoadName +#define glLogicOp dglLogicOp +#define glMap1d dglMap1d +#define glMap1f dglMap1f +#define glMap2d dglMap2d +#define glMap2f dglMap2f +#define glMapGrid1d dglMapGrid1d +#define glMapGrid1f dglMapGrid1f +#define glMapGrid2d dglMapGrid2d +#define glMapGrid2f dglMapGrid2f +#define glMaterialf dglMaterialf +#define glMaterialfv dglMaterialfv +#define glMateriali dglMateriali +#define glMaterialiv dglMaterialiv +#define glMatrixMode dglMatrixMode +#define glMultMatrixd dglMultMatrixd +#define glMultMatrixf dglMultMatrixf +#define glNewList dglNewList +#define glNormal3b dglNormal3b +#define glNormal3bv dglNormal3bv +#define glNormal3d dglNormal3d +#define glNormal3dv dglNormal3dv +#define glNormal3f dglNormal3f +#define glNormal3fv dglNormal3fv +#define glNormal3i dglNormal3i +#define glNormal3iv dglNormal3iv +#define glNormal3s dglNormal3s +#define glNormal3sv dglNormal3sv +#define glNormalPointer dglNormalPointer +#define glOrtho dglOrtho +#define glPassThrough dglPassThrough +#define glPixelMapfv dglPixelMapfv +#define glPixelMapuiv dglPixelMapuiv +#define glPixelMapusv dglPixelMapusv +#define glPixelStoref dglPixelStoref +#define glPixelStorei dglPixelStorei +#define glPixelTransferf dglPixelTransferf +#define glPixelTransferi dglPixelTransferi +#define glPixelZoom dglPixelZoom +#define glPointSize dglPointSize +#define glPolygonMode dglPolygonMode +#define glPolygonOffset dglPolygonOffset +#define glPolygonStipple dglPolygonStipple +#define glPopAttrib dglPopAttrib +#define glPopClientAttrib dglPopClientAttrib +#define glPopMatrix dglPopMatrix +#define glPopName dglPopName +#define glPrioritizeTextures dglPrioritizeTextures +#define glPushAttrib dglPushAttrib +#define glPushClientAttrib dglPushClientAttrib +#define glPushMatrix dglPushMatrix +#define glPushName dglPushName +#define glRasterPos2d dglRasterPos2d +#define glRasterPos2dv dglRasterPos2dv +#define glRasterPos2f dglRasterPos2f +#define glRasterPos2fv dglRasterPos2fv +#define glRasterPos2i dglRasterPos2i +#define glRasterPos2iv dglRasterPos2iv +#define glRasterPos2s dglRasterPos2s +#define glRasterPos2sv dglRasterPos2sv +#define glRasterPos3d dglRasterPos3d +#define glRasterPos3dv dglRasterPos3dv +#define glRasterPos3f dglRasterPos3f +#define glRasterPos3fv dglRasterPos3fv +#define glRasterPos3i dglRasterPos3i +#define glRasterPos3iv dglRasterPos3iv +#define glRasterPos3s dglRasterPos3s +#define glRasterPos3sv dglRasterPos3sv +#define glRasterPos4d dglRasterPos4d +#define glRasterPos4dv dglRasterPos4dv +#define glRasterPos4f dglRasterPos4f +#define glRasterPos4fv dglRasterPos4fv +#define glRasterPos4i dglRasterPos4i +#define glRasterPos4iv dglRasterPos4iv +#define glRasterPos4s dglRasterPos4s +#define glRasterPos4sv dglRasterPos4sv +#define glReadBuffer dglReadBuffer +#define glReadPixels dglReadPixels +#define glRectd dglRectd +#define glRectdv dglRectdv +#define glRectf dglRectf +#define glRectfv dglRectfv +#define glRecti dglRecti +#define glRectiv dglRectiv +#define glRects dglRects +#define glRectsv dglRectsv +#define glRenderMode dglRenderMode +#define glRotated dglRotated +#define glRotatef dglRotatef +#define glScaled dglScaled +#define glScalef dglScalef +#define glScissor dglScissor +#define glSelectBuffer dglSelectBuffer +#define glShadeModel dglShadeModel +#define glStencilFunc dglStencilFunc +#define glStencilMask dglStencilMask +#define glStencilOp dglStencilOp +#define glTexCoord1d dglTexCoord1d +#define glTexCoord1dv dglTexCoord1dv +#define glTexCoord1f dglTexCoord1f +#define glTexCoord1fv dglTexCoord1fv +#define glTexCoord1i dglTexCoord1i +#define glTexCoord1iv dglTexCoord1iv +#define glTexCoord1s dglTexCoord1s +#define glTexCoord1sv dglTexCoord1sv +#define glTexCoord2d dglTexCoord2d +#define glTexCoord2dv dglTexCoord2dv +#define glTexCoord2f dglTexCoord2f +#define glTexCoord2fv dglTexCoord2fv +#define glTexCoord2i dglTexCoord2i +#define glTexCoord2iv dglTexCoord2iv +#define glTexCoord2s dglTexCoord2s +#define glTexCoord2sv dglTexCoord2sv +#define glTexCoord3d dglTexCoord3d +#define glTexCoord3dv dglTexCoord3dv +#define glTexCoord3f dglTexCoord3f +#define glTexCoord3fv dglTexCoord3fv +#define glTexCoord3i dglTexCoord3i +#define glTexCoord3iv dglTexCoord3iv +#define glTexCoord3s dglTexCoord3s +#define glTexCoord3sv dglTexCoord3sv +#define glTexCoord4d dglTexCoord4d +#define glTexCoord4dv dglTexCoord4dv +#define glTexCoord4f dglTexCoord4f +#define glTexCoord4fv dglTexCoord4fv +#define glTexCoord4i dglTexCoord4i +#define glTexCoord4iv dglTexCoord4iv +#define glTexCoord4s dglTexCoord4s +#define glTexCoord4sv dglTexCoord4sv +#define glTexCoordPointer dglTexCoordPointer +#define glTexEnvf dglTexEnvf +#define glTexEnvfv dglTexEnvfv +#define glTexEnvi dglTexEnvi +#define glTexEnviv dglTexEnviv +#define glTexGend dglTexGend +#define glTexGendv dglTexGendv +#define glTexGenf dglTexGenf +#define glTexGenfv dglTexGenfv +#define glTexGeni dglTexGeni +#define glTexGeniv dglTexGeniv +#define glTexImage1D dglTexImage1D +#define glTexImage2D dglTexImage2D +#define glTexParameterf dglTexParameterf +#define glTexParameterfv dglTexParameterfv +#define glTexParameteri dglTexParameteri +#define glTexParameteriv dglTexParameteriv +#define glTexSubImage1D dglTexSubImage1D +#define glTexSubImage2D dglTexSubImage2D +#define glTranslated dglTranslated +#define glTranslatef dglTranslatef +#define glVertex2d dglVertex2d +#define glVertex2dv dglVertex2dv +#define glVertex2f dglVertex2f +#define glVertex2fv dglVertex2fv +#define glVertex2i dglVertex2i +#define glVertex2iv dglVertex2iv +#define glVertex2s dglVertex2s +#define glVertex2sv dglVertex2sv +#define glVertex3d dglVertex3d +#define glVertex3dv dglVertex3dv +#define glVertex3f dglVertex3f +#define glVertex3fv dglVertex3fv +#define glVertex3i dglVertex3i +#define glVertex3iv dglVertex3iv +#define glVertex3s dglVertex3s +#define glVertex3sv dglVertex3sv +#define glVertex4d dglVertex4d +#define glVertex4dv dglVertex4dv +#define glVertex4f dglVertex4f +#define glVertex4fv dglVertex4fv +#define glVertex4i dglVertex4i +#define glVertex4iv dglVertex4iv +#define glVertex4s dglVertex4s +#define glVertex4sv dglVertex4sv +#define glVertexPointer dglVertexPointer +#define glViewport dglViewport + + +#ifdef WIN32 +#define wglCopyContext dwglCopyContext +#define wglCreateContext dwglCreateContext +#define wglCreateLayerContext dwglCreateLayerContext +#define wglDeleteContext dwglDeleteContext +#define wglGetCurrentContext dwglGetCurrentContext +#define wglGetCurrentDC dwglGetCurrentDC +#define wglGetProcAddress dwglGetProcAddress +#define wglMakeCurrent dwglMakeCurrent +#define wglShareLists dwglShareLists +#define wglUseFontBitmapsA dwglUseFontBitmapsA +#define wglUseFontBitmapsW dwglUseFontBitmapsW +#define wglUseFontOutlinesA dwglUseFontOutlinesA +#define wglUseFontOutlinesW dwglUseFontOutlinesW +#define wglDescribeLayerPlane dwglDescribeLayerPlane +#define wglSetLayerPaletteEntries dwglSetLayerPaletteEntries +#define wglGetLayerPaletteEntries dwglGetLayerPaletteEntries +#define wglRealizeLayerPalette dwglRealizeLayerPalette +#define wglSwapLayerBuffers dwglSwapLayerBuffers +#if (WINVER >= 0x0500) +#define wglSwapMultipleBuffers dwglSwapMultipleBuffers +#endif +#endif + +typedef void (OGLFUNCCALL *glAccum_fp)(GLenum op, GLfloat value); +typedef void (OGLFUNCCALL *glAlphaFunc_fp)(GLenum func, GLclampf ref); +typedef GLboolean (OGLFUNCCALL *glAreTexturesResident_fp)(GLsizei n, const GLuint *textures, GLboolean *residences); +typedef void (OGLFUNCCALL *glArrayElement_fp)(GLint i); +typedef void (OGLFUNCCALL *glBegin_fp)(GLenum mode); +typedef void (OGLFUNCCALL *glBindTexture_fp)(GLenum target, GLuint texture); +typedef void (OGLFUNCCALL *glBitmap_fp)(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); +typedef void (OGLFUNCCALL *glBlendFunc_fp)(GLenum sfactor, GLenum dfactor); +typedef void (OGLFUNCCALL *glCallList_fp)(GLuint list); +typedef void (OGLFUNCCALL *glCallLists_fp)(GLsizei n, GLenum type, const GLvoid *lists); +typedef void (OGLFUNCCALL *glClear_fp)(GLbitfield mask); +typedef void (OGLFUNCCALL *glClearAccum_fp)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (OGLFUNCCALL *glClearColor_fp)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +typedef void (OGLFUNCCALL *glClearDepth_fp)(GLclampd depth); +typedef void (OGLFUNCCALL *glClearIndex_fp)(GLfloat c); +typedef void (OGLFUNCCALL *glClearStencil_fp)(GLint s); +typedef void (OGLFUNCCALL *glClipPlane_fp)(GLenum plane, const GLdouble *equation); +typedef void (OGLFUNCCALL *glColor3b_fp)(GLbyte red, GLbyte green, GLbyte blue); +typedef void (OGLFUNCCALL *glColor3bv_fp)(const GLbyte *v); +typedef void (OGLFUNCCALL *glColor3d_fp)(GLdouble red, GLdouble green, GLdouble blue); +typedef void (OGLFUNCCALL *glColor3dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glColor3f_fp)(GLfloat red, GLfloat green, GLfloat blue); +typedef void (OGLFUNCCALL *glColor3fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glColor3i_fp)(GLint red, GLint green, GLint blue); +typedef void (OGLFUNCCALL *glColor3iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glColor3s_fp)(GLshort red, GLshort green, GLshort blue); +typedef void (OGLFUNCCALL *glColor3sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glColor3ub_fp)(GLubyte red, GLubyte green, GLubyte blue); +typedef void (OGLFUNCCALL *glColor3ubv_fp)(const GLubyte *v); +typedef void (OGLFUNCCALL *glColor3ui_fp)(GLuint red, GLuint green, GLuint blue); +typedef void (OGLFUNCCALL *glColor3uiv_fp)(const GLuint *v); +typedef void (OGLFUNCCALL *glColor3us_fp)(GLushort red, GLushort green, GLushort blue); +typedef void (OGLFUNCCALL *glColor3usv_fp)(const GLushort *v); +typedef void (OGLFUNCCALL *glColor4b_fp)(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); +typedef void (OGLFUNCCALL *glColor4bv_fp)(const GLbyte *v); +typedef void (OGLFUNCCALL *glColor4d_fp)(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); +typedef void (OGLFUNCCALL *glColor4dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glColor4f_fp)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (OGLFUNCCALL *glColor4fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glColor4i_fp)(GLint red, GLint green, GLint blue, GLint alpha); +typedef void (OGLFUNCCALL *glColor4iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glColor4s_fp)(GLshort red, GLshort green, GLshort blue, GLshort alpha); +typedef void (OGLFUNCCALL *glColor4sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glColor4ub_fp)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +typedef void (OGLFUNCCALL *glColor4ubv_fp)(const GLubyte *v); +typedef void (OGLFUNCCALL *glColor4ui_fp)(GLuint red, GLuint green, GLuint blue, GLuint alpha); +typedef void (OGLFUNCCALL *glColor4uiv_fp)(const GLuint *v); +typedef void (OGLFUNCCALL *glColor4us_fp)(GLushort red, GLushort green, GLushort blue, GLushort alpha); +typedef void (OGLFUNCCALL *glColor4usv_fp)(const GLushort *v); +typedef void (OGLFUNCCALL *glColorMask_fp)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +typedef void (OGLFUNCCALL *glColorMaterial_fp)(GLenum face, GLenum mode); +typedef void (OGLFUNCCALL *glColorPointer_fp)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (OGLFUNCCALL *glCopyPixels_fp)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); +typedef void (OGLFUNCCALL *glCopyTexImage1D_fp)(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (OGLFUNCCALL *glCopyTexImage2D_fp)(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (OGLFUNCCALL *glCopyTexSubImage1D_fp)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (OGLFUNCCALL *glCopyTexSubImage2D_fp)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (OGLFUNCCALL *glCullFace_fp)(GLenum mode); +typedef void (OGLFUNCCALL *glDeleteLists_fp)(GLuint list, GLsizei range); +typedef void (OGLFUNCCALL *glDeleteTextures_fp)(GLsizei n, const GLuint *textures); +typedef void (OGLFUNCCALL *glDepthFunc_fp)(GLenum func); +typedef void (OGLFUNCCALL *glDepthMask_fp)(GLboolean flag); +typedef void (OGLFUNCCALL *glDepthRange_fp)(GLclampd zNear, GLclampd zFar); +typedef void (OGLFUNCCALL *glDisable_fp)(GLenum cap); +typedef void (OGLFUNCCALL *glDisableClientState_fp)(GLenum array); +typedef void (OGLFUNCCALL *glDrawArrays_fp)(GLenum mode, GLint first, GLsizei count); +typedef void (OGLFUNCCALL *glDrawBuffer_fp)(GLenum mode); +typedef void (OGLFUNCCALL *glDrawElements_fp)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +typedef void (OGLFUNCCALL *glDrawPixels_fp)(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (OGLFUNCCALL *glEdgeFlag_fp)(GLboolean flag); +typedef void (OGLFUNCCALL *glEdgeFlagPointer_fp)(GLsizei stride, const GLvoid *pointer); +typedef void (OGLFUNCCALL *glEdgeFlagv_fp)(const GLboolean *flag); +typedef void (OGLFUNCCALL *glEnable_fp)(GLenum cap); +typedef void (OGLFUNCCALL *glEnableClientState_fp)(GLenum array); +typedef void (OGLFUNCCALL *glEnd_fp)(void); +typedef void (OGLFUNCCALL *glEndList_fp)(void); +typedef void (OGLFUNCCALL *glEvalCoord1d_fp)(GLdouble u); +typedef void (OGLFUNCCALL *glEvalCoord1dv_fp)(const GLdouble *u); +typedef void (OGLFUNCCALL *glEvalCoord1f_fp)(GLfloat u); +typedef void (OGLFUNCCALL *glEvalCoord1fv_fp)(const GLfloat *u); +typedef void (OGLFUNCCALL *glEvalCoord2d_fp)(GLdouble u, GLdouble v); +typedef void (OGLFUNCCALL *glEvalCoord2dv_fp)(const GLdouble *u); +typedef void (OGLFUNCCALL *glEvalCoord2f_fp)(GLfloat u, GLfloat v); +typedef void (OGLFUNCCALL *glEvalCoord2fv_fp)(const GLfloat *u); +typedef void (OGLFUNCCALL *glEvalMesh1_fp)(GLenum mode, GLint i1, GLint i2); +typedef void (OGLFUNCCALL *glEvalMesh2_fp)(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); +typedef void (OGLFUNCCALL *glEvalPoint1_fp)(GLint i); +typedef void (OGLFUNCCALL *glEvalPoint2_fp)(GLint i, GLint j); +typedef void (OGLFUNCCALL *glFeedbackBuffer_fp)(GLsizei size, GLenum type, GLfloat *buffer); +typedef void (OGLFUNCCALL *glFinish_fp)(void); +typedef void (OGLFUNCCALL *glFlush_fp)(void); +typedef void (OGLFUNCCALL *glFogf_fp)(GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glFogfv_fp)(GLenum pname, const GLfloat *params); +typedef void (OGLFUNCCALL *glFogi_fp)(GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glFogiv_fp)(GLenum pname, const GLint *params); +typedef void (OGLFUNCCALL *glFrontFace_fp)(GLenum mode); +typedef void (OGLFUNCCALL *glFrustum_fp)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +typedef GLuint (OGLFUNCCALL *glGenLists_fp)(GLsizei range); +typedef void (OGLFUNCCALL *glGenTextures_fp)(GLsizei n, GLuint *textures); +typedef void (OGLFUNCCALL *glGetBooleanv_fp)(GLenum pname, GLboolean *params); +typedef void (OGLFUNCCALL *glGetClipPlane_fp)(GLenum plane, GLdouble *equation); +typedef void (OGLFUNCCALL *glGetDoublev_fp)(GLenum pname, GLdouble *params); +typedef GLenum (OGLFUNCCALL *glGetError_fp)(void); +typedef void (OGLFUNCCALL *glGetFloatv_fp)(GLenum pname, GLfloat *params); +typedef void (OGLFUNCCALL *glGetIntegerv_fp)(GLenum pname, GLint *params); +typedef void (OGLFUNCCALL *glGetLightfv_fp)(GLenum light, GLenum pname, GLfloat *params); +typedef void (OGLFUNCCALL *glGetLightiv_fp)(GLenum light, GLenum pname, GLint *params); +typedef void (OGLFUNCCALL *glGetMapdv_fp)(GLenum target, GLenum query, GLdouble *v); +typedef void (OGLFUNCCALL *glGetMapfv_fp)(GLenum target, GLenum query, GLfloat *v); +typedef void (OGLFUNCCALL *glGetMapiv_fp)(GLenum target, GLenum query, GLint *v); +typedef void (OGLFUNCCALL *glGetMaterialfv_fp)(GLenum face, GLenum pname, GLfloat *params); +typedef void (OGLFUNCCALL *glGetMaterialiv_fp)(GLenum face, GLenum pname, GLint *params); +typedef void (OGLFUNCCALL *glGetPixelMapfv_fp)(GLenum map, GLfloat *values); +typedef void (OGLFUNCCALL *glGetPixelMapuiv_fp)(GLenum map, GLuint *values); +typedef void (OGLFUNCCALL *glGetPixelMapusv_fp)(GLenum map, GLushort *values); +typedef void (OGLFUNCCALL *glGetPointerv_fp)(GLenum pname, GLvoid* *params); +typedef void (OGLFUNCCALL *glGetPolygonStipple_fp)(GLubyte *mask); +typedef const GLubyte *(OGLFUNCCALL *glGetString_fp)(GLenum name); +typedef void (OGLFUNCCALL *glGetTexEnvfv_fp)(GLenum target, GLenum pname, GLfloat *params); +typedef void (OGLFUNCCALL *glGetTexEnviv_fp)(GLenum target, GLenum pname, GLint *params); +typedef void (OGLFUNCCALL *glGetTexGendv_fp)(GLenum coord, GLenum pname, GLdouble *params); +typedef void (OGLFUNCCALL *glGetTexGenfv_fp)(GLenum coord, GLenum pname, GLfloat *params); +typedef void (OGLFUNCCALL *glGetTexGeniv_fp)(GLenum coord, GLenum pname, GLint *params); +typedef void (OGLFUNCCALL *glGetTexImage_fp)(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +typedef void (OGLFUNCCALL *glGetTexLevelParameterfv_fp)(GLenum target, GLint level, GLenum pname, GLfloat *params); +typedef void (OGLFUNCCALL *glGetTexLevelParameteriv_fp)(GLenum target, GLint level, GLenum pname, GLint *params); +typedef void (OGLFUNCCALL *glGetTexParameterfv_fp)(GLenum target, GLenum pname, GLfloat *params); +typedef void (OGLFUNCCALL *glGetTexParameteriv_fp)(GLenum target, GLenum pname, GLint *params); +typedef void (OGLFUNCCALL *glHint_fp)(GLenum target, GLenum mode); +typedef void (OGLFUNCCALL *glIndexMask_fp)(GLuint mask); +typedef void (OGLFUNCCALL *glIndexPointer_fp)(GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (OGLFUNCCALL *glIndexd_fp)(GLdouble c); +typedef void (OGLFUNCCALL *glIndexdv_fp)(const GLdouble *c); +typedef void (OGLFUNCCALL *glIndexf_fp)(GLfloat c); +typedef void (OGLFUNCCALL *glIndexfv_fp)(const GLfloat *c); +typedef void (OGLFUNCCALL *glIndexi_fp)(GLint c); +typedef void (OGLFUNCCALL *glIndexiv_fp)(const GLint *c); +typedef void (OGLFUNCCALL *glIndexs_fp)(GLshort c); +typedef void (OGLFUNCCALL *glIndexsv_fp)(const GLshort *c); +typedef void (OGLFUNCCALL *glIndexub_fp)(GLubyte c); +typedef void (OGLFUNCCALL *glIndexubv_fp)(const GLubyte *c); +typedef void (OGLFUNCCALL *glInitNames_fp)(void); +typedef void (OGLFUNCCALL *glInterleavedArrays_fp)(GLenum format, GLsizei stride, const GLvoid *pointer); +typedef GLboolean (OGLFUNCCALL *glIsEnabled_fp)(GLenum cap); +typedef GLboolean (OGLFUNCCALL *glIsList_fp)(GLuint list); +typedef GLboolean (OGLFUNCCALL *glIsTexture_fp)(GLuint texture); +typedef void (OGLFUNCCALL *glLightModelf_fp)(GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glLightModelfv_fp)(GLenum pname, const GLfloat *params); +typedef void (OGLFUNCCALL *glLightModeli_fp)(GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glLightModeliv_fp)(GLenum pname, const GLint *params); +typedef void (OGLFUNCCALL *glLightf_fp)(GLenum light, GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glLightfv_fp)(GLenum light, GLenum pname, const GLfloat *params); +typedef void (OGLFUNCCALL *glLighti_fp)(GLenum light, GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glLightiv_fp)(GLenum light, GLenum pname, const GLint *params); +typedef void (OGLFUNCCALL *glLineStipple_fp)(GLint factor, GLushort pattern); +typedef void (OGLFUNCCALL *glLineWidth_fp)(GLfloat width); +typedef void (OGLFUNCCALL *glListBase_fp)(GLuint base); +typedef void (OGLFUNCCALL *glLoadIdentity_fp)(void); +typedef void (OGLFUNCCALL *glLoadMatrixd_fp)(const GLdouble *m); +typedef void (OGLFUNCCALL *glLoadMatrixf_fp)(const GLfloat *m); +typedef void (OGLFUNCCALL *glLoadName_fp)(GLuint name); +typedef void (OGLFUNCCALL *glLogicOp_fp)(GLenum opcode); +typedef void (OGLFUNCCALL *glMap1d_fp)(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); +typedef void (OGLFUNCCALL *glMap1f_fp)(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); +typedef void (OGLFUNCCALL *glMap2d_fp)(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); +typedef void (OGLFUNCCALL *glMap2f_fp)(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); +typedef void (OGLFUNCCALL *glMapGrid1d_fp)(GLint un, GLdouble u1, GLdouble u2); +typedef void (OGLFUNCCALL *glMapGrid1f_fp)(GLint un, GLfloat u1, GLfloat u2); +typedef void (OGLFUNCCALL *glMapGrid2d_fp)(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); +typedef void (OGLFUNCCALL *glMapGrid2f_fp)(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); +typedef void (OGLFUNCCALL *glMaterialf_fp)(GLenum face, GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glMaterialfv_fp)(GLenum face, GLenum pname, const GLfloat *params); +typedef void (OGLFUNCCALL *glMateriali_fp)(GLenum face, GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glMaterialiv_fp)(GLenum face, GLenum pname, const GLint *params); +typedef void (OGLFUNCCALL *glMatrixMode_fp)(GLenum mode); +typedef void (OGLFUNCCALL *glMultMatrixd_fp)(const GLdouble *m); +typedef void (OGLFUNCCALL *glMultMatrixf_fp)(const GLfloat *m); +typedef void (OGLFUNCCALL *glNewList_fp)(GLuint list, GLenum mode); +typedef void (OGLFUNCCALL *glNormal3b_fp)(GLbyte nx, GLbyte ny, GLbyte nz); +typedef void (OGLFUNCCALL *glNormal3bv_fp)(const GLbyte *v); +typedef void (OGLFUNCCALL *glNormal3d_fp)(GLdouble nx, GLdouble ny, GLdouble nz); +typedef void (OGLFUNCCALL *glNormal3dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glNormal3f_fp)(GLfloat nx, GLfloat ny, GLfloat nz); +typedef void (OGLFUNCCALL *glNormal3fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glNormal3i_fp)(GLint nx, GLint ny, GLint nz); +typedef void (OGLFUNCCALL *glNormal3iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glNormal3s_fp)(GLshort nx, GLshort ny, GLshort nz); +typedef void (OGLFUNCCALL *glNormal3sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glNormalPointer_fp)(GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (OGLFUNCCALL *glOrtho_fp)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +typedef void (OGLFUNCCALL *glPassThrough_fp)(GLfloat token); +typedef void (OGLFUNCCALL *glPixelMapfv_fp)(GLenum map, GLsizei mapsize, const GLfloat *values); +typedef void (OGLFUNCCALL *glPixelMapuiv_fp)(GLenum map, GLsizei mapsize, const GLuint *values); +typedef void (OGLFUNCCALL *glPixelMapusv_fp)(GLenum map, GLsizei mapsize, const GLushort *values); +typedef void (OGLFUNCCALL *glPixelStoref_fp)(GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glPixelStorei_fp)(GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glPixelTransferf_fp)(GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glPixelTransferi_fp)(GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glPixelZoom_fp)(GLfloat xfactor, GLfloat yfactor); +typedef void (OGLFUNCCALL *glPointSize_fp)(GLfloat size); +typedef void (OGLFUNCCALL *glPolygonMode_fp)(GLenum face, GLenum mode); +typedef void (OGLFUNCCALL *glPolygonOffset_fp)(GLfloat factor, GLfloat units); +typedef void (OGLFUNCCALL *glPolygonStipple_fp)(const GLubyte *mask); +typedef void (OGLFUNCCALL *glPopAttrib_fp)(void); +typedef void (OGLFUNCCALL *glPopClientAttrib_fp)(void); +typedef void (OGLFUNCCALL *glPopMatrix_fp)(void); +typedef void (OGLFUNCCALL *glPopName_fp)(void); +typedef void (OGLFUNCCALL *glPrioritizeTextures_fp)(GLsizei n, const GLuint *textures, const GLclampf *priorities); +typedef void (OGLFUNCCALL *glPushAttrib_fp)(GLbitfield mask); +typedef void (OGLFUNCCALL *glPushClientAttrib_fp)(GLbitfield mask); +typedef void (OGLFUNCCALL *glPushMatrix_fp)(void); +typedef void (OGLFUNCCALL *glPushName_fp)(GLuint name); +typedef void (OGLFUNCCALL *glRasterPos2d_fp)(GLdouble x, GLdouble y); +typedef void (OGLFUNCCALL *glRasterPos2dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glRasterPos2f_fp)(GLfloat x, GLfloat y); +typedef void (OGLFUNCCALL *glRasterPos2fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glRasterPos2i_fp)(GLint x, GLint y); +typedef void (OGLFUNCCALL *glRasterPos2iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glRasterPos2s_fp)(GLshort x, GLshort y); +typedef void (OGLFUNCCALL *glRasterPos2sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glRasterPos3d_fp)(GLdouble x, GLdouble y, GLdouble z); +typedef void (OGLFUNCCALL *glRasterPos3dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glRasterPos3f_fp)(GLfloat x, GLfloat y, GLfloat z); +typedef void (OGLFUNCCALL *glRasterPos3fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glRasterPos3i_fp)(GLint x, GLint y, GLint z); +typedef void (OGLFUNCCALL *glRasterPos3iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glRasterPos3s_fp)(GLshort x, GLshort y, GLshort z); +typedef void (OGLFUNCCALL *glRasterPos3sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glRasterPos4d_fp)(GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (OGLFUNCCALL *glRasterPos4dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glRasterPos4f_fp)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (OGLFUNCCALL *glRasterPos4fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glRasterPos4i_fp)(GLint x, GLint y, GLint z, GLint w); +typedef void (OGLFUNCCALL *glRasterPos4iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glRasterPos4s_fp)(GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (OGLFUNCCALL *glRasterPos4sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glReadBuffer_fp)(GLenum mode); +typedef void (OGLFUNCCALL *glReadPixels_fp)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); +typedef void (OGLFUNCCALL *glRectd_fp)(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); +typedef void (OGLFUNCCALL *glRectdv_fp)(const GLdouble *v1, const GLdouble *v2); +typedef void (OGLFUNCCALL *glRectf_fp)(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); +typedef void (OGLFUNCCALL *glRectfv_fp)(const GLfloat *v1, const GLfloat *v2); +typedef void (OGLFUNCCALL *glRecti_fp)(GLint x1, GLint y1, GLint x2, GLint y2); +typedef void (OGLFUNCCALL *glRectiv_fp)(const GLint *v1, const GLint *v2); +typedef void (OGLFUNCCALL *glRects_fp)(GLshort x1, GLshort y1, GLshort x2, GLshort y2); +typedef void (OGLFUNCCALL *glRectsv_fp)(const GLshort *v1, const GLshort *v2); +typedef GLint (OGLFUNCCALL *glRenderMode_fp)(GLenum mode); +typedef void (OGLFUNCCALL *glRotated_fp)(GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +typedef void (OGLFUNCCALL *glRotatef_fp)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +typedef void (OGLFUNCCALL *glScaled_fp)(GLdouble x, GLdouble y, GLdouble z); +typedef void (OGLFUNCCALL *glScalef_fp)(GLfloat x, GLfloat y, GLfloat z); +typedef void (OGLFUNCCALL *glScissor_fp)(GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (OGLFUNCCALL *glSelectBuffer_fp)(GLsizei size, GLuint *buffer); +typedef void (OGLFUNCCALL *glShadeModel_fp)(GLenum mode); +typedef void (OGLFUNCCALL *glStencilFunc_fp)(GLenum func, GLint ref, GLuint mask); +typedef void (OGLFUNCCALL *glStencilMask_fp)(GLuint mask); +typedef void (OGLFUNCCALL *glStencilOp_fp)(GLenum fail, GLenum zfail, GLenum zpass); +typedef void (OGLFUNCCALL *glTexCoord1d_fp)(GLdouble s); +typedef void (OGLFUNCCALL *glTexCoord1dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glTexCoord1f_fp)(GLfloat s); +typedef void (OGLFUNCCALL *glTexCoord1fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glTexCoord1i_fp)(GLint s); +typedef void (OGLFUNCCALL *glTexCoord1iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glTexCoord1s_fp)(GLshort s); +typedef void (OGLFUNCCALL *glTexCoord1sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glTexCoord2d_fp)(GLdouble s, GLdouble t); +typedef void (OGLFUNCCALL *glTexCoord2dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glTexCoord2f_fp)(GLfloat s, GLfloat t); +typedef void (OGLFUNCCALL *glTexCoord2fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glTexCoord2i_fp)(GLint s, GLint t); +typedef void (OGLFUNCCALL *glTexCoord2iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glTexCoord2s_fp)(GLshort s, GLshort t); +typedef void (OGLFUNCCALL *glTexCoord2sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glTexCoord3d_fp)(GLdouble s, GLdouble t, GLdouble r); +typedef void (OGLFUNCCALL *glTexCoord3dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glTexCoord3f_fp)(GLfloat s, GLfloat t, GLfloat r); +typedef void (OGLFUNCCALL *glTexCoord3fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glTexCoord3i_fp)(GLint s, GLint t, GLint r); +typedef void (OGLFUNCCALL *glTexCoord3iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glTexCoord3s_fp)(GLshort s, GLshort t, GLshort r); +typedef void (OGLFUNCCALL *glTexCoord3sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glTexCoord4d_fp)(GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (OGLFUNCCALL *glTexCoord4dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glTexCoord4f_fp)(GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (OGLFUNCCALL *glTexCoord4fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glTexCoord4i_fp)(GLint s, GLint t, GLint r, GLint q); +typedef void (OGLFUNCCALL *glTexCoord4iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glTexCoord4s_fp)(GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (OGLFUNCCALL *glTexCoord4sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glTexCoordPointer_fp)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (OGLFUNCCALL *glTexEnvf_fp)(GLenum target, GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glTexEnvfv_fp)(GLenum target, GLenum pname, const GLfloat *params); +typedef void (OGLFUNCCALL *glTexEnvi_fp)(GLenum target, GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glTexEnviv_fp)(GLenum target, GLenum pname, const GLint *params); +typedef void (OGLFUNCCALL *glTexGend_fp)(GLenum coord, GLenum pname, GLdouble param); +typedef void (OGLFUNCCALL *glTexGendv_fp)(GLenum coord, GLenum pname, const GLdouble *params); +typedef void (OGLFUNCCALL *glTexGenf_fp)(GLenum coord, GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glTexGenfv_fp)(GLenum coord, GLenum pname, const GLfloat *params); +typedef void (OGLFUNCCALL *glTexGeni_fp)(GLenum coord, GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glTexGeniv_fp)(GLenum coord, GLenum pname, const GLint *params); +typedef void (OGLFUNCCALL *glTexImage1D_fp)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (OGLFUNCCALL *glTexImage2D_fp)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (OGLFUNCCALL *glTexParameterf_fp)(GLenum target, GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glTexParameterfv_fp)(GLenum target, GLenum pname, const GLfloat *params); +typedef void (OGLFUNCCALL *glTexParameteri_fp)(GLenum target, GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glTexParameteriv_fp)(GLenum target, GLenum pname, const GLint *params); +typedef void (OGLFUNCCALL *glTexSubImage1D_fp)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (OGLFUNCCALL *glTexSubImage2D_fp)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (OGLFUNCCALL *glTranslated_fp)(GLdouble x, GLdouble y, GLdouble z); +typedef void (OGLFUNCCALL *glTranslatef_fp)(GLfloat x, GLfloat y, GLfloat z); +typedef void (OGLFUNCCALL *glVertex2d_fp)(GLdouble x, GLdouble y); +typedef void (OGLFUNCCALL *glVertex2dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glVertex2f_fp)(GLfloat x, GLfloat y); +typedef void (OGLFUNCCALL *glVertex2fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glVertex2i_fp)(GLint x, GLint y); +typedef void (OGLFUNCCALL *glVertex2iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glVertex2s_fp)(GLshort x, GLshort y); +typedef void (OGLFUNCCALL *glVertex2sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glVertex3d_fp)(GLdouble x, GLdouble y, GLdouble z); +typedef void (OGLFUNCCALL *glVertex3dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glVertex3f_fp)(GLfloat x, GLfloat y, GLfloat z); +typedef void (OGLFUNCCALL *glVertex3fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glVertex3i_fp)(GLint x, GLint y, GLint z); +typedef void (OGLFUNCCALL *glVertex3iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glVertex3s_fp)(GLshort x, GLshort y, GLshort z); +typedef void (OGLFUNCCALL *glVertex3sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glVertex4d_fp)(GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (OGLFUNCCALL *glVertex4dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glVertex4f_fp)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (OGLFUNCCALL *glVertex4fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glVertex4i_fp)(GLint x, GLint y, GLint z, GLint w); +typedef void (OGLFUNCCALL *glVertex4iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glVertex4s_fp)(GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (OGLFUNCCALL *glVertex4sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glVertexPointer_fp)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (OGLFUNCCALL *glViewport_fp)(GLint x, GLint y, GLsizei width, GLsizei height); + +#ifdef WIN32 +typedef BOOL (OGLFUNCCALL *wglCopyContext_fp)(HGLRC, HGLRC, UINT); +typedef HGLRC (OGLFUNCCALL *wglCreateContext_fp)(HDC); +typedef HGLRC (OGLFUNCCALL *wglCreateLayerContext_fp)(HDC, int); +typedef BOOL (OGLFUNCCALL *wglDeleteContext_fp)(HGLRC); +typedef HGLRC (OGLFUNCCALL *wglGetCurrentContext_fp)(VOID); +typedef HDC (OGLFUNCCALL *wglGetCurrentDC_fp)(VOID); +typedef PROC (OGLFUNCCALL *wglGetProcAddress_fp)(LPCSTR); +typedef BOOL (OGLFUNCCALL *wglMakeCurrent_fp)(HDC, HGLRC); +typedef BOOL (OGLFUNCCALL *wglShareLists_fp)(HGLRC, HGLRC); +typedef BOOL (OGLFUNCCALL *wglUseFontBitmapsA_fp)(HDC, DWORD, DWORD, DWORD); +typedef BOOL (OGLFUNCCALL *wglUseFontBitmapsW_fp)(HDC, DWORD, DWORD, DWORD); +typedef BOOL (OGLFUNCCALL *wglUseFontOutlinesA_fp)(HDC, DWORD, DWORD, DWORD, FLOAT,FLOAT, int, LPGLYPHMETRICSFLOAT); +typedef BOOL (OGLFUNCCALL *wglUseFontOutlinesW_fp)(HDC, DWORD, DWORD, DWORD, FLOAT,FLOAT, int, LPGLYPHMETRICSFLOAT); +typedef BOOL (OGLFUNCCALL *wglDescribeLayerPlane_fp)(HDC, int, int, UINT,LPLAYERPLANEDESCRIPTOR); +typedef int (OGLFUNCCALL *wglSetLayerPaletteEntries_fp)(HDC, int, int, int,CONST COLORREF *); +typedef int (OGLFUNCCALL *wglGetLayerPaletteEntries_fp)(HDC, int, int, int,COLORREF *); +typedef BOOL (OGLFUNCCALL *wglRealizeLayerPalette_fp)(HDC, int, BOOL); +typedef BOOL (OGLFUNCCALL *wglSwapLayerBuffers_fp)(HDC, UINT); +#if (WINVER >= 0x0500) +typedef DWORD (OGLFUNCCALL *wglSwapMultipleBuffers_fp)(UINT, CONST WGLSWAP *); +#endif +#endif + +DEFVAR glAccum_fp dglAccum; +DEFVAR glAlphaFunc_fp dglAlphaFunc; +DEFVAR glAreTexturesResident_fp dglAreTexturesResident; +DEFVAR glArrayElement_fp dglArrayElement; +DEFVAR glBegin_fp dglBegin; +DEFVAR glBindTexture_fp dglBindTexture; +DEFVAR glBitmap_fp dglBitmap; +DEFVAR glBlendFunc_fp dglBlendFunc; +DEFVAR glCallList_fp dglCallList; +DEFVAR glCallLists_fp dglCallLists; +DEFVAR glClear_fp dglClear; +DEFVAR glClearAccum_fp dglClearAccum; +DEFVAR glClearColor_fp dglClearColor; +DEFVAR glClearDepth_fp dglClearDepth; +DEFVAR glClearIndex_fp dglClearIndex; +DEFVAR glClearStencil_fp dglClearStencil; +DEFVAR glClipPlane_fp dglClipPlane; +DEFVAR glColor3b_fp dglColor3b; +DEFVAR glColor3bv_fp dglColor3bv; +DEFVAR glColor3d_fp dglColor3d; +DEFVAR glColor3dv_fp dglColor3dv; +DEFVAR glColor3f_fp dglColor3f; +DEFVAR glColor3fv_fp dglColor3fv; +DEFVAR glColor3i_fp dglColor3i; +DEFVAR glColor3iv_fp dglColor3iv; +DEFVAR glColor3s_fp dglColor3s; +DEFVAR glColor3sv_fp dglColor3sv; +DEFVAR glColor3ub_fp dglColor3ub; +DEFVAR glColor3ubv_fp dglColor3ubv; +DEFVAR glColor3ui_fp dglColor3ui; +DEFVAR glColor3uiv_fp dglColor3uiv; +DEFVAR glColor3us_fp dglColor3us; +DEFVAR glColor3usv_fp dglColor3usv; +DEFVAR glColor4b_fp dglColor4b; +DEFVAR glColor4bv_fp dglColor4bv; +DEFVAR glColor4d_fp dglColor4d; +DEFVAR glColor4dv_fp dglColor4dv; +DEFVAR glColor4f_fp dglColor4f; +DEFVAR glColor4fv_fp dglColor4fv; +DEFVAR glColor4i_fp dglColor4i; +DEFVAR glColor4iv_fp dglColor4iv; +DEFVAR glColor4s_fp dglColor4s; +DEFVAR glColor4sv_fp dglColor4sv; +DEFVAR glColor4ub_fp dglColor4ub; +DEFVAR glColor4ubv_fp dglColor4ubv; +DEFVAR glColor4ui_fp dglColor4ui; +DEFVAR glColor4uiv_fp dglColor4uiv; +DEFVAR glColor4us_fp dglColor4us; +DEFVAR glColor4usv_fp dglColor4usv; +DEFVAR glColorMask_fp dglColorMask; +DEFVAR glColorMaterial_fp dglColorMaterial; +DEFVAR glColorPointer_fp dglColorPointer; +DEFVAR glCopyPixels_fp dglCopyPixels; +DEFVAR glCopyTexImage1D_fp dglCopyTexImage1D; +DEFVAR glCopyTexImage2D_fp dglCopyTexImage2D; +DEFVAR glCopyTexSubImage1D_fp dglCopyTexSubImage1D; +DEFVAR glCopyTexSubImage2D_fp dglCopyTexSubImage2D; +DEFVAR glCullFace_fp dglCullFace; +DEFVAR glDeleteLists_fp dglDeleteLists; +DEFVAR glDeleteTextures_fp dglDeleteTextures; +DEFVAR glDepthFunc_fp dglDepthFunc; +DEFVAR glDepthMask_fp dglDepthMask; +DEFVAR glDepthRange_fp dglDepthRange; +DEFVAR glDisable_fp dglDisable; +DEFVAR glDisableClientState_fp dglDisableClientState; +DEFVAR glDrawArrays_fp dglDrawArrays; +DEFVAR glDrawBuffer_fp dglDrawBuffer; +DEFVAR glDrawElements_fp dglDrawElements; +DEFVAR glDrawPixels_fp dglDrawPixels; +DEFVAR glEdgeFlag_fp dglEdgeFlag; +DEFVAR glEdgeFlagPointer_fp dglEdgeFlagPointer; +DEFVAR glEdgeFlagv_fp dglEdgeFlagv; +DEFVAR glEnable_fp dglEnable; +DEFVAR glEnableClientState_fp dglEnableClientState; +DEFVAR glEnd_fp dglEnd; +DEFVAR glEndList_fp dglEndList; +DEFVAR glEvalCoord1d_fp dglEvalCoord1d; +DEFVAR glEvalCoord1dv_fp dglEvalCoord1dv; +DEFVAR glEvalCoord1f_fp dglEvalCoord1f; +DEFVAR glEvalCoord1fv_fp dglEvalCoord1fv; +DEFVAR glEvalCoord2d_fp dglEvalCoord2d; +DEFVAR glEvalCoord2dv_fp dglEvalCoord2dv; +DEFVAR glEvalCoord2f_fp dglEvalCoord2f; +DEFVAR glEvalCoord2fv_fp dglEvalCoord2fv; +DEFVAR glEvalMesh1_fp dglEvalMesh1; +DEFVAR glEvalMesh2_fp dglEvalMesh2; +DEFVAR glEvalPoint1_fp dglEvalPoint1; +DEFVAR glEvalPoint2_fp dglEvalPoint2; +DEFVAR glFeedbackBuffer_fp dglFeedbackBuffer; +DEFVAR glFinish_fp dglFinish; +DEFVAR glFlush_fp dglFlush; +DEFVAR glFogf_fp dglFogf; +DEFVAR glFogfv_fp dglFogfv; +DEFVAR glFogi_fp dglFogi; +DEFVAR glFogiv_fp dglFogiv; +DEFVAR glFrontFace_fp dglFrontFace; +DEFVAR glFrustum_fp dglFrustum; +DEFVAR glGenLists_fp dglGenLists; +DEFVAR glGenTextures_fp dglGenTextures; +DEFVAR glGetBooleanv_fp dglGetBooleanv; +DEFVAR glGetClipPlane_fp dglGetClipPlane; +DEFVAR glGetDoublev_fp dglGetDoublev; +DEFVAR glGetError_fp dglGetError; +DEFVAR glGetFloatv_fp dglGetFloatv; +DEFVAR glGetIntegerv_fp dglGetIntegerv; +DEFVAR glGetLightfv_fp dglGetLightfv; +DEFVAR glGetLightiv_fp dglGetLightiv; +DEFVAR glGetMapdv_fp dglGetMapdv; +DEFVAR glGetMapfv_fp dglGetMapfv; +DEFVAR glGetMapiv_fp dglGetMapiv; +DEFVAR glGetMaterialfv_fp dglGetMaterialfv; +DEFVAR glGetMaterialiv_fp dglGetMaterialiv; +DEFVAR glGetPixelMapfv_fp dglGetPixelMapfv; +DEFVAR glGetPixelMapuiv_fp dglGetPixelMapuiv; +DEFVAR glGetPixelMapusv_fp dglGetPixelMapusv; +DEFVAR glGetPointerv_fp dglGetPointerv; +DEFVAR glGetPolygonStipple_fp dglGetPolygonStipple; +DEFVAR glGetString_fp dglGetString; +DEFVAR glGetTexEnvfv_fp dglGetTexEnvfv; +DEFVAR glGetTexEnviv_fp dglGetTexEnviv; +DEFVAR glGetTexGendv_fp dglGetTexGendv; +DEFVAR glGetTexGenfv_fp dglGetTexGenfv; +DEFVAR glGetTexGeniv_fp dglGetTexGeniv; +DEFVAR glGetTexImage_fp dglGetTexImage; +DEFVAR glGetTexLevelParameterfv_fp dglGetTexLevelParameterfv; +DEFVAR glGetTexLevelParameteriv_fp dglGetTexLevelParameteriv; +DEFVAR glGetTexParameterfv_fp dglGetTexParameterfv; +DEFVAR glGetTexParameteriv_fp dglGetTexParameteriv; +DEFVAR glHint_fp dglHint; +DEFVAR glIndexMask_fp dglIndexMask; +DEFVAR glIndexPointer_fp dglIndexPointer; +DEFVAR glIndexd_fp dglIndexd; +DEFVAR glIndexdv_fp dglIndexdv; +DEFVAR glIndexf_fp dglIndexf; +DEFVAR glIndexfv_fp dglIndexfv; +DEFVAR glIndexi_fp dglIndexi; +DEFVAR glIndexiv_fp dglIndexiv; +DEFVAR glIndexs_fp dglIndexs; +DEFVAR glIndexsv_fp dglIndexsv; +DEFVAR glIndexub_fp dglIndexub; +DEFVAR glIndexubv_fp dglIndexubv; +DEFVAR glInitNames_fp dglInitNames; +DEFVAR glInterleavedArrays_fp dglInterleavedArrays; +DEFVAR glIsEnabled_fp dglIsEnabled; +DEFVAR glIsList_fp dglIsList; +DEFVAR glIsTexture_fp dglIsTexture; +DEFVAR glLightModelf_fp dglLightModelf; +DEFVAR glLightModelfv_fp dglLightModelfv; +DEFVAR glLightModeli_fp dglLightModeli; +DEFVAR glLightModeliv_fp dglLightModeliv; +DEFVAR glLightf_fp dglLightf; +DEFVAR glLightfv_fp dglLightfv; +DEFVAR glLighti_fp dglLighti; +DEFVAR glLightiv_fp dglLightiv; +DEFVAR glLineStipple_fp dglLineStipple; +DEFVAR glLineWidth_fp dglLineWidth; +DEFVAR glListBase_fp dglListBase; +DEFVAR glLoadIdentity_fp dglLoadIdentity; +DEFVAR glLoadMatrixd_fp dglLoadMatrixd; +DEFVAR glLoadMatrixf_fp dglLoadMatrixf; +DEFVAR glLoadName_fp dglLoadName; +DEFVAR glLogicOp_fp dglLogicOp; +DEFVAR glMap1d_fp dglMap1d; +DEFVAR glMap1f_fp dglMap1f; +DEFVAR glMap2d_fp dglMap2d; +DEFVAR glMap2f_fp dglMap2f; +DEFVAR glMapGrid1d_fp dglMapGrid1d; +DEFVAR glMapGrid1f_fp dglMapGrid1f; +DEFVAR glMapGrid2d_fp dglMapGrid2d; +DEFVAR glMapGrid2f_fp dglMapGrid2f; +DEFVAR glMaterialf_fp dglMaterialf; +DEFVAR glMaterialfv_fp dglMaterialfv; +DEFVAR glMateriali_fp dglMateriali; +DEFVAR glMaterialiv_fp dglMaterialiv; +DEFVAR glMatrixMode_fp dglMatrixMode; +DEFVAR glMultMatrixd_fp dglMultMatrixd; +DEFVAR glMultMatrixf_fp dglMultMatrixf; +DEFVAR glNewList_fp dglNewList; +DEFVAR glNormal3b_fp dglNormal3b; +DEFVAR glNormal3bv_fp dglNormal3bv; +DEFVAR glNormal3d_fp dglNormal3d; +DEFVAR glNormal3dv_fp dglNormal3dv; +DEFVAR glNormal3f_fp dglNormal3f; +DEFVAR glNormal3fv_fp dglNormal3fv; +DEFVAR glNormal3i_fp dglNormal3i; +DEFVAR glNormal3iv_fp dglNormal3iv; +DEFVAR glNormal3s_fp dglNormal3s; +DEFVAR glNormal3sv_fp dglNormal3sv; +DEFVAR glNormalPointer_fp dglNormalPointer; +DEFVAR glOrtho_fp dglOrtho; +DEFVAR glPassThrough_fp dglPassThrough; +DEFVAR glPixelMapfv_fp dglPixelMapfv; +DEFVAR glPixelMapuiv_fp dglPixelMapuiv; +DEFVAR glPixelMapusv_fp dglPixelMapusv; +DEFVAR glPixelStoref_fp dglPixelStoref; +DEFVAR glPixelStorei_fp dglPixelStorei; +DEFVAR glPixelTransferf_fp dglPixelTransferf; +DEFVAR glPixelTransferi_fp dglPixelTransferi; +DEFVAR glPixelZoom_fp dglPixelZoom; +DEFVAR glPointSize_fp dglPointSize; +DEFVAR glPolygonMode_fp dglPolygonMode; +DEFVAR glPolygonOffset_fp dglPolygonOffset; +DEFVAR glPolygonStipple_fp dglPolygonStipple; +DEFVAR glPopAttrib_fp dglPopAttrib; +DEFVAR glPopClientAttrib_fp dglPopClientAttrib; +DEFVAR glPopMatrix_fp dglPopMatrix; +DEFVAR glPopName_fp dglPopName; +DEFVAR glPrioritizeTextures_fp dglPrioritizeTextures; +DEFVAR glPushAttrib_fp dglPushAttrib; +DEFVAR glPushClientAttrib_fp dglPushClientAttrib; +DEFVAR glPushMatrix_fp dglPushMatrix; +DEFVAR glPushName_fp dglPushName; +DEFVAR glRasterPos2d_fp dglRasterPos2d; +DEFVAR glRasterPos2dv_fp dglRasterPos2dv; +DEFVAR glRasterPos2f_fp dglRasterPos2f; +DEFVAR glRasterPos2fv_fp dglRasterPos2fv; +DEFVAR glRasterPos2i_fp dglRasterPos2i; +DEFVAR glRasterPos2iv_fp dglRasterPos2iv; +DEFVAR glRasterPos2s_fp dglRasterPos2s; +DEFVAR glRasterPos2sv_fp dglRasterPos2sv; +DEFVAR glRasterPos3d_fp dglRasterPos3d; +DEFVAR glRasterPos3dv_fp dglRasterPos3dv; +DEFVAR glRasterPos3f_fp dglRasterPos3f; +DEFVAR glRasterPos3fv_fp dglRasterPos3fv; +DEFVAR glRasterPos3i_fp dglRasterPos3i; +DEFVAR glRasterPos3iv_fp dglRasterPos3iv; +DEFVAR glRasterPos3s_fp dglRasterPos3s; +DEFVAR glRasterPos3sv_fp dglRasterPos3sv; +DEFVAR glRasterPos4d_fp dglRasterPos4d; +DEFVAR glRasterPos4dv_fp dglRasterPos4dv; +DEFVAR glRasterPos4f_fp dglRasterPos4f; +DEFVAR glRasterPos4fv_fp dglRasterPos4fv; +DEFVAR glRasterPos4i_fp dglRasterPos4i; +DEFVAR glRasterPos4iv_fp dglRasterPos4iv; +DEFVAR glRasterPos4s_fp dglRasterPos4s; +DEFVAR glRasterPos4sv_fp dglRasterPos4sv; +DEFVAR glReadBuffer_fp dglReadBuffer; +DEFVAR glReadPixels_fp dglReadPixels; +DEFVAR glRectd_fp dglRectd; +DEFVAR glRectdv_fp dglRectdv; +DEFVAR glRectf_fp dglRectf; +DEFVAR glRectfv_fp dglRectfv; +DEFVAR glRecti_fp dglRecti; +DEFVAR glRectiv_fp dglRectiv; +DEFVAR glRects_fp dglRects; +DEFVAR glRectsv_fp dglRectsv; +DEFVAR glRenderMode_fp dglRenderMode; +DEFVAR glRotated_fp dglRotated; +DEFVAR glRotatef_fp dglRotatef; +DEFVAR glScaled_fp dglScaled; +DEFVAR glScalef_fp dglScalef; +DEFVAR glScissor_fp dglScissor; +DEFVAR glSelectBuffer_fp dglSelectBuffer; +DEFVAR glShadeModel_fp dglShadeModel; +DEFVAR glStencilFunc_fp dglStencilFunc; +DEFVAR glStencilMask_fp dglStencilMask; +DEFVAR glStencilOp_fp dglStencilOp; +DEFVAR glTexCoord1d_fp dglTexCoord1d; +DEFVAR glTexCoord1dv_fp dglTexCoord1dv; +DEFVAR glTexCoord1f_fp dglTexCoord1f; +DEFVAR glTexCoord1fv_fp dglTexCoord1fv; +DEFVAR glTexCoord1i_fp dglTexCoord1i; +DEFVAR glTexCoord1iv_fp dglTexCoord1iv; +DEFVAR glTexCoord1s_fp dglTexCoord1s; +DEFVAR glTexCoord1sv_fp dglTexCoord1sv; +DEFVAR glTexCoord2d_fp dglTexCoord2d; +DEFVAR glTexCoord2dv_fp dglTexCoord2dv; +DEFVAR glTexCoord2f_fp dglTexCoord2f; +DEFVAR glTexCoord2fv_fp dglTexCoord2fv; +DEFVAR glTexCoord2i_fp dglTexCoord2i; +DEFVAR glTexCoord2iv_fp dglTexCoord2iv; +DEFVAR glTexCoord2s_fp dglTexCoord2s; +DEFVAR glTexCoord2sv_fp dglTexCoord2sv; +DEFVAR glTexCoord3d_fp dglTexCoord3d; +DEFVAR glTexCoord3dv_fp dglTexCoord3dv; +DEFVAR glTexCoord3f_fp dglTexCoord3f; +DEFVAR glTexCoord3fv_fp dglTexCoord3fv; +DEFVAR glTexCoord3i_fp dglTexCoord3i; +DEFVAR glTexCoord3iv_fp dglTexCoord3iv; +DEFVAR glTexCoord3s_fp dglTexCoord3s; +DEFVAR glTexCoord3sv_fp dglTexCoord3sv; +DEFVAR glTexCoord4d_fp dglTexCoord4d; +DEFVAR glTexCoord4dv_fp dglTexCoord4dv; +DEFVAR glTexCoord4f_fp dglTexCoord4f; +DEFVAR glTexCoord4fv_fp dglTexCoord4fv; +DEFVAR glTexCoord4i_fp dglTexCoord4i; +DEFVAR glTexCoord4iv_fp dglTexCoord4iv; +DEFVAR glTexCoord4s_fp dglTexCoord4s; +DEFVAR glTexCoord4sv_fp dglTexCoord4sv; +DEFVAR glTexCoordPointer_fp dglTexCoordPointer; +DEFVAR glTexEnvf_fp dglTexEnvf; +DEFVAR glTexEnvfv_fp dglTexEnvfv; +DEFVAR glTexEnvi_fp dglTexEnvi; +DEFVAR glTexEnviv_fp dglTexEnviv; +DEFVAR glTexGend_fp dglTexGend; +DEFVAR glTexGendv_fp dglTexGendv; +DEFVAR glTexGenf_fp dglTexGenf; +DEFVAR glTexGenfv_fp dglTexGenfv; +DEFVAR glTexGeni_fp dglTexGeni; +DEFVAR glTexGeniv_fp dglTexGeniv; +DEFVAR glTexImage1D_fp dglTexImage1D; +DEFVAR glTexImage2D_fp dglTexImage2D; +DEFVAR glTexParameterf_fp dglTexParameterf; +DEFVAR glTexParameterfv_fp dglTexParameterfv; +DEFVAR glTexParameteri_fp dglTexParameteri; +DEFVAR glTexParameteriv_fp dglTexParameteriv; +DEFVAR glTexSubImage1D_fp dglTexSubImage1D; +DEFVAR glTexSubImage2D_fp dglTexSubImage2D; +DEFVAR glTranslated_fp dglTranslated; +DEFVAR glTranslatef_fp dglTranslatef; +DEFVAR glVertex2d_fp dglVertex2d; +DEFVAR glVertex2dv_fp dglVertex2dv; +DEFVAR glVertex2f_fp dglVertex2f; +DEFVAR glVertex2fv_fp dglVertex2fv; +DEFVAR glVertex2i_fp dglVertex2i; +DEFVAR glVertex2iv_fp dglVertex2iv; +DEFVAR glVertex2s_fp dglVertex2s; +DEFVAR glVertex2sv_fp dglVertex2sv; +DEFVAR glVertex3d_fp dglVertex3d; +DEFVAR glVertex3dv_fp dglVertex3dv; +DEFVAR glVertex3f_fp dglVertex3f; +DEFVAR glVertex3fv_fp dglVertex3fv; +DEFVAR glVertex3i_fp dglVertex3i; +DEFVAR glVertex3iv_fp dglVertex3iv; +DEFVAR glVertex3s_fp dglVertex3s; +DEFVAR glVertex3sv_fp dglVertex3sv; +DEFVAR glVertex4d_fp dglVertex4d; +DEFVAR glVertex4dv_fp dglVertex4dv; +DEFVAR glVertex4f_fp dglVertex4f; +DEFVAR glVertex4fv_fp dglVertex4fv; +DEFVAR glVertex4i_fp dglVertex4i; +DEFVAR glVertex4iv_fp dglVertex4iv; +DEFVAR glVertex4s_fp dglVertex4s; +DEFVAR glVertex4sv_fp dglVertex4sv; +DEFVAR glVertexPointer_fp dglVertexPointer; +DEFVAR glViewport_fp dglViewport; + +#ifdef WIN32 +DEFVAR wglCopyContext_fp dwglCopyContext; +DEFVAR wglCreateContext_fp dwglCreateContext; +DEFVAR wglCreateLayerContext_fp dwglCreateLayerContext; +DEFVAR wglDeleteContext_fp dwglDeleteContext; +DEFVAR wglGetCurrentContext_fp dwglGetCurrentContext; +DEFVAR wglGetCurrentDC_fp dwglGetCurrentDC; +DEFVAR wglGetProcAddress_fp dwglGetProcAddress; +DEFVAR wglMakeCurrent_fp dwglMakeCurrent; +DEFVAR wglShareLists_fp dwglShareLists; +DEFVAR wglUseFontBitmapsA_fp dwglUseFontBitmapsA; +DEFVAR wglUseFontBitmapsW_fp dwglUseFontBitmapsW; +DEFVAR wglUseFontOutlinesA_fp dwglUseFontOutlinesA; +DEFVAR wglUseFontOutlinesW_fp dwglUseFontOutlinesW; +DEFVAR wglDescribeLayerPlane_fp dwglDescribeLayerPlane; +DEFVAR wglSetLayerPaletteEntries_fp dwglSetLayerPaletteEntries; +DEFVAR wglGetLayerPaletteEntries_fp dwglGetLayerPaletteEntries; +DEFVAR wglRealizeLayerPalette_fp dwglRealizeLayerPalette; +DEFVAR wglSwapLayerBuffers_fp dwglSwapLayerBuffers; +#if (WINVER >= 0x0500) +DEFVAR wglSwapMultipleBuffers_fp dwglSwapMultipleBuffers; +#endif +#endif + +#ifdef DECLARE_VARS + +// Dynamic module load functions +#ifdef WIN32 +void *dll_LoadModule(const char *name) +{ + HINSTANCE handle; + handle = LoadLibrary(name); + return (void *)handle; +} +void dll_UnloadModule(void *hdl) +{ + HINSTANCE handle; + handle = (HINSTANCE)hdl; + + if(hdl) + { + FreeLibrary(handle); + } +} +void *dll_GetSymbol(void *dllhandle,const char *symname) +{ + if(!dllhandle) + return NULL; + return (void *)GetProcAddress((HINSTANCE)dllhandle,symname); +} +#endif +#ifdef __LINUX__ +#include +void *dll_LoadModule(const char *name) +{ + return (void *)dlopen(name,RTLD_NOW|RTLD_GLOBAL); +} +void dll_UnloadModule(void *hdl) +{ + if(hdl) + { + dlclose(hdl); + } +} +void *dll_GetSymbol(void *dllhandle,const char *symname) +{ + if(!dllhandle) + return NULL; + return dlsym(dllhandle,symname); +} +#endif + +#endif //DECLARE_VARS + +void OpenGL_SetFuncsToNull(void); + +extern char *OglLibPath; + +#ifndef DECLARE_VARS +// pass true to load the library +// pass false to unload it +bool OpenGL_LoadLibrary(bool load);//load=true removed because not c++ +#else +void *OpenGLModuleHandle=NULL; +//char *OglLibPath="opengl32.dll"; +bool OpenGL_LoadLibrary(bool load) +{ + if(load && OpenGLModuleHandle) + return true; + + OpenGL_SetFuncsToNull(); + + if(!load) + { + if(OpenGLModuleHandle) + { + dll_UnloadModule(OpenGLModuleHandle); + OpenGLModuleHandle = NULL; + } + return true; + }else + { + OpenGLModuleHandle = dll_LoadModule(OglLibPath); + if(!OpenGLModuleHandle) + return false; + + dglAccum = (glAccum_fp)dll_GetSymbol(OpenGLModuleHandle,"glAccum"); + dglAlphaFunc = (glAlphaFunc_fp)dll_GetSymbol(OpenGLModuleHandle,"glAlphaFunc"); + dglAreTexturesResident = (glAreTexturesResident_fp)dll_GetSymbol(OpenGLModuleHandle,"glAreTexturesResident"); + dglArrayElement = (glArrayElement_fp)dll_GetSymbol(OpenGLModuleHandle,"glArrayElement"); + dglBegin = (glBegin_fp)dll_GetSymbol(OpenGLModuleHandle,"glBegin"); + dglBindTexture = (glBindTexture_fp)dll_GetSymbol(OpenGLModuleHandle,"glBindTexture"); + dglBitmap = (glBitmap_fp)dll_GetSymbol(OpenGLModuleHandle,"glBitmap"); + dglBlendFunc = (glBlendFunc_fp)dll_GetSymbol(OpenGLModuleHandle,"glBlendFunc"); + dglCallList = (glCallList_fp)dll_GetSymbol(OpenGLModuleHandle,"glCallList"); + dglCallLists = (glCallLists_fp)dll_GetSymbol(OpenGLModuleHandle,"glCallLists"); + dglClear = (glClear_fp)dll_GetSymbol(OpenGLModuleHandle,"glClear"); + dglClearAccum = (glClearAccum_fp)dll_GetSymbol(OpenGLModuleHandle,"glClearAccum"); + dglClearColor = (glClearColor_fp)dll_GetSymbol(OpenGLModuleHandle,"glClearColor"); + dglClearDepth = (glClearDepth_fp)dll_GetSymbol(OpenGLModuleHandle,"glClearDepth"); + dglClearIndex = (glClearIndex_fp)dll_GetSymbol(OpenGLModuleHandle,"glClearIndex"); + dglClearStencil = (glClearStencil_fp)dll_GetSymbol(OpenGLModuleHandle,"glClearStencil"); + dglClipPlane = (glClipPlane_fp)dll_GetSymbol(OpenGLModuleHandle,"glClipPlane"); + dglColor3b = (glColor3b_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3b"); + dglColor3bv = (glColor3bv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3bv"); + dglColor3d = (glColor3d_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3d"); + dglColor3dv = (glColor3dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3dv"); + dglColor3f = (glColor3f_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3f"); + dglColor3fv = (glColor3fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3fv"); + dglColor3i = (glColor3i_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3i"); + dglColor3iv = (glColor3iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3iv"); + dglColor3s = (glColor3s_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3s"); + dglColor3sv = (glColor3sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3sv"); + dglColor3ub = (glColor3ub_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3ub"); + dglColor3ubv = (glColor3ubv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3ubv"); + dglColor3ui = (glColor3ui_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3ui"); + dglColor3uiv = (glColor3uiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3uiv"); + dglColor3us = (glColor3us_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3us"); + dglColor3usv = (glColor3usv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3usv"); + dglColor4b = (glColor4b_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4b"); + dglColor4bv = (glColor4bv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4bv"); + dglColor4d = (glColor4d_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4d"); + dglColor4dv = (glColor4dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4dv"); + dglColor4f = (glColor4f_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4f"); + dglColor4fv = (glColor4fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4fv"); + dglColor4i = (glColor4i_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4i"); + dglColor4iv = (glColor4iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4iv"); + dglColor4s = (glColor4s_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4s"); + dglColor4sv = (glColor4sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4sv"); + dglColor4ub = (glColor4ub_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4ub"); + dglColor4ubv = (glColor4ubv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4ubv"); + dglColor4ui = (glColor4ui_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4ui"); + dglColor4uiv = (glColor4uiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4uiv"); + dglColor4us = (glColor4us_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4us"); + dglColor4usv = (glColor4usv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4usv"); + dglColorMask = (glColorMask_fp)dll_GetSymbol(OpenGLModuleHandle,"glColorMask"); + dglColorMaterial = (glColorMaterial_fp)dll_GetSymbol(OpenGLModuleHandle,"glColorMaterial"); + dglColorPointer = (glColorPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glColorPointer"); + dglCopyPixels = (glCopyPixels_fp)dll_GetSymbol(OpenGLModuleHandle,"glCopyPixels"); + dglCopyTexImage1D = (glCopyTexImage1D_fp)dll_GetSymbol(OpenGLModuleHandle,"glCopyTexImage1D"); + dglCopyTexImage2D = (glCopyTexImage2D_fp)dll_GetSymbol(OpenGLModuleHandle,"glCopyTexImage2D"); + dglCopyTexSubImage1D = (glCopyTexSubImage1D_fp)dll_GetSymbol(OpenGLModuleHandle,"glCopyTexSubImage1D"); + dglCopyTexSubImage2D = (glCopyTexSubImage2D_fp)dll_GetSymbol(OpenGLModuleHandle,"glCopyTexSubImage2D"); + dglCullFace = (glCullFace_fp)dll_GetSymbol(OpenGLModuleHandle,"glCullFace"); + dglDeleteLists = (glDeleteLists_fp)dll_GetSymbol(OpenGLModuleHandle,"glDeleteLists"); + dglDeleteTextures = (glDeleteTextures_fp)dll_GetSymbol(OpenGLModuleHandle,"glDeleteTextures"); + dglDepthFunc = (glDepthFunc_fp)dll_GetSymbol(OpenGLModuleHandle,"glDepthFunc"); + dglDepthMask = (glDepthMask_fp)dll_GetSymbol(OpenGLModuleHandle,"glDepthMask"); + dglDepthRange = (glDepthRange_fp)dll_GetSymbol(OpenGLModuleHandle,"glDepthRange"); + dglDisable = (glDisable_fp)dll_GetSymbol(OpenGLModuleHandle,"glDisable"); + dglDisableClientState = (glDisableClientState_fp)dll_GetSymbol(OpenGLModuleHandle,"glDisableClientState"); + dglDrawArrays = (glDrawArrays_fp)dll_GetSymbol(OpenGLModuleHandle,"glDrawArrays"); + dglDrawBuffer = (glDrawBuffer_fp)dll_GetSymbol(OpenGLModuleHandle,"glDrawBuffer"); + dglDrawElements = (glDrawElements_fp)dll_GetSymbol(OpenGLModuleHandle,"glDrawElements"); + dglDrawPixels = (glDrawPixels_fp)dll_GetSymbol(OpenGLModuleHandle,"glDrawPixels"); + dglEdgeFlag = (glEdgeFlag_fp)dll_GetSymbol(OpenGLModuleHandle,"glEdgeFlag"); + dglEdgeFlagPointer = (glEdgeFlagPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glEdgeFlagPointer"); + dglEdgeFlagv = (glEdgeFlagv_fp)dll_GetSymbol(OpenGLModuleHandle,"glEdgeFlagv"); + dglEnable = (glEnable_fp)dll_GetSymbol(OpenGLModuleHandle,"glEnable"); + dglEnableClientState = (glEnableClientState_fp)dll_GetSymbol(OpenGLModuleHandle,"glEnableClientState"); + dglEnd = (glEnd_fp)dll_GetSymbol(OpenGLModuleHandle,"glEnd"); + dglEndList = (glEndList_fp)dll_GetSymbol(OpenGLModuleHandle,"glEndList"); + dglEvalCoord1d = (glEvalCoord1d_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord1d"); + dglEvalCoord1dv = (glEvalCoord1dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord1dv"); + dglEvalCoord1f = (glEvalCoord1f_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord1f"); + dglEvalCoord1fv = (glEvalCoord1fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord1fv"); + dglEvalCoord2d = (glEvalCoord2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord2d"); + dglEvalCoord2dv = (glEvalCoord2dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord2dv"); + dglEvalCoord2f = (glEvalCoord2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord2f"); + dglEvalCoord2fv = (glEvalCoord2fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord2fv"); + dglEvalMesh1 = (glEvalMesh1_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalMesh1"); + dglEvalMesh2 = (glEvalMesh2_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalMesh2"); + dglEvalPoint1 = (glEvalPoint1_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalPoint1"); + dglEvalPoint2 = (glEvalPoint2_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalPoint2"); + dglFeedbackBuffer = (glFeedbackBuffer_fp)dll_GetSymbol(OpenGLModuleHandle,"glFeedbackBuffer"); + dglFinish = (glFinish_fp)dll_GetSymbol(OpenGLModuleHandle,"glFinish"); + dglFlush = (glFlush_fp)dll_GetSymbol(OpenGLModuleHandle,"glFlush"); + dglFogf = (glFogf_fp)dll_GetSymbol(OpenGLModuleHandle,"glFogf"); + dglFogfv = (glFogfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glFogfv"); + dglFogi = (glFogi_fp)dll_GetSymbol(OpenGLModuleHandle,"glFogi"); + dglFogiv = (glFogiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glFogiv"); + dglFrontFace = (glFrontFace_fp)dll_GetSymbol(OpenGLModuleHandle,"glFrontFace"); + dglFrustum = (glFrustum_fp)dll_GetSymbol(OpenGLModuleHandle,"glFrustum"); + dglGenLists = (glGenLists_fp)dll_GetSymbol(OpenGLModuleHandle,"glGenLists"); + dglGenTextures = (glGenTextures_fp)dll_GetSymbol(OpenGLModuleHandle,"glGenTextures"); + dglGetBooleanv = (glGetBooleanv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetBooleanv"); + dglGetClipPlane = (glGetClipPlane_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetClipPlane"); + dglGetDoublev = (glGetDoublev_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetDoublev"); + dglGetError = (glGetError_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetError"); + dglGetFloatv = (glGetFloatv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetFloatv"); + dglGetIntegerv = (glGetIntegerv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetIntegerv"); + dglGetLightfv = (glGetLightfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetLightfv"); + dglGetLightiv = (glGetLightiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetLightiv"); + dglGetMapdv = (glGetMapdv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetMapdv"); + dglGetMapfv = (glGetMapfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetMapfv"); + dglGetMapiv = (glGetMapiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetMapiv"); + dglGetMaterialfv = (glGetMaterialfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetMaterialfv"); + dglGetMaterialiv = (glGetMaterialiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetMaterialiv"); + dglGetPixelMapfv = (glGetPixelMapfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetPixelMapfv"); + dglGetPixelMapuiv = (glGetPixelMapuiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetPixelMapuiv"); + dglGetPixelMapusv = (glGetPixelMapusv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetPixelMapusv"); + dglGetPointerv = (glGetPointerv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetPointerv"); + dglGetPolygonStipple = (glGetPolygonStipple_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetPolygonStipple"); + dglGetString = (glGetString_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetString"); + dglGetTexEnvfv = (glGetTexEnvfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexEnvfv"); + dglGetTexEnviv = (glGetTexEnviv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexEnviv"); + dglGetTexGendv = (glGetTexGendv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexGendv"); + dglGetTexGenfv = (glGetTexGenfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexGenfv"); + dglGetTexGeniv = (glGetTexGeniv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexGeniv"); + dglGetTexImage = (glGetTexImage_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexImage"); + dglGetTexLevelParameterfv = (glGetTexLevelParameterfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexLevelParameterfv"); + dglGetTexLevelParameteriv = (glGetTexLevelParameteriv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexLevelParameteriv"); + dglGetTexParameterfv = (glGetTexParameterfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexParameterfv"); + dglGetTexParameteriv = (glGetTexParameteriv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexParameteriv"); + dglHint = (glHint_fp)dll_GetSymbol(OpenGLModuleHandle,"glHint"); + dglIndexMask = (glIndexMask_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexMask"); + dglIndexPointer = (glIndexPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexPointer"); + dglIndexd = (glIndexd_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexd"); + dglIndexdv = (glIndexdv_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexdv"); + dglIndexf = (glIndexf_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexf"); + dglIndexfv = (glIndexfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexfv"); + dglIndexi = (glIndexi_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexi"); + dglIndexiv = (glIndexiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexiv"); + dglIndexs = (glIndexs_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexs"); + dglIndexsv = (glIndexsv_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexsv"); + dglIndexub = (glIndexub_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexub"); + dglIndexubv = (glIndexubv_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexubv"); + dglInitNames = (glInitNames_fp)dll_GetSymbol(OpenGLModuleHandle,"glInitNames"); + dglInterleavedArrays = (glInterleavedArrays_fp)dll_GetSymbol(OpenGLModuleHandle,"glInterleavedArrays"); + dglIsEnabled = (glIsEnabled_fp)dll_GetSymbol(OpenGLModuleHandle,"glIsEnabled"); + dglIsList = (glIsList_fp)dll_GetSymbol(OpenGLModuleHandle,"glIsList"); + dglIsTexture = (glIsTexture_fp)dll_GetSymbol(OpenGLModuleHandle,"glIsTexture"); + dglLightModelf = (glLightModelf_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightModelf"); + dglLightModelfv = (glLightModelfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightModelfv"); + dglLightModeli = (glLightModeli_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightModeli"); + dglLightModeliv = (glLightModeliv_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightModeliv"); + dglLightf = (glLightf_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightf"); + dglLightfv = (glLightfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightfv"); + dglLighti = (glLighti_fp)dll_GetSymbol(OpenGLModuleHandle,"glLighti"); + dglLightiv = (glLightiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightiv"); + dglLineStipple = (glLineStipple_fp)dll_GetSymbol(OpenGLModuleHandle,"glLineStipple"); + dglLineWidth = (glLineWidth_fp)dll_GetSymbol(OpenGLModuleHandle,"glLineWidth"); + dglListBase = (glListBase_fp)dll_GetSymbol(OpenGLModuleHandle,"glListBase"); + dglLoadIdentity = (glLoadIdentity_fp)dll_GetSymbol(OpenGLModuleHandle,"glLoadIdentity"); + dglLoadMatrixd = (glLoadMatrixd_fp)dll_GetSymbol(OpenGLModuleHandle,"glLoadMatrixd"); + dglLoadMatrixf = (glLoadMatrixf_fp)dll_GetSymbol(OpenGLModuleHandle,"glLoadMatrixf"); + dglLoadName = (glLoadName_fp)dll_GetSymbol(OpenGLModuleHandle,"glLoadName"); + dglLogicOp = (glLogicOp_fp)dll_GetSymbol(OpenGLModuleHandle,"glLogicOp"); + dglMap1d = (glMap1d_fp)dll_GetSymbol(OpenGLModuleHandle,"glMap1d"); + dglMap1f = (glMap1f_fp)dll_GetSymbol(OpenGLModuleHandle,"glMap1f"); + dglMap2d = (glMap2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glMap2d"); + dglMap2f = (glMap2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glMap2f"); + dglMapGrid1d = (glMapGrid1d_fp)dll_GetSymbol(OpenGLModuleHandle,"glMapGrid1d"); + dglMapGrid1f = (glMapGrid1f_fp)dll_GetSymbol(OpenGLModuleHandle,"glMapGrid1f"); + dglMapGrid2d = (glMapGrid2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glMapGrid2d"); + dglMapGrid2f = (glMapGrid2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glMapGrid2f"); + dglMaterialf = (glMaterialf_fp)dll_GetSymbol(OpenGLModuleHandle,"glMaterialf"); + dglMaterialfv = (glMaterialfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glMaterialfv"); + dglMateriali = (glMateriali_fp)dll_GetSymbol(OpenGLModuleHandle,"glMateriali"); + dglMaterialiv = (glMaterialiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glMaterialiv"); + dglMatrixMode = (glMatrixMode_fp)dll_GetSymbol(OpenGLModuleHandle,"glMatrixMode"); + dglMultMatrixd = (glMultMatrixd_fp)dll_GetSymbol(OpenGLModuleHandle,"glMultMatrixd"); + dglMultMatrixf = (glMultMatrixf_fp)dll_GetSymbol(OpenGLModuleHandle,"glMultMatrixf"); + dglNewList = (glNewList_fp)dll_GetSymbol(OpenGLModuleHandle,"glNewList"); + dglNormal3b = (glNormal3b_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3b"); + dglNormal3bv = (glNormal3bv_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3bv"); + dglNormal3d = (glNormal3d_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3d"); + dglNormal3dv = (glNormal3dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3dv"); + dglNormal3f = (glNormal3f_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3f"); + dglNormal3fv = (glNormal3fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3fv"); + dglNormal3i = (glNormal3i_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3i"); + dglNormal3iv = (glNormal3iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3iv"); + dglNormal3s = (glNormal3s_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3s"); + dglNormal3sv = (glNormal3sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3sv"); + dglNormalPointer = (glNormalPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormalPointer"); + dglOrtho = (glOrtho_fp)dll_GetSymbol(OpenGLModuleHandle,"glOrtho"); + dglPassThrough = (glPassThrough_fp)dll_GetSymbol(OpenGLModuleHandle,"glPassThrough"); + dglPixelMapfv = (glPixelMapfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelMapfv"); + dglPixelMapuiv = (glPixelMapuiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelMapuiv"); + dglPixelMapusv = (glPixelMapusv_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelMapusv"); + dglPixelStoref = (glPixelStoref_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelStoref"); + dglPixelStorei = (glPixelStorei_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelStorei"); + dglPixelTransferf = (glPixelTransferf_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelTransferf"); + dglPixelTransferi = (glPixelTransferi_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelTransferi"); + dglPixelZoom = (glPixelZoom_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelZoom"); + dglPointSize = (glPointSize_fp)dll_GetSymbol(OpenGLModuleHandle,"glPointSize"); + dglPolygonMode = (glPolygonMode_fp)dll_GetSymbol(OpenGLModuleHandle,"glPolygonMode"); + dglPolygonOffset = (glPolygonOffset_fp)dll_GetSymbol(OpenGLModuleHandle,"glPolygonOffset"); + dglPolygonStipple = (glPolygonStipple_fp)dll_GetSymbol(OpenGLModuleHandle,"glPolygonStipple"); + dglPopAttrib = (glPopAttrib_fp)dll_GetSymbol(OpenGLModuleHandle,"glPopAttrib"); + dglPopClientAttrib = (glPopClientAttrib_fp)dll_GetSymbol(OpenGLModuleHandle,"glPopClientAttrib"); + dglPopMatrix = (glPopMatrix_fp)dll_GetSymbol(OpenGLModuleHandle,"glPopMatrix"); + dglPopName = (glPopName_fp)dll_GetSymbol(OpenGLModuleHandle,"glPopName"); + dglPrioritizeTextures = (glPrioritizeTextures_fp)dll_GetSymbol(OpenGLModuleHandle,"glPrioritizeTextures"); + dglPushAttrib = (glPushAttrib_fp)dll_GetSymbol(OpenGLModuleHandle,"glPushAttrib"); + dglPushClientAttrib = (glPushClientAttrib_fp)dll_GetSymbol(OpenGLModuleHandle,"glPushClientAttrib"); + dglPushMatrix = (glPushMatrix_fp)dll_GetSymbol(OpenGLModuleHandle,"glPushMatrix"); + dglPushName = (glPushName_fp)dll_GetSymbol(OpenGLModuleHandle,"glPushName"); + dglRasterPos2d = (glRasterPos2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2d"); + dglRasterPos2dv = (glRasterPos2dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2dv"); + dglRasterPos2f = (glRasterPos2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2f"); + dglRasterPos2fv = (glRasterPos2fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2fv"); + dglRasterPos2i = (glRasterPos2i_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2i"); + dglRasterPos2iv = (glRasterPos2iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2iv"); + dglRasterPos2s = (glRasterPos2s_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2s"); + dglRasterPos2sv = (glRasterPos2sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2sv"); + dglRasterPos3d = (glRasterPos3d_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3d"); + dglRasterPos3dv = (glRasterPos3dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3dv"); + dglRasterPos3f = (glRasterPos3f_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3f"); + dglRasterPos3fv = (glRasterPos3fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3fv"); + dglRasterPos3i = (glRasterPos3i_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3i"); + dglRasterPos3iv = (glRasterPos3iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3iv"); + dglRasterPos3s = (glRasterPos3s_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3s"); + dglRasterPos3sv = (glRasterPos3sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3sv"); + dglRasterPos4d = (glRasterPos4d_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4d"); + dglRasterPos4dv = (glRasterPos4dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4dv"); + dglRasterPos4f = (glRasterPos4f_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4f"); + dglRasterPos4fv = (glRasterPos4fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4fv"); + dglRasterPos4i = (glRasterPos4i_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4i"); + dglRasterPos4iv = (glRasterPos4iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4iv"); + dglRasterPos4s = (glRasterPos4s_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4s"); + dglRasterPos4sv = (glRasterPos4sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4sv"); + dglReadBuffer = (glReadBuffer_fp)dll_GetSymbol(OpenGLModuleHandle,"glReadBuffer"); + dglReadPixels = (glReadPixels_fp)dll_GetSymbol(OpenGLModuleHandle,"glReadPixels"); + dglRectd = (glRectd_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectd"); + dglRectdv = (glRectdv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectdv"); + dglRectf = (glRectf_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectf"); + dglRectfv = (glRectfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectfv"); + dglRecti = (glRecti_fp)dll_GetSymbol(OpenGLModuleHandle,"glRecti"); + dglRectiv = (glRectiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectiv"); + dglRects = (glRects_fp)dll_GetSymbol(OpenGLModuleHandle,"glRects"); + dglRectsv = (glRectsv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectsv"); + dglRenderMode = (glRenderMode_fp)dll_GetSymbol(OpenGLModuleHandle,"glRenderMode"); + dglRotated = (glRotated_fp)dll_GetSymbol(OpenGLModuleHandle,"glRotated"); + dglRotatef = (glRotatef_fp)dll_GetSymbol(OpenGLModuleHandle,"glRotatef"); + dglScaled = (glScaled_fp)dll_GetSymbol(OpenGLModuleHandle,"glScaled"); + dglScalef = (glScalef_fp)dll_GetSymbol(OpenGLModuleHandle,"glScalef"); + dglScissor = (glScissor_fp)dll_GetSymbol(OpenGLModuleHandle,"glScissor"); + dglSelectBuffer = (glSelectBuffer_fp)dll_GetSymbol(OpenGLModuleHandle,"glSelectBuffer"); + dglShadeModel = (glShadeModel_fp)dll_GetSymbol(OpenGLModuleHandle,"glShadeModel"); + dglStencilFunc = (glStencilFunc_fp)dll_GetSymbol(OpenGLModuleHandle,"glStencilFunc"); + dglStencilMask = (glStencilMask_fp)dll_GetSymbol(OpenGLModuleHandle,"glStencilMask"); + dglStencilOp = (glStencilOp_fp)dll_GetSymbol(OpenGLModuleHandle,"glStencilOp"); + dglTexCoord1d = (glTexCoord1d_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1d"); + dglTexCoord1dv = (glTexCoord1dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1dv"); + dglTexCoord1f = (glTexCoord1f_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1f"); + dglTexCoord1fv = (glTexCoord1fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1fv"); + dglTexCoord1i = (glTexCoord1i_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1i"); + dglTexCoord1iv = (glTexCoord1iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1iv"); + dglTexCoord1s = (glTexCoord1s_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1s"); + dglTexCoord1sv = (glTexCoord1sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1sv"); + dglTexCoord2d = (glTexCoord2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2d"); + dglTexCoord2dv = (glTexCoord2dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2dv"); + dglTexCoord2f = (glTexCoord2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2f"); + dglTexCoord2fv = (glTexCoord2fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2fv"); + dglTexCoord2i = (glTexCoord2i_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2i"); + dglTexCoord2iv = (glTexCoord2iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2iv"); + dglTexCoord2s = (glTexCoord2s_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2s"); + dglTexCoord2sv = (glTexCoord2sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2sv"); + dglTexCoord3d = (glTexCoord3d_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3d"); + dglTexCoord3dv = (glTexCoord3dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3dv"); + dglTexCoord3f = (glTexCoord3f_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3f"); + dglTexCoord3fv = (glTexCoord3fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3fv"); + dglTexCoord3i = (glTexCoord3i_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3i"); + dglTexCoord3iv = (glTexCoord3iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3iv"); + dglTexCoord3s = (glTexCoord3s_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3s"); + dglTexCoord3sv = (glTexCoord3sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3sv"); + dglTexCoord4d = (glTexCoord4d_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4d"); + dglTexCoord4dv = (glTexCoord4dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4dv"); + dglTexCoord4f = (glTexCoord4f_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4f"); + dglTexCoord4fv = (glTexCoord4fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4fv"); + dglTexCoord4i = (glTexCoord4i_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4i"); + dglTexCoord4iv = (glTexCoord4iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4iv"); + dglTexCoord4s = (glTexCoord4s_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4s"); + dglTexCoord4sv = (glTexCoord4sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4sv"); + dglTexCoordPointer = (glTexCoordPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoordPointer"); + dglTexEnvf = (glTexEnvf_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexEnvf"); + dglTexEnvfv = (glTexEnvfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexEnvfv"); + dglTexEnvi = (glTexEnvi_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexEnvi"); + dglTexEnviv = (glTexEnviv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexEnviv"); + dglTexGend = (glTexGend_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGend"); + dglTexGendv = (glTexGendv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGendv"); + dglTexGenf = (glTexGenf_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGenf"); + dglTexGenfv = (glTexGenfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGenfv"); + dglTexGeni = (glTexGeni_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGeni"); + dglTexGeniv = (glTexGeniv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGeniv"); + dglTexImage1D = (glTexImage1D_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexImage1D"); + dglTexImage2D = (glTexImage2D_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexImage2D"); + dglTexParameterf = (glTexParameterf_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexParameterf"); + dglTexParameterfv = (glTexParameterfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexParameterfv"); + dglTexParameteri = (glTexParameteri_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexParameteri"); + dglTexParameteriv = (glTexParameteriv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexParameteriv"); + dglTexSubImage1D = (glTexSubImage1D_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexSubImage1D"); + dglTexSubImage2D = (glTexSubImage2D_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexSubImage2D"); + dglTranslated = (glTranslated_fp)dll_GetSymbol(OpenGLModuleHandle,"glTranslated"); + dglTranslatef = (glTranslatef_fp)dll_GetSymbol(OpenGLModuleHandle,"glTranslatef"); + dglVertex2d = (glVertex2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2d"); + dglVertex2dv = (glVertex2dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2dv"); + dglVertex2f = (glVertex2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2f"); + dglVertex2fv = (glVertex2fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2fv"); + dglVertex2i = (glVertex2i_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2i"); + dglVertex2iv = (glVertex2iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2iv"); + dglVertex2s = (glVertex2s_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2s"); + dglVertex2sv = (glVertex2sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2sv"); + dglVertex3d = (glVertex3d_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3d"); + dglVertex3dv = (glVertex3dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3dv"); + dglVertex3f = (glVertex3f_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3f"); + dglVertex3fv = (glVertex3fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3fv"); + dglVertex3i = (glVertex3i_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3i"); + dglVertex3iv = (glVertex3iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3iv"); + dglVertex3s = (glVertex3s_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3s"); + dglVertex3sv = (glVertex3sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3sv"); + dglVertex4d = (glVertex4d_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4d"); + dglVertex4dv = (glVertex4dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4dv"); + dglVertex4f = (glVertex4f_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4f"); + dglVertex4fv = (glVertex4fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4fv"); + dglVertex4i = (glVertex4i_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4i"); + dglVertex4iv = (glVertex4iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4iv"); + dglVertex4s = (glVertex4s_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4s"); + dglVertex4sv = (glVertex4sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4sv"); + dglVertexPointer = (glVertexPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertexPointer"); + dglViewport = (glViewport_fp)dll_GetSymbol(OpenGLModuleHandle,"glViewport"); + +#ifdef WIN32 + dwglCopyContext = (wglCopyContext_fp)dll_GetSymbol(OpenGLModuleHandle,"wglCopyContext"); + dwglCreateContext = (wglCreateContext_fp)dll_GetSymbol(OpenGLModuleHandle,"wglCreateContext"); + dwglCreateLayerContext = (wglCreateLayerContext_fp)dll_GetSymbol(OpenGLModuleHandle,"wglCreateLayerContext"); + dwglDeleteContext = (wglDeleteContext_fp)dll_GetSymbol(OpenGLModuleHandle,"wglDeleteContext"); + dwglGetCurrentContext = (wglGetCurrentContext_fp)dll_GetSymbol(OpenGLModuleHandle,"wglGetCurrentContext"); + dwglGetCurrentDC = (wglGetCurrentDC_fp)dll_GetSymbol(OpenGLModuleHandle,"wglGetCurrentDC"); + dwglGetProcAddress = (wglGetProcAddress_fp)dll_GetSymbol(OpenGLModuleHandle,"wglGetProcAddress"); + dwglMakeCurrent = (wglMakeCurrent_fp)dll_GetSymbol(OpenGLModuleHandle,"wglMakeCurrent"); + dwglShareLists = (wglShareLists_fp)dll_GetSymbol(OpenGLModuleHandle,"wglShareLists"); + dwglUseFontBitmapsA = (wglUseFontBitmapsA_fp)dll_GetSymbol(OpenGLModuleHandle,"wglUseFontBitmapsA"); + dwglUseFontBitmapsW = (wglUseFontBitmapsW_fp)dll_GetSymbol(OpenGLModuleHandle,"wglUseFontBitmapsW"); + dwglUseFontOutlinesA = (wglUseFontOutlinesA_fp)dll_GetSymbol(OpenGLModuleHandle,"wglUseFontOutlinesA"); + dwglUseFontOutlinesW = (wglUseFontOutlinesW_fp)dll_GetSymbol(OpenGLModuleHandle,"wglUseFontOutlinesW"); + dwglDescribeLayerPlane = (wglDescribeLayerPlane_fp)dll_GetSymbol(OpenGLModuleHandle,"wglDescribeLayerPlane"); + dwglSetLayerPaletteEntries = (wglSetLayerPaletteEntries_fp)dll_GetSymbol(OpenGLModuleHandle,"wglSetLayerPaletteEntries"); + dwglGetLayerPaletteEntries = (wglGetLayerPaletteEntries_fp)dll_GetSymbol(OpenGLModuleHandle,"wglGetLayerPaletteEntries"); + dwglRealizeLayerPalette = (wglRealizeLayerPalette_fp)dll_GetSymbol(OpenGLModuleHandle,"wglRealizeLayerPalette"); + dwglSwapLayerBuffers = (wglSwapLayerBuffers_fp)dll_GetSymbol(OpenGLModuleHandle,"wglSwapLayerBuffers"); + #if (WINVER >= 0x0500) + dwglSwapMultipleBuffers = (wglSwapMultipleBuffers_fp)dll_GetSymbol(OpenGLModuleHandle,"wglSwapMultipleBuffers"); + #endif +#endif + + } + + return true; +} + +void OpenGL_SetFuncsToNull(void) +{ + dglAccum = NULL; + dglAlphaFunc = NULL; + dglAreTexturesResident = NULL; + dglArrayElement = NULL; + dglBegin = NULL; + dglBindTexture = NULL; + dglBitmap = NULL; + dglBlendFunc = NULL; + dglCallList = NULL; + dglCallLists = NULL; + dglClear = NULL; + dglClearAccum = NULL; + dglClearColor = NULL; + dglClearDepth = NULL; + dglClearIndex = NULL; + dglClearStencil = NULL; + dglClipPlane = NULL; + dglColor3b = NULL; + dglColor3bv = NULL; + dglColor3d = NULL; + dglColor3dv = NULL; + dglColor3f = NULL; + dglColor3fv = NULL; + dglColor3i = NULL; + dglColor3iv = NULL; + dglColor3s = NULL; + dglColor3sv = NULL; + dglColor3ub = NULL; + dglColor3ubv = NULL; + dglColor3ui = NULL; + dglColor3uiv = NULL; + dglColor3us = NULL; + dglColor3usv = NULL; + dglColor4b = NULL; + dglColor4bv = NULL; + dglColor4d = NULL; + dglColor4dv = NULL; + dglColor4f = NULL; + dglColor4fv = NULL; + dglColor4i = NULL; + dglColor4iv = NULL; + dglColor4s = NULL; + dglColor4sv = NULL; + dglColor4ub = NULL; + dglColor4ubv = NULL; + dglColor4ui = NULL; + dglColor4uiv = NULL; + dglColor4us = NULL; + dglColor4usv = NULL; + dglColorMask = NULL; + dglColorMaterial = NULL; + dglColorPointer = NULL; + dglCopyPixels = NULL; + dglCopyTexImage1D = NULL; + dglCopyTexImage2D = NULL; + dglCopyTexSubImage1D = NULL; + dglCopyTexSubImage2D = NULL; + dglCullFace = NULL; + dglDeleteLists = NULL; + dglDeleteTextures = NULL; + dglDepthFunc = NULL; + dglDepthMask = NULL; + dglDepthRange = NULL; + dglDisable = NULL; + dglDisableClientState = NULL; + dglDrawArrays = NULL; + dglDrawBuffer = NULL; + dglDrawElements = NULL; + dglDrawPixels = NULL; + dglEdgeFlag = NULL; + dglEdgeFlagPointer = NULL; + dglEdgeFlagv = NULL; + dglEnable = NULL; + dglEnableClientState = NULL; + dglEnd = NULL; + dglEndList = NULL; + dglEvalCoord1d = NULL; + dglEvalCoord1dv = NULL; + dglEvalCoord1f = NULL; + dglEvalCoord1fv = NULL; + dglEvalCoord2d = NULL; + dglEvalCoord2dv = NULL; + dglEvalCoord2f = NULL; + dglEvalCoord2fv = NULL; + dglEvalMesh1 = NULL; + dglEvalMesh2 = NULL; + dglEvalPoint1 = NULL; + dglEvalPoint2 = NULL; + dglFeedbackBuffer = NULL; + dglFinish = NULL; + dglFlush = NULL; + dglFogf = NULL; + dglFogfv = NULL; + dglFogi = NULL; + dglFogiv = NULL; + dglFrontFace = NULL; + dglFrustum = NULL; + dglGenLists = NULL; + dglGenTextures = NULL; + dglGetBooleanv = NULL; + dglGetClipPlane = NULL; + dglGetDoublev = NULL; + dglGetError = NULL; + dglGetFloatv = NULL; + dglGetIntegerv = NULL; + dglGetLightfv = NULL; + dglGetLightiv = NULL; + dglGetMapdv = NULL; + dglGetMapfv = NULL; + dglGetMapiv = NULL; + dglGetMaterialfv = NULL; + dglGetMaterialiv = NULL; + dglGetPixelMapfv = NULL; + dglGetPixelMapuiv = NULL; + dglGetPixelMapusv = NULL; + dglGetPointerv = NULL; + dglGetPolygonStipple = NULL; + dglGetString = NULL; + dglGetTexEnvfv = NULL; + dglGetTexEnviv = NULL; + dglGetTexGendv = NULL; + dglGetTexGenfv = NULL; + dglGetTexGeniv = NULL; + dglGetTexImage = NULL; + dglGetTexLevelParameterfv = NULL; + dglGetTexLevelParameteriv = NULL; + dglGetTexParameterfv = NULL; + dglGetTexParameteriv = NULL; + dglHint = NULL; + dglIndexMask = NULL; + dglIndexPointer = NULL; + dglIndexd = NULL; + dglIndexdv = NULL; + dglIndexf = NULL; + dglIndexfv = NULL; + dglIndexi = NULL; + dglIndexiv = NULL; + dglIndexs = NULL; + dglIndexsv = NULL; + dglIndexub = NULL; + dglIndexubv = NULL; + dglInitNames = NULL; + dglInterleavedArrays = NULL; + dglIsEnabled = NULL; + dglIsList = NULL; + dglIsTexture = NULL; + dglLightModelf = NULL; + dglLightModelfv = NULL; + dglLightModeli = NULL; + dglLightModeliv = NULL; + dglLightf = NULL; + dglLightfv = NULL; + dglLighti = NULL; + dglLightiv = NULL; + dglLineStipple = NULL; + dglLineWidth = NULL; + dglListBase = NULL; + dglLoadIdentity = NULL; + dglLoadMatrixd = NULL; + dglLoadMatrixf = NULL; + dglLoadName = NULL; + dglLogicOp = NULL; + dglMap1d = NULL; + dglMap1f = NULL; + dglMap2d = NULL; + dglMap2f = NULL; + dglMapGrid1d = NULL; + dglMapGrid1f = NULL; + dglMapGrid2d = NULL; + dglMapGrid2f = NULL; + dglMaterialf = NULL; + dglMaterialfv = NULL; + dglMateriali = NULL; + dglMaterialiv = NULL; + dglMatrixMode = NULL; + dglMultMatrixd = NULL; + dglMultMatrixf = NULL; + dglNewList = NULL; + dglNormal3b = NULL; + dglNormal3bv = NULL; + dglNormal3d = NULL; + dglNormal3dv = NULL; + dglNormal3f = NULL; + dglNormal3fv = NULL; + dglNormal3i = NULL; + dglNormal3iv = NULL; + dglNormal3s = NULL; + dglNormal3sv = NULL; + dglNormalPointer = NULL; + dglOrtho = NULL; + dglPassThrough = NULL; + dglPixelMapfv = NULL; + dglPixelMapuiv = NULL; + dglPixelMapusv = NULL; + dglPixelStoref = NULL; + dglPixelStorei = NULL; + dglPixelTransferf = NULL; + dglPixelTransferi = NULL; + dglPixelZoom = NULL; + dglPointSize = NULL; + dglPolygonMode = NULL; + dglPolygonOffset = NULL; + dglPolygonStipple = NULL; + dglPopAttrib = NULL; + dglPopClientAttrib = NULL; + dglPopMatrix = NULL; + dglPopName = NULL; + dglPrioritizeTextures = NULL; + dglPushAttrib = NULL; + dglPushClientAttrib = NULL; + dglPushMatrix = NULL; + dglPushName = NULL; + dglRasterPos2d = NULL; + dglRasterPos2dv = NULL; + dglRasterPos2f = NULL; + dglRasterPos2fv = NULL; + dglRasterPos2i = NULL; + dglRasterPos2iv = NULL; + dglRasterPos2s = NULL; + dglRasterPos2sv = NULL; + dglRasterPos3d = NULL; + dglRasterPos3dv = NULL; + dglRasterPos3f = NULL; + dglRasterPos3fv = NULL; + dglRasterPos3i = NULL; + dglRasterPos3iv = NULL; + dglRasterPos3s = NULL; + dglRasterPos3sv = NULL; + dglRasterPos4d = NULL; + dglRasterPos4dv = NULL; + dglRasterPos4f = NULL; + dglRasterPos4fv = NULL; + dglRasterPos4i = NULL; + dglRasterPos4iv = NULL; + dglRasterPos4s = NULL; + dglRasterPos4sv = NULL; + dglReadBuffer = NULL; + dglReadPixels = NULL; + dglRectd = NULL; + dglRectdv = NULL; + dglRectf = NULL; + dglRectfv = NULL; + dglRecti = NULL; + dglRectiv = NULL; + dglRects = NULL; + dglRectsv = NULL; + dglRenderMode = NULL; + dglRotated = NULL; + dglRotatef = NULL; + dglScaled = NULL; + dglScalef = NULL; + dglScissor = NULL; + dglSelectBuffer = NULL; + dglShadeModel = NULL; + dglStencilFunc = NULL; + dglStencilMask = NULL; + dglStencilOp = NULL; + dglTexCoord1d = NULL; + dglTexCoord1dv = NULL; + dglTexCoord1f = NULL; + dglTexCoord1fv = NULL; + dglTexCoord1i = NULL; + dglTexCoord1iv = NULL; + dglTexCoord1s = NULL; + dglTexCoord1sv = NULL; + dglTexCoord2d = NULL; + dglTexCoord2dv = NULL; + dglTexCoord2f = NULL; + dglTexCoord2fv = NULL; + dglTexCoord2i = NULL; + dglTexCoord2iv = NULL; + dglTexCoord2s = NULL; + dglTexCoord2sv = NULL; + dglTexCoord3d = NULL; + dglTexCoord3dv = NULL; + dglTexCoord3f = NULL; + dglTexCoord3fv = NULL; + dglTexCoord3i = NULL; + dglTexCoord3iv = NULL; + dglTexCoord3s = NULL; + dglTexCoord3sv = NULL; + dglTexCoord4d = NULL; + dglTexCoord4dv = NULL; + dglTexCoord4f = NULL; + dglTexCoord4fv = NULL; + dglTexCoord4i = NULL; + dglTexCoord4iv = NULL; + dglTexCoord4s = NULL; + dglTexCoord4sv = NULL; + dglTexCoordPointer = NULL; + dglTexEnvf = NULL; + dglTexEnvfv = NULL; + dglTexEnvi = NULL; + dglTexEnviv = NULL; + dglTexGend = NULL; + dglTexGendv = NULL; + dglTexGenf = NULL; + dglTexGenfv = NULL; + dglTexGeni = NULL; + dglTexGeniv = NULL; + dglTexImage1D = NULL; + dglTexImage2D = NULL; + dglTexParameterf = NULL; + dglTexParameterfv = NULL; + dglTexParameteri = NULL; + dglTexParameteriv = NULL; + dglTexSubImage1D = NULL; + dglTexSubImage2D = NULL; + dglTranslated = NULL; + dglTranslatef = NULL; + dglVertex2d = NULL; + dglVertex2dv = NULL; + dglVertex2f = NULL; + dglVertex2fv = NULL; + dglVertex2i = NULL; + dglVertex2iv = NULL; + dglVertex2s = NULL; + dglVertex2sv = NULL; + dglVertex3d = NULL; + dglVertex3dv = NULL; + dglVertex3f = NULL; + dglVertex3fv = NULL; + dglVertex3i = NULL; + dglVertex3iv = NULL; + dglVertex3s = NULL; + dglVertex3sv = NULL; + dglVertex4d = NULL; + dglVertex4dv = NULL; + dglVertex4f = NULL; + dglVertex4fv = NULL; + dglVertex4i = NULL; + dglVertex4iv = NULL; + dglVertex4s = NULL; + dglVertex4sv = NULL; + dglVertexPointer = NULL; + dglViewport = NULL; + +#ifdef WIN32 + dwglCopyContext = NULL; + dwglCreateContext = NULL; + dwglCreateLayerContext = NULL; + dwglDeleteContext = NULL; + dwglGetCurrentContext = NULL; + dwglGetCurrentDC = NULL; + dwglGetProcAddress = NULL; + dwglMakeCurrent = NULL; + dwglShareLists = NULL; + dwglUseFontBitmapsA = NULL; + dwglUseFontBitmapsW = NULL; + dwglUseFontOutlinesA = NULL; + dwglUseFontOutlinesW = NULL; + dwglDescribeLayerPlane = NULL; + dwglSetLayerPaletteEntries = NULL; + dwglGetLayerPaletteEntries = NULL; + dwglRealizeLayerPalette = NULL; + dwglSwapLayerBuffers = NULL; + #if (WINVER >= 0x0500) + dwglSwapMultipleBuffers = NULL; + #endif +#endif + +} +#endif + + +#endif //!__LOADGL_H__ diff --git a/arch/ogl/include/ogl_init.h b/arch/ogl/include/ogl_init.h new file mode 100644 index 00000000..e0ee68be --- /dev/null +++ b/arch/ogl/include/ogl_init.h @@ -0,0 +1,160 @@ +//prototypes opengl functions - Added 9/15/99 Matthew Mueller +#ifndef _OGL_INIT_H_ +#define _OGL_INIT_H_ + +#ifdef __WINDOWS__ +#include +#include +#endif + +//#ifdef __WINDOWS__ +//#define OGL_RUNTIME_LOAD +//#endif + +#ifdef OGL_RUNTIME_LOAD +#include "loadgl.h" +int ogl_init_load_library(void); +#else +#include +#endif + +#ifndef GL_VERSION_1_1 +#ifdef GL_EXT_texture +#define GL_INTENSITY4 GL_INTENSITY4_EXT +#define GL_INTENSITY8 GL_INTENSITY8_EXT +#endif +#endif + + +#include "gr.h" +#include "palette.h" +#include "types.h" + + +#define OGL_TEXTURE_LIST_SIZE 2000 + +typedef struct _ogl_texture { + int handle; + GLint internalformat; + GLenum format; + int w,h,tw,th,lw; + int bytesu; + int bytes; + GLfloat u,v; + GLfloat prio; + int wrapstate; + fix lastrend; + ulong numrend; + char wantmip; +} ogl_texture; + +extern ogl_texture ogl_texture_list[OGL_TEXTURE_LIST_SIZE]; + +extern int ogl_mem_target; +ogl_texture* ogl_get_free_texture(void); +void ogl_init_texture(ogl_texture* t); +void ogl_init_texture_list_internal(void); +void ogl_smash_texture_list_internal(void); +void ogl_vivify_texture_list_internal(void); + +extern int ogl_fullscreen; +void ogl_do_fullscreen_internal(void); + +extern int ogl_voodoohack; + +extern int ogl_alttexmerge;//merge textures by just printing the seperate textures? +extern int ogl_rgba_format; +extern int ogl_intensity4_ok; +extern int ogl_luminance4_alpha4_ok; +extern int ogl_rgba2_ok; +extern int ogl_readpixels_ok; + +extern int gl_initialized; +extern int GL_texmagfilt,GL_texminfilt,GL_needmipmaps; +extern int gl_reticle; + +extern int GL_TEXTURE_2D_enabled; +//extern int GL_texclamp_enabled; +//extern int GL_TEXTURE_ENV_MODE_state,GL_TEXTURE_MAG_FILTER_state,GL_TEXTURE_MIN_FILTER_state; +#define OGL_ENABLE2(a,f) {if (a ## _enabled!=1) {f;a ## _enabled=1;}} +#define OGL_DISABLE2(a,f) {if (a ## _enabled!=0) {f;a ## _enabled=0;}} + +//#define OGL_ENABLE(a) OGL_ENABLE2(a,glEnable(a)) +//#define OGL_DISABLE(a) OGL_DISABLE2(a,glDisable(a)) +#define OGL_ENABLE(a) OGL_ENABLE2(GL_ ## a,glEnable(GL_ ## a)) +#define OGL_DISABLE(a) OGL_DISABLE2(GL_ ## a,glDisable(GL_ ## a)) + +//#define OGL_TEXCLAMP() OGL_ENABLE2(GL_texclamp,glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);) +//#define OGL_TEXREPEAT() OGL_DISABLE2(GL_texclamp,glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);) + +//#define OGL_SETSTATE(a,s,f) {if (a ## _state!=s) {f;a ## _state=s;}} + +//#define OGL_TEXENV(p,m) OGL_SETSTATE(p,m,glTexEnvi(GL_TEXTURE_ENV, p,m)); +//#define OGL_TEXPARAM(p,m) OGL_SETSTATE(p,m,glTexParameteri(GL_TEXTURE_2D,p,m)); + +extern int last_width,last_height; +#define OGL_VIEWPORT(x,y,w,h){if (w!=last_width || h!=last_height){glViewport(x,grd_curscreen->sc_canvas.cv_bitmap.bm_h-y-h,w,h);last_width=w;last_height=h;}} + +//platform specific funcs +//MSVC seems to have problems with inline funcs not being found during linking +#ifndef _MSC_VER +inline +#endif +void ogl_swap_buffers_internal(void); +int ogl_init_window(int x, int y);//create a window/switch modes/etc +void ogl_destroy_window(void);//destroy window/etc +void ogl_init(void);//one time initialization +void ogl_close(void);//one time shutdown + +//generic funcs +#define OGLTEXBUFSIZE (1024*1024*4) +extern GLubyte texbuf[OGLTEXBUFSIZE]; +//void ogl_filltexbuf(unsigned char *data,GLubyte *texp,int width,int height,int twidth,int theight); +void ogl_filltexbuf(unsigned char *data,GLubyte *texp,int truewidth,int width,int height,int dxo,int dyo,int twidth,int theight,int type); +void ogl_loadbmtexture_m(grs_bitmap *bm,int domipmap); +void ogl_loadbmtexture(grs_bitmap *bm); +//void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,int dyo, int *texid,float *u,float *v,char domipmap,float prio); +void ogl_loadtexture(unsigned char * data, int dxo,int dyo, ogl_texture *tex); +void ogl_freetexture(ogl_texture *gltexture); +void ogl_freebmtexture(grs_bitmap *bm); +void ogl_do_palfx(void); +void ogl_start_frame(void); +void ogl_end_frame(void); +void ogl_swap_buffers(void); +void ogl_set_screen_mode(void); +void ogl_cache_level_textures(void); + +void ogl_urect(int left,int top,int right,int bot); +bool ogl_ubitmapm_c(int x, int y,grs_bitmap *bm,int c); +bool ogl_ubitmapm(int x, int y,grs_bitmap *bm); +bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); +bool ogl_ubitblt_tolinear(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); +bool ogl_ubitblt_copy(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); +void ogl_upixelc(int x, int y, int c); +void ogl_ulinec(int left,int top,int right,int bot,int c); + +extern unsigned char *ogl_pal; + +#include "3d.h" +bool g3_draw_tmap_2(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bmbot,grs_bitmap *bm,int orient); + +void ogl_draw_reticle(int cross,int primary,int secondary); + +//whee +//#define PAL2Tr(c) ((gr_palette[c*3]+gr_palette_gamma)/63.0) +//#define PAL2Tg(c) ((gr_palette[c*3+1]+gr_palette_gamma)/63.0) +//#define PAL2Tb(c) ((gr_palette[c*3+2]+gr_palette_gamma)/63.0) +//#define PAL2Tr(c) ((gr_palette[c*3])/63.0) +//#define PAL2Tg(c) ((gr_palette[c*3+1])/63.0) +//#define PAL2Tb(c) ((gr_palette[c*3+2])/63.0) +#define CPAL2Tr(c) ((gr_current_pal[c*3])/63.0) +#define CPAL2Tg(c) ((gr_current_pal[c*3+1])/63.0) +#define CPAL2Tb(c) ((gr_current_pal[c*3+2])/63.0) +#define PAL2Tr(c) ((ogl_pal[c*3])/63.0) +#define PAL2Tg(c) ((ogl_pal[c*3+1])/63.0) +#define PAL2Tb(c) ((ogl_pal[c*3+2])/63.0) +//inline GLfloat PAL2Tr(int c); +//inline GLfloat PAL2Tg(int c); +//inline GLfloat PAL2Tb(int c); + +#endif diff --git a/arch/sdl/Makefile.am b/arch/sdl/Makefile.am new file mode 100644 index 00000000..23a16a3e --- /dev/null +++ b/arch/sdl/Makefile.am @@ -0,0 +1,4 @@ +noinst_LIBRARIES = libarchsdl.a +INCLUDES = -I $(top_srcdir)/includes -Iinclude -I $(top_srcdir)/main -I$(top_srcdir)/input/sdl/include + +libarchsdl_a_SOURCES = init.c timer.c diff --git a/arch/sdl/Makefile.in b/arch/sdl/Makefile.in new file mode 100644 index 00000000..d4985647 --- /dev/null +++ b/arch/sdl/Makefile.in @@ -0,0 +1,299 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +CFLAGS = @CFLAGS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +NASM = @NASM@ +NASMFLAGS = @NASMFLAGS@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_LIBS = @SDL_LIBS@ +VERSION = @VERSION@ + +noinst_LIBRARIES = libarchsdl.a +INCLUDES = -I $(top_srcdir)/includes -Iinclude -I $(top_srcdir)/main -I$(top_srcdir)/input/sdl/include + +libarchsdl_a_SOURCES = init.c timer.c +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../../conf.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I../.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +libarchsdl_a_LIBADD = +libarchsdl_a_OBJECTS = init.o timer.o +AR = ar +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +DEP_FILES = .deps/init.P .deps/timer.P +SOURCES = $(libarchsdl_a_SOURCES) +OBJECTS = $(libarchsdl_a_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu arch/sdl/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +libarchsdl.a: $(libarchsdl_a_OBJECTS) $(libarchsdl_a_DEPENDENCIES) + -rm -f libarchsdl.a + $(AR) cru libarchsdl.a $(libarchsdl_a_OBJECTS) $(libarchsdl_a_LIBADD) + $(RANLIB) libarchsdl.a + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = arch/sdl + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu arch/sdl/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile $(LIBRARIES) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ + mostlyclean-tags mostlyclean-depend mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \ + clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-noinstLIBRARIES distclean-compile \ + distclean-tags distclean-depend distclean-generic \ + clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/arch/sdl/init.c b/arch/sdl/init.c new file mode 100644 index 00000000..361d24ed --- /dev/null +++ b/arch/sdl/init.c @@ -0,0 +1,29 @@ +// SDL architecture support +#include +#include +#include +#include +#include "text.h" +#include "event.h" +#include "error.h" +#include "args.h" + +extern void d_mouse_init(); + +void sdl_close() +{ + SDL_Quit(); +} + +void arch_sdl_init() +{ + // Initialise the library +//edited on 01/03/99 by Matt Mueller - if we use SDL_INIT_EVERYTHING, cdrom is initialized even if -nocdaudio is used +#ifdef SDL_INPUT + if (!args_find("-nomouse")) + d_mouse_init(); +#endif + if (!args_find("-nosound")) + digi_init(); + atexit(sdl_close); +} diff --git a/arch/sdl/timer.c b/arch/sdl/timer.c new file mode 100644 index 00000000..715bcb28 --- /dev/null +++ b/arch/sdl/timer.c @@ -0,0 +1,13 @@ +// SDL library timer functions + +#include +#include +#include "maths.h" + +fix timer_get_fixed_seconds(void) { + fix x; + unsigned long tv_now = SDL_GetTicks(); + x=i2f(tv_now/1000) | fixdiv(i2f(tv_now % 1000),i2f(1000)); + return x; +} + diff --git a/arch/win32/d1x.ico b/arch/win32/d1x.ico new file mode 100644 index 0000000000000000000000000000000000000000..650118d7ddae18969144f6d1e683e0176b8c41bf GIT binary patch literal 2494 zcmb`|v2N2)6vpurs1ydIE~OxZR1XXt85xjz2OgmV1A`xcp(A4P*o3 zl(*StoESQUd{BZz$R|i}2v(Ef5b}Wu4#8S79D;RZIE1`Nfk6qgnaP{4#8?N974V^2@b(pG8}?+ zWH^L;6B8VY8=APO4#BFL^~n(O%}#I#R+Hfn@`Ffl2-cF}5UeA^A>@aa;7~lk#OnDa zSmmrwf{-6>f=rEv&WwX9Euz{yyj48dwL z90CimJ{f|wWHJY5zSf31mgIS*p!D=!b0w-pDG6ZYMa0u3s z;ShLZeKHh3h&0}L@y-vT;#&xZz|O2shF~=r4uKP~J{f|wWHawlcpu(`1*O_U;Yn^D%iV zNAI?ciQL_^^Jub-&2rRaxY?mhmOLG=_88}G4VzDZZsye0iJpGHklUqyWr^+VJ)>X)cLqW+G0^r)P#iuxkz>!_EH LOaChB$Ebe*Ac>P{ literal 0 HcmV?d00001 diff --git a/arch/win32/d1x.rc b/arch/win32/d1x.rc new file mode 100644 index 00000000..3695fe47 --- /dev/null +++ b/arch/win32/d1x.rc @@ -0,0 +1,220 @@ +//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 + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_MAIN_ACCEL ACCELERATORS DISCARDABLE +BEGIN + VK_F1, IDM_HELP, VIRTKEY, SHIFT, NOINVERT + VK_F2, IDM_CHANGEDEVICE, VIRTKEY, SHIFT, NOINVERT + VK_F4, IDM_EXIT, VIRTKEY, ALT, NOINVERT + VK_RETURN, IDM_TOGGLESTART, VIRTKEY, NOINVERT + VK_RETURN, IDM_TOGGLEFULLSCREEN, VIRTKEY, ALT, NOINVERT + VK_SPACE, IDM_SINGLESTEP, VIRTKEY, SHIFT, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 236 + VERTGUIDE, 28 + VERTGUIDE, 215 + TOPMARGIN, 7 + BOTTOMMARGIN, 99 + HORZGUIDE, 27 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUT DIALOG DISCARDABLE 0, 0, 243, 106 +STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "About Direct3D Descent" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,201,85,35,14 + CTEXT "Based on original code by Parallax Software",IDC_STATIC, + 7,46,229,14 + CTEXT "Only for use with full version of Descent from Interplay Productions", + IDC_STATIC,7,65,229,14 + ICON IDI_MAIN_ICON,IDC_STATIC,7,7,21,20 + CTEXT "DOS/VGA to Win32/Direct3D conversion by Piers Haken", + IDC_STATIC,28,27,187,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Go/stop\tEnter", IDM_TOGGLESTART + MENUITEM "&Single step\tSpace", IDM_SINGLESTEP + MENUITEM SEPARATOR + MENUITEM "&About...\tF1", IDM_HELP + MENUITEM "&Change device...\tF2", IDM_CHANGEDEVICE + MENUITEM SEPARATOR + MENUITEM "E&xit\tESC", IDM_EXIT + END +END + +IDR_POPUP MENU DISCARDABLE +BEGIN + POPUP "Popup" + BEGIN + MENUITEM "&Go/stop", IDM_TOGGLESTART + MENUITEM "&Single step", IDM_SINGLESTEP + MENUITEM SEPARATOR + MENUITEM "&About...", IDM_HELP + MENUITEM "&Change device...", IDM_CHANGEDEVICE + MENUITEM SEPARATOR + MENUITEM "E&xit", IDM_EXIT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAIN_ICON ICON DISCARDABLE "d1x.ico" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.K.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK +#pragma code_page(1252) +#endif //_WIN32 + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,0,0,1 + PRODUCTVERSION 0,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904b0" + BEGIN + VALUE "Comments", "Doesn't work very well\0" + VALUE "CompanyName", "Spong Technologies\0" + VALUE "FileDescription", "d1xd3d\0" + VALUE "FileVersion", "0, 0, 0, 1\0" + VALUE "InternalName", "d1xd3d\0" + VALUE "OriginalFilename", "d1xd3d.exe\0" + VALUE "ProductName", "Direct3D Descent\0" + VALUE "ProductVersion", "0, 0, 0, 1\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x809, 1200 + END +END + +#endif // !_MAC + +#endif // English (U.K.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/arch/win32/d3d.ico b/arch/win32/d3d.ico new file mode 100644 index 0000000000000000000000000000000000000000..aa7361f6d8881eb50bf9606327cf7528137770c2 GIT binary patch literal 953 zcmbVKF>d5A3>@1F=xi8??gb~f2m*iNTx_|2it~h&+bvZ36)IfrBT}YJnIc%-47J{* zNOiO+c{n6R(F7{g2*E@0Rs#>*y)XE&0`3~%k+wjcs14bnY5VnXUTd++E#+^hQl7{*Xic5BmQz2hOiSp6o(k&5Qwh<-8hbM5LOmo zp^S3q*DF3DMq%T-WjSFP7*Kd(pi_cdJnlMlo^u049Rp7{g% zGu?&J*>R%L(wX>#eYyU|Gu*`Za$LcRhqwF4K%Vvb(g5M3>i0U&q6TT~LOrLm6n*ZeV z`edr + +// HACK!!!!! +#include +#ifndef SM_CMONITORS +#define SM_CMONITORS +DECLARE_HANDLE(HMONITOR); +#endif + +#include "D3DEnum.h" +#include "D3DUtil.h" + + + + +//----------------------------------------------------------------------------- +// Constants and function prototypes for the user select driver dialog +//----------------------------------------------------------------------------- +DLGTEMPLATE* _BuildDriverSelectTemplate(); +BOOL CALLBACK _DriverSelectProc( HWND, UINT, WPARAM, LPARAM ); + + + + +//----------------------------------------------------------------------------- +// Global data for the enumerator functions +//----------------------------------------------------------------------------- +static LPDIRECTDRAW4 g_pDD = NULL; // Used for callbacks +static BOOL g_bRefRastEnumerated = FALSE; // For the reference rast +static BOOL g_bDevicesEnumerated = FALSE; // Used during enumeration + +D3DEnum_DriverInfo* g_pFirstDriver = NULL; // List of DD drivers +D3DEnum_DriverInfo* g_pDefaultDriver = NULL; // Default driver +D3DEnum_DriverInfo* g_pCurrentDriver = NULL; // The selected DD driver + +static HRESULT (*g_fnAppConfirmFn)(DDCAPS*, D3DDEVICEDESC*) = NULL; + + + + +//----------------------------------------------------------------------------- +// Local callback functions used during enumeration +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Name: EnumDisplayModesCallback() +// Desc: Callback function called for each display mode. Each available +// display mode is added to a list for further choosing from the app. +//----------------------------------------------------------------------------- +static HRESULT WINAPI EnumDisplayModesCallback( DDSURFACEDESC2* pddsd, + VOID* pvContext ) +{ + // Check parameters + if( NULL==pddsd || NULL==pvContext ) + return DDENUMRET_CANCEL; + + D3DEnum_DeviceInfo* pDevice = (D3DEnum_DeviceInfo*)pvContext; + D3DEnum_ModeInfo* pNewMode; + DWORD dwBitDepth = pDevice->ddDesc.dwDeviceRenderBitDepth; + DWORD dwModeDepth = pddsd->ddpfPixelFormat.dwRGBBitCount; + + // Check mode for compatability with device. Skip 8-bit modes. + if( (32==dwModeDepth) && (0==(dwBitDepth&DDBD_32)) ) return DDENUMRET_OK; + if( (24==dwModeDepth) && (0==(dwBitDepth&DDBD_24)) ) return DDENUMRET_OK; + if( (16==dwModeDepth) && (0==(dwBitDepth&DDBD_16)) ) return DDENUMRET_OK; + if( ( 8==dwModeDepth) ) return DDENUMRET_OK; + + // Create a new mode structure + if( NULL == ( pNewMode = new D3DEnum_ModeInfo ) ) + return DDENUMRET_CANCEL; + + // Initialize the new mode structure + ZeroMemory( pNewMode, sizeof(D3DEnum_ModeInfo) ); + memcpy( &pNewMode->ddsd, pddsd, sizeof(DDSURFACEDESC2) ); + sprintf( pNewMode->strDesc, TEXT("%ld x %ld x %ld"), pddsd->dwWidth, + pddsd->dwHeight, dwModeDepth ); + + // Link the new mode struct in the list of other display modes + D3DEnum_ModeInfo** pMode = &pDevice->pFirstMode; + while( *pMode ) + pMode = &((*pMode)->pNext); + (*pMode) = pNewMode; + + // If this is a 640x480x16 mode, save it as the default mode + if( ( 640 == pddsd->dwWidth ) && ( 480 == pddsd->dwHeight ) && + ( 16 == pddsd->ddpfPixelFormat.dwRGBBitCount ) ) + pDevice->pCurrentMode = pNewMode; + + if( NULL == pDevice->pCurrentMode ) + pDevice->pCurrentMode = pNewMode; + + return DDENUMRET_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: Enum3DDevicesCallback() +// Desc: Callback function called for each DirectX 3D device. The driver's +// attributes are added to the list of available drivers. +//----------------------------------------------------------------------------- +static HRESULT WINAPI Enum3DDevicesCallback( GUID* pGUID, LPSTR strDesc, + LPSTR strName, LPD3DDEVICEDESC pHALDesc, + LPD3DDEVICEDESC pHELDesc, LPVOID pvContext ) +{ + D3DEnum_DriverInfo* pDriver = (D3DEnum_DriverInfo*)pvContext; + D3DEnum_DeviceInfo* pNewDevice; + + // Check params + if( NULL==pGUID || NULL==pHALDesc || NULL==pHELDesc || NULL==pDriver ) + return D3DENUMRET_CANCEL; + + // Handle specific device GUIDs. NullDevice renders nothing + if( IsEqualGUID( *pGUID, IID_IDirect3DNullDevice ) ) + return D3DENUMRET_OK; + + // Set a flag so we know enumeration is working. This is just a feature to + // help return more informative return codes later on. + g_bDevicesEnumerated = TRUE; + + // Get info about this device. + BOOL bIsHardware = ( 0 != pHALDesc->dwFlags ); + D3DDEVICEDESC* pDesc = bIsHardware ? pHALDesc : pHELDesc; + + // Only enumerate software rasterizers for the primary device (which has + // a NULL GUID). This is to avoid duplicates + if( pDriver->pGUID != NULL ) + if( FALSE == bIsHardware ) + return D3DENUMRET_OK; + + + // Give the app a chance to accept or reject this device, based on + // what feature set it supports + if( g_fnAppConfirmFn ) + if( FAILED( g_fnAppConfirmFn( &pDriver->ddDriverCaps, pDesc ) ) ) + return D3DENUMRET_OK; + + // Create a new D3D Driver struct + if( NULL == ( pNewDevice = new D3DEnum_DeviceInfo ) ) + return D3DENUMRET_CANCEL; + ZeroMemory( pNewDevice, sizeof(D3DEnum_DeviceInfo) ); + + // Copy remaining device attributes + memcpy( &pNewDevice->guid, pGUID, sizeof(GUID) ); + pNewDevice->pGUID = &pNewDevice->guid; + strncpy( pNewDevice->strName, strName, 39 ); + memcpy( &pNewDevice->ddDesc, pDesc, sizeof(D3DDEVICEDESC) ); + pNewDevice->bIsHardware = bIsHardware; + + if( pNewDevice->bIsHardware ) + pDriver->pCurrentDevice = pNewDevice; + else + { + if( NULL == pDriver->pCurrentDevice ) + if( D3DCOLOR_RGB & pHELDesc->dcmColorModel ) + pDriver->pCurrentDevice = pNewDevice; + } + + // Enumerate the display modes + g_pDD->EnumDisplayModes( 0, NULL, pNewDevice, EnumDisplayModesCallback ); + + // Get the display mode's depth + DDSURFACEDESC2 ddsd; + ddsd.dwSize = sizeof(DDSURFACEDESC2); + g_pDD->GetDisplayMode( &ddsd ); + DWORD dwDisplayBPP = ddsd.ddpfPixelFormat.dwRGBBitCount; + + // Set the initial bWindowed flag if the device can render in a window and + // supports the current display mode + if( pDriver->ddDriverCaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED ) + { + for( D3DEnum_ModeInfo* pMode=pNewDevice->pFirstMode; pMode; + pMode = pMode->pNext ) + { + if( pMode->ddsd.ddpfPixelFormat.dwRGBBitCount == dwDisplayBPP ) + { + pNewDevice->bCompatbileWithDesktop = TRUE; + if( NULL == pDriver->pGUID ) + pNewDevice->bWindowed = TRUE; + } + } + } + + if( pNewDevice->pFirstMode ) + { + // Link it with the other D3D drivers in the DD Driver struct + D3DEnum_DeviceInfo** pDevice = &pDriver->pFirstDevice; + while( *pDevice ) + pDevice = &((*pDevice)->pNext); + (*pDevice) = pNewDevice; + } + else + // Device has no modes, so delete it + delete pNewDevice; + + if( IsEqualGUID( *pGUID, IID_IDirect3DRefDevice ) ) + g_bRefRastEnumerated = TRUE; + + return D3DENUMRET_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DirectDrawEnumCallbackEx() +// Desc: Callback function called for each DirectDraw driver. Unless we have +// multimon or a type of card which uses a separate 2D card in +// conjunction with the 3D card, this is only done once. +//----------------------------------------------------------------------------- +static BOOL WINAPI DirectDrawEnumCallbackEx( GUID FAR* pGUID, LPSTR strDesc, + LPSTR strName, VOID*, + HMONITOR hMonitor ) +{ + // Use the GUID to create the DirectDraw object, so that information + // can be extracted from it. + LPDIRECTDRAW pDD; + if( FAILED( DirectDrawCreate( pGUID, &pDD, 0L ) ) ) + { + DEBUG_MSG( TEXT("Can't create DDraw during enumeration!") ); + return D3DENUMRET_OK; + } + + // Query the DirectDraw driver for access to Direct3D. + if( FAILED( pDD->QueryInterface( IID_IDirectDraw4, (VOID**)&g_pDD ) ) ) + { + DEBUG_MSG( TEXT("Can't query IDirectDraw4 during enumeration!") ); + pDD->Release(); + return D3DENUMRET_OK; + } + pDD->Release(); + + // Query the DirectDraw driver for access to Direct3D. + LPDIRECT3D3 pD3D; + if( FAILED( g_pDD->QueryInterface( IID_IDirect3D3, (VOID**)&pD3D ) ) ) + { + DEBUG_MSG( TEXT("Can't query IDirect3D3 during enumeration!") ); + g_pDD->Release(); + return D3DENUMRET_OK; + } + + // Copy the DDDriver info into a new DriverInfo struct + D3DEnum_DriverInfo* pNewDriver = new D3DEnum_DriverInfo; + if( NULL == pNewDriver ) + return D3DENUMRET_CANCEL; + + ZeroMemory( pNewDriver, sizeof(D3DEnum_DriverInfo) ); + + // Copy the GUID (if specified) and the driver name + if( NULL != pGUID ) + { + memcpy( &pNewDriver->guid, pGUID, sizeof(GUID) ); + pNewDriver->pGUID = &pNewDriver->guid; + } + strncpy( pNewDriver->strDesc, strDesc, 39 ); + strncpy( pNewDriver->strName, strName, 39 ); + pNewDriver->hMonitor = hMonitor; + + // Get the caps bits for the driver + pNewDriver->ddDriverCaps.dwSize = sizeof(DDCAPS); + pNewDriver->ddHELCaps.dwSize = sizeof(DDCAPS); + g_pDD->GetCaps( &pNewDriver->ddDriverCaps, &pNewDriver->ddHELCaps ); + + // Now, enumerate all the 3D devices + pD3D->EnumDevices( Enum3DDevicesCallback, pNewDriver ); + + if( pNewDriver->pFirstDevice ) + { + // Link the new DDDriver with the global list + D3DEnum_DriverInfo** pDriver = &g_pFirstDriver; + while( *pDriver ) + pDriver = &((*pDriver)->pNext); + (*pDriver) = pNewDriver; + + // Decide if this is a good default driver + if( NULL == pGUID ) + g_pCurrentDriver = pNewDriver; + } + else + // Driver has no devices, so delete it + delete pNewDriver; + + pD3D->Release(); + g_pDD->Release(); + return DDENUMRET_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DirectDrawEnumCallback() +// Desc: Non-mulitmon version of the ddraw enumeration callback +//----------------------------------------------------------------------------- +static BOOL WINAPI DirectDrawEnumCallback( GUID FAR* pGUID, LPSTR strDesc, + LPSTR strName, VOID* ) +{ + return DirectDrawEnumCallbackEx( pGUID, strDesc, strName, NULL, NULL ); +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_FreeResources() +// Desc: Frees all resources used for driver enumeration +//----------------------------------------------------------------------------- +VOID D3DEnum_FreeResources() +{ + // Loop through each driver, and delete everything + while( g_pFirstDriver ) + { + D3DEnum_DriverInfo* pDriverVictim = g_pFirstDriver; + g_pFirstDriver = g_pFirstDriver->pNext; + + while( pDriverVictim->pFirstDevice ) + { + D3DEnum_DeviceInfo* pDeviceVictim = pDriverVictim->pFirstDevice; + pDriverVictim->pFirstDevice = pDeviceVictim->pNext; + + while( pDeviceVictim->pFirstMode ) + { + D3DEnum_ModeInfo* pModeVictim = pDeviceVictim->pFirstMode; + pDeviceVictim->pFirstMode = pModeVictim->pNext; + delete pModeVictim; + } + delete pDeviceVictim; + } + delete pDriverVictim; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: RefreshListForDesktopCompatibility() +// Desc: Loops through list of devices, and marks a flag for whether the device +// is compatible with the desktop bit depth. +//----------------------------------------------------------------------------- +static VOID RefreshListForDesktopCompatibility() +{ + // Get the currect display mode description + LPDIRECTDRAW pDD; + DDSURFACEDESC ddsd; + if( FAILED( DirectDrawCreate( NULL, &pDD, NULL ) ) ) + return; + ddsd.dwSize = sizeof(DDSURFACEDESC); + pDD->GetDisplayMode( &ddsd ); + pDD->Release(); + + // Get the display mode's depth + DWORD dwDisplayBPP = ddsd.ddpfPixelFormat.dwRGBBitCount; + + // Loop through the devices, and check if any modes works with the current + // display setting + for( D3DEnum_DriverInfo* pDriver = g_pFirstDriver; pDriver; + pDriver = pDriver->pNext ) + { + for( D3DEnum_DeviceInfo* pDevice=pDriver->pFirstDevice; pDevice; + pDevice = pDevice->pNext ) + { + pDevice->bCompatbileWithDesktop = FALSE; + + for( D3DEnum_ModeInfo* pMode=pDevice->pFirstMode; pMode; + pMode = pMode->pNext ) + { + if( pMode->ddsd.ddpfPixelFormat.dwRGBBitCount == dwDisplayBPP ) + pDevice->bCompatbileWithDesktop = TRUE; + } + } + } +} + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_EnumerateDevices() +// Desc: Enumerates all drivers, devices, and modes. The optional app-supplied +// callback is called for each enumerated device, to confirm that the +// device supports the feature set required by the app. +//----------------------------------------------------------------------------- +HRESULT D3DEnum_EnumerateDevices( + HRESULT (*AppConfirmFn)(DDCAPS*, D3DDEVICEDESC*) ) +{ + g_fnAppConfirmFn = AppConfirmFn; + g_bRefRastEnumerated = FALSE; + + // We need to manually get the procedure address for the DDrawEnumEx() + // function. + HMODULE hDDrawDLL = GetModuleHandle("DDRAW.DLL"); + if( NULL == hDDrawDLL ) + { + DEBUG_MSG( TEXT("Can't load DDRAW.DLL!") ); + return D3DENUMERR_NODIRECTDRAW; + } + + // Find the DDraw enumeration function, and call it + LPDIRECTDRAWENUMERATEEX pDDrawEnumFn = (LPDIRECTDRAWENUMERATEEX) + GetProcAddress( hDDrawDLL, "DirectDrawEnumerateExA" ); + + if( pDDrawEnumFn ) + pDDrawEnumFn( DirectDrawEnumCallbackEx, NULL, + DDENUM_ATTACHEDSECONDARYDEVICES | + DDENUM_DETACHEDSECONDARYDEVICES | + DDENUM_NONDISPLAYDEVICES ); + else + DirectDrawEnumerate( DirectDrawEnumCallback, NULL ); + + // Select a driver. Ask for a hardware device that renders in a window + return D3DEnum_SelectDefaultDriver( NULL ); +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_SelectDefaultDriver() +// Desc: Picks a default driver according to the passed in flags. +//----------------------------------------------------------------------------- +HRESULT D3DEnum_SelectDefaultDriver( DWORD dwFlags ) +{ + // Refresh the list of devices to mark which devices (if any) are + // compatible with the current desktop (ie. can render in a window). + RefreshListForDesktopCompatibility(); + + // If a specific driver was requested, perform that search here + if( dwFlags & 0x0000003c ) + { + for( D3DEnum_DriverInfo* pDriver = g_pFirstDriver; pDriver; + pDriver = pDriver->pNext ) + { + for( D3DEnum_DeviceInfo* pDevice = pDriver->pFirstDevice; pDevice; + pDevice = pDevice->pNext ) + { + BOOL bFound = FALSE; + + if( IsEqualGUID( *pDevice->pGUID, IID_IDirect3DRGBDevice ) ) + { + if( dwFlags & D3DENUM_RGBEMULATION ) + bFound = TRUE; + } + else if( IsEqualGUID( *pDevice->pGUID, IID_IDirect3DRefDevice ) ) + { + if( dwFlags & D3DENUM_REFERENCERAST ) + bFound = TRUE; + } + else + { + if( dwFlags & D3DENUM_PRIMARYHAL ) + if( pDriver == g_pFirstDriver ) + bFound = TRUE; + if( dwFlags & D3DENUM_SECONDARYHAL ) + if( pDriver != g_pFirstDriver ) + bFound = TRUE; + } + + if( bFound ) + { + g_pCurrentDriver = pDriver; + g_pCurrentDriver->pCurrentDevice = pDevice; + return S_OK; + } + } + } + return D3DENUMERR_NOTFOUND; + } + + // Do 4 passes, looping through drivers, devices and modes. The 1st pass + // searches for hardware. The 2nd pass looks for software devices. The + // final two passes allow fullscreen modes. + for( WORD pass=0; pass<4; pass++ ) + { + BOOL bSeekHardware = ( pass & 0x1 ) ? FALSE : TRUE; + BOOL bSeekWindowed = ( pass & 0x2 ) ? FALSE : TRUE; + + // Skip the passes we aren't allowing + if( (TRUE==bSeekHardware) && (dwFlags&D3DENUM_SOFTWAREONLY) ) + continue; + if( (TRUE==bSeekWindowed) && (dwFlags&D3DENUM_FULLSCREENONLY) ) + continue; + + for( D3DEnum_DriverInfo* pDriver = g_pFirstDriver; pDriver; + pDriver = pDriver->pNext ) + { + DDCAPS* pCaps = &pDriver->ddDriverCaps; + + if( bSeekWindowed ) + if( 0 == ( pCaps->dwCaps2 & DDCAPS2_CANRENDERWINDOWED ) ) + continue; + + for( D3DEnum_DeviceInfo* pDevice = pDriver->pFirstDevice; pDevice; + pDevice = pDevice->pNext ) + { + if( bSeekHardware != pDevice->bIsHardware ) + continue; + if( bSeekWindowed && FALSE == pDevice->bCompatbileWithDesktop ) + continue; + + pDevice->bWindowed = bSeekWindowed; + g_pCurrentDriver = pDriver; + g_pCurrentDriver->pCurrentDevice = pDevice; + + return S_OK; + } + } + } + + // No compatible devices were found. Return an error code + if( FALSE == g_bDevicesEnumerated ) + return D3DENUMERR_ENUMERATIONFAILED; // Enumeration really did fail + if( FALSE == g_bRefRastEnumerated ) + return D3DENUMERR_SUGGESTREFRAST; // Suggest enabling the RefRast + + return D3DENUMERR_NOCOMPATIBLEDEVICES; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_UserDlgSelectDriver() +// Desc: Displays a dialog box for the user to select a driver/device/mode. +// The return values are akin to the Windows DialogBox() function. +//----------------------------------------------------------------------------- +INT D3DEnum_UserDlgSelectDriver( HWND hwndParent, BOOL bCurrentlyWindowed ) +{ + INT nResult = -1; + + // Check in case drivers weren't properly enumerated beforehand. + if( NULL == g_pCurrentDriver ) + return -1; + + // Refresh the list of devices to mark which devices (if any) are + // compatible with the current desktop (ie. can render in a window). + RefreshListForDesktopCompatibility(); + + // Match the current windowed-vs-fullscreen state + g_pCurrentDriver->pCurrentDevice->bWindowed = bCurrentlyWindowed; + + // Pop up a dialog box for the user's choice of driver/device/mode + HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndParent, + GWL_HINSTANCE ); + + // Create dynamic dialog template + DLGTEMPLATE* pDlgSelect = _BuildDriverSelectTemplate(); + if( pDlgSelect ) + { + // Create dialog box from template + nResult = DialogBoxIndirectParam( hInstance, pDlgSelect, hwndParent, + (DLGPROC)_DriverSelectProc, 0L ); + delete pDlgSelect; + } + + return nResult; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_GetSelectedDriver() +// Desc: Returns the currently selected driver, device, and display mode +//----------------------------------------------------------------------------- +HRESULT D3DEnum_GetSelectedDriver( LPGUID* ppDriverGUID, LPGUID* ppDeviceGUID, + LPDDSURFACEDESC2* ppddsd, BOOL* pbWindowed, + BOOL* pbIsHardware ) + +{ + // Check parans + if( (!ppDriverGUID) || (!ppDeviceGUID) ) + return E_INVALIDARG; + + // Abort if things weren't setup correctly + if( NULL == g_pCurrentDriver ) + return D3DENUMERR_ENUMERATIONFAILED; + + // Copy the driver and device GUID ptrs + (*ppDriverGUID) = g_pCurrentDriver->pGUID; + (*ppDeviceGUID) = g_pCurrentDriver->pCurrentDevice->pGUID; + + if( ppddsd ) + (*ppddsd) = &g_pCurrentDriver->pCurrentDevice->pCurrentMode->ddsd; + if( pbWindowed ) + (*pbWindowed) = g_pCurrentDriver->pCurrentDevice->bWindowed; + if( pbIsHardware ) + (*pbIsHardware) = g_pCurrentDriver->pCurrentDevice->bIsHardware; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_GetSelectedDriver() +// Desc: Returns the currently selected driver, device, and display mode +//----------------------------------------------------------------------------- +HRESULT D3DEnum_GetSelectedDriver( D3DEnum_DriverInfo** ppDriverInfo, + D3DEnum_DeviceInfo** ppDeviceInfo ) + +{ + // Abort if things weren't setup correctly + if( NULL == g_pCurrentDriver ) + return D3DENUMERR_ENUMERATIONFAILED; + + // Copy the driver and device info ptrs + if( ppDriverInfo ) *ppDriverInfo = g_pCurrentDriver; + if( ppDeviceInfo ) *ppDeviceInfo = g_pCurrentDriver->pCurrentDevice; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_GetFirstDriver() +// Desc: Returns a ptr to the first DriverInfo structure in the list. +//----------------------------------------------------------------------------- +D3DEnum_DriverInfo* D3DEnum_GetFirstDriver() +{ + return g_pFirstDriver; +} + + + + + diff --git a/arch/win32/d3dframe/d3denum.h b/arch/win32/d3dframe/d3denum.h new file mode 100644 index 00000000..63b71a74 --- /dev/null +++ b/arch/win32/d3dframe/d3denum.h @@ -0,0 +1,180 @@ +//----------------------------------------------------------------------------- +// File: D3DEnum.h +// +// Desc: Functions which enumerate through the DirectDraw drivers, Direct3D +// devices, and the display modes available to each device. +// +// +// Copyright (C) 1997 Microsoft Corporation. All rights reserved +//----------------------------------------------------------------------------- + + +#ifndef D3DENUM_H +#define D3DENUM_H + +#include +#include + + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_ModeInfo +// Desc: Linked-list structure to hold information about a display mode. This +// info is stored as a width, height, bpp, and pixelformat within a +// DDSURFACEDESC2. +//----------------------------------------------------------------------------- +struct D3DEnum_ModeInfo +{ + DDSURFACEDESC2 ddsd; + CHAR strDesc[40]; + D3DEnum_ModeInfo* pNext; +}; + + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_DeviceInfo +// Desc: Linked-list structure to hold information about a Direct3D device. The +// primary information recorded here is the D3DDEVICEDESC and a ptr to a +// linked-list of valid display modes. +//----------------------------------------------------------------------------- +struct D3DEnum_DeviceInfo +{ + GUID guid; + GUID* pGUID; + CHAR strName[40]; + D3DDEVICEDESC ddDesc; + BOOL bIsHardware; + BOOL bCompatbileWithDesktop; + BOOL bWindowed; + + D3DEnum_ModeInfo* pCurrentMode; + D3DEnum_ModeInfo* pFirstMode; + D3DEnum_DeviceInfo* pNext; +}; + + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_DriverInfo +// Desc: Linked-list structure to hold information about a DirectX driver. The +// info stored is the capability bits for the driver plus a linked-list +// of valid Direct3D devices for the driver. Note: most systems will only +// have one driver. The exception are multi-monitor systems, and systems +// with non-GDI 3D video cards. +//----------------------------------------------------------------------------- +struct D3DEnum_DriverInfo +{ + GUID guid; + GUID* pGUID; + CHAR strDesc[40]; + CHAR strName[40]; + DDCAPS ddDriverCaps; + DDCAPS ddHELCaps; + HANDLE hMonitor; + + D3DEnum_DeviceInfo* pCurrentDevice; + D3DEnum_DeviceInfo* pFirstDevice; + D3DEnum_DriverInfo* pNext; +}; + + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_EnumerateDevices() +// Desc: Enumerates all drivers, devices, and modes. The optional app-supplied +// callback is called for each enumerated device, to confirm that the +// device supports the feature set required by the app. +//----------------------------------------------------------------------------- +HRESULT D3DEnum_EnumerateDevices( + HRESULT (*AppConfirmFn)(DDCAPS*, D3DDEVICEDESC*) ); + + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_FreeResources() +// Desc: Frees all resources used for driver enumeration +//----------------------------------------------------------------------------- +VOID D3DEnum_FreeResources(); + + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_SelectDefaultDriver() +// Desc: Picks a driver based on a set of passed in criteria. +//----------------------------------------------------------------------------- +HRESULT D3DEnum_SelectDefaultDriver( DWORD dwFlags ); + +#define D3DENUM_SOFTWAREONLY 0x00000001 +#define D3DENUM_FULLSCREENONLY 0x00000002 +#define D3DENUM_RGBEMULATION 0x00000004 +#define D3DENUM_REFERENCERAST 0x00000008 +#define D3DENUM_PRIMARYHAL 0x00000010 +#define D3DENUM_SECONDARYHAL 0x00000020 + + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_UserDlgSelectDriver() +// Desc: Prompts the user with a dialog box, from which to choose a DD driver, +// D3D device, and compatible display mode. The function will return +// IDOK if a new driver/device/mode was selected, or IDCANCEL if not. +// Any error will result in a -1 for a return code. +//----------------------------------------------------------------------------- +INT D3DEnum_UserDlgSelectDriver( HWND hwndParent, BOOL bCurrentlyWindowed ); + + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_GetSelectedDriver() +// Desc: Returns the currently selected driver, device, and display mode. +//----------------------------------------------------------------------------- +HRESULT D3DEnum_GetSelectedDriver( LPGUID* ppDriverGUID, LPGUID* ppDeviceGuid, + LPDDSURFACEDESC2* pddsdDisplayMode = NULL, + BOOL* pbWindowed = NULL, + BOOL* pbIsHardware = NULL ); + + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_GetSelectedDriver() +// Desc: Returns the currently selected driver, device, and display mode. +//----------------------------------------------------------------------------- +HRESULT D3DEnum_GetSelectedDriver( D3DEnum_DriverInfo** ppDriverInfo, + D3DEnum_DeviceInfo** ppDeviceInfo ); + + + + +//----------------------------------------------------------------------------- +// Name: D3DEnum_GetFirstDriver() +// Desc: Returns a ptr to the first DriverInfo structure in the tree holding +// the device/driver/mode enumeration information. +//----------------------------------------------------------------------------- +D3DEnum_DriverInfo* D3DEnum_GetFirstDriver(); + + + + +//----------------------------------------------------------------------------- +// Error codes +//----------------------------------------------------------------------------- +#define D3DENUMERR_ENUMERATIONFAILED 0x81000001 // Enumeration failed +#define D3DENUMERR_SUGGESTREFRAST 0x81000002 // Suggest using the RefRast +#define D3DENUMERR_NOCOMPATIBLEDEVICES 0x81000003 // No devices were found that + // meet the app's desired + // capabilities +#define D3DENUMERR_NODIRECTDRAW 0x81000004 // DDraw couldn't initialize +#define D3DENUMERR_NOTFOUND 0x81000005 // Requested device not found + +#endif // D3DENUM_H + diff --git a/arch/win32/d3dframe/d3dframe.cpp b/arch/win32/d3dframe/d3dframe.cpp new file mode 100644 index 00000000..c0cba618 --- /dev/null +++ b/arch/win32/d3dframe/d3dframe.cpp @@ -0,0 +1,754 @@ +//----------------------------------------------------------------------------- +// File: D3DFrame.cpp +// +// Desc: Class to manage the Direct3D environment objects such as buffers, +// viewports, and 3D devices. +// +// The class is initialized with the Initialize() function, after which +// the Get????() functions can be used to access the objects needed for +// rendering. If the device or display needs to be changed, the +// ChangeDevice() function can be called. If the display window is moved +// the changes need to be reported with the Move() function. +// +// After rendering a frame, the ShowFrame() function filps or blits the +// backbuffer contents to the primary. If surfaces are lost, they can be +// restored with the RestoreSurfaces() function. Finally, if normal +// Windows output is needed, the FlipToGDISurface() provides a GDI +// surface to draw on. +// +// +// Copyright (c) 1995-1998 by Microsoft, all rights reserved +//----------------------------------------------------------------------------- + +#include +#include "D3DFrame.h" +#include "D3DUtil.h" + + + + +//----------------------------------------------------------------------------- +// Name: EnumZBufferFormatsCallback() +// Desc: Enumeration function to report valid pixel formats for z-buffers. +//----------------------------------------------------------------------------- +static HRESULT WINAPI EnumZBufferFormatsCallback( DDPIXELFORMAT* pddpf, + VOID* pddpfDesired ) +{ + if( NULL==pddpf || NULL==pddpfDesired ) + return D3DENUMRET_CANCEL; + + // If the current pixel format's match the desired ones (DDPF_ZBUFFER and + // possibly DDPF_STENCILBUFFER), lets copy it and return. This function is + // not choosy...it accepts the first valid format that comes along. + if( pddpf->dwFlags == ((DDPIXELFORMAT*)pddpfDesired)->dwFlags ) + { + memcpy( pddpfDesired, pddpf, sizeof(DDPIXELFORMAT) ); + + // We're happy with a 16-bit z-buffer. Otherwise, keep looking. + if( pddpf->dwZBufferBitDepth == 16 ) + return D3DENUMRET_CANCEL; + } + + return D3DENUMRET_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CD3DFramework() +// Desc: The constructor. Clears static variables +//----------------------------------------------------------------------------- +CD3DFramework::CD3DFramework() +{ + m_hWnd = NULL; + m_bIsFullscreen = FALSE; + m_dwRenderWidth = 0L; + m_dwRenderHeight = 0L; + m_pddsFrontBuffer = NULL; + m_pddsBackBuffer = NULL; + m_pddsRenderTarget = NULL; + m_pddsZBuffer = NULL; + m_pd3dDevice = NULL; + m_pvViewport = NULL; + m_pDD = NULL; + m_pD3D = NULL; + m_dwDeviceMemType = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: ~CD3DFramework() +// Desc: The destructor. Deletes all objects +//----------------------------------------------------------------------------- +CD3DFramework::~CD3DFramework() +{ + DestroyObjects(); +} + + + + +//----------------------------------------------------------------------------- +// Name: DestroyObjects() +// Desc: Cleans everything up upon deletion. This code returns an error +// if any of the objects have remaining reference counts. +//----------------------------------------------------------------------------- +HRESULT CD3DFramework::DestroyObjects() +{ + LONG nDD = 0L; // Number of outstanding DDraw references + LONG nD3D = 0L; // Number of outstanding D3DDevice references + + SAFE_RELEASE( m_pvViewport ); + + // Do a safe check for releasing the D3DDEVICE. RefCount must be zero. + if( m_pd3dDevice ) + if( 0 < ( nD3D = m_pd3dDevice->Release() ) ) + DEBUG_MSG( TEXT("Error: D3DDevice object is still referenced!") ); + m_pd3dDevice = NULL; + + // In windowed mode, release the explicity created backbuffer. + if( FALSE == m_bIsFullscreen ) + SAFE_RELEASE( m_pddsBackBuffer ); + SAFE_RELEASE( m_pddsRenderTarget ); //Note: release before frontbuffer + SAFE_RELEASE( m_pddsZBuffer ); + SAFE_RELEASE( m_pddsFrontBuffer ); + SAFE_RELEASE( m_pD3D ); + + // Do a safe check for releasing DDRAW. RefCount must be zero. + if( m_pDD ) + { + m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ); + + if( 0 < ( nDD = m_pDD->Release() ) ) + DEBUG_MSG( TEXT("Error: DDraw object is still referenced!") ); + } + m_pDD = NULL; + + // Return successful, unless there are outstanding DD or D3DDevice refs. + return ( nDD==0 && nD3D==0 ) ? S_OK : D3DFWERR_NONZEROREFCOUNT; +} + + + + +//----------------------------------------------------------------------------- +// Name: Initialize() +// Desc: Creates the internal objects for the framework +//----------------------------------------------------------------------------- +HRESULT CD3DFramework::Initialize( HWND hWnd, GUID* pDriverGUID, + GUID* pDeviceGUID, DDSURFACEDESC2* pMode, + DWORD dwFlags ) +{ + HRESULT hr; + + // Check params. A NULL mode is valid for windowed modes only. A NULL + // device GUID is legal for apps that only want 2D support. + if( NULL==hWnd || ( NULL==pMode && (dwFlags&D3DFW_FULLSCREEN) ) ) + return E_INVALIDARG; + + // Setup state for windowed/fullscreen mode + m_hWnd = hWnd; + m_bIsFullscreen = ( dwFlags & D3DFW_FULLSCREEN ) ? TRUE : FALSE; + + // Create the D3D rendering environment (surfaces, device, viewport, etc.) + if( FAILED( hr = CreateEnvironment( pDriverGUID, pDeviceGUID, pMode, + dwFlags ) ) ) + { + DestroyObjects(); + if( E_FAIL == hr ) + hr = D3DFWERR_INITIALIZATIONFAILED; + } + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateEnvironment() +// Desc: Creates the internal objects for the framework +//----------------------------------------------------------------------------- +HRESULT CD3DFramework::CreateEnvironment( GUID* pDriverGUID, GUID* pDeviceGUID, + DDSURFACEDESC2* pMode, DWORD dwFlags ) +{ + HRESULT hr; + + // Create the DDraw object + if( FAILED( hr = CreateDirectDraw( pDriverGUID, dwFlags ) ) ) + return hr; + + // Create the Direct3D object + if( pDeviceGUID ) + if( FAILED( hr = CreateDirect3D( pDeviceGUID, dwFlags ) ) ) + return hr; + + // Create the front and back buffers, and attach a clipper + if( FAILED( hr = CreateBuffers( pMode, dwFlags ) ) ) + return hr; + + // If there is no device GUID, then the app only wants 2D, so we're done + if( NULL == pDeviceGUID ) + return S_OK; + + // Create and attach the zbuffer + if( dwFlags & D3DFW_ZBUFFER ) + if( FAILED( hr = CreateZBuffer() ) ) + return hr; + + // Query the render buffer for the 3ddevice + if( FAILED( hr = Create3DDevice( pDeviceGUID ) ) ) + return hr; + + // Create and set the viewport + if( FAILED( hr = CreateViewport() ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateDirectDraw() +// Desc: Create the DirectDraw interface +//----------------------------------------------------------------------------- +HRESULT CD3DFramework::CreateDirectDraw( GUID* pDriverGUID, DWORD dwFlags ) +{ + // Create the DirectDraw interface, and query for the DD4 interface + LPDIRECTDRAW pDD; + if( FAILED( DirectDrawCreate( pDriverGUID, &pDD, NULL ) ) ) + { + DEBUG_MSG( TEXT("Could not create DirectDraw") ); + return D3DFWERR_NODIRECTDRAW; + } + + if( FAILED( pDD->QueryInterface( IID_IDirectDraw4, (VOID**)&m_pDD ) ) ) + { + pDD->Release(); + DEBUG_MSG( TEXT("Couldn't query for DirectDraw4") ); + return D3DFWERR_NODIRECTDRAW; + } + pDD->Release(); + + // Set the Windows cooperative level + DWORD dwCoopFlags = DDSCL_NORMAL; + if( m_bIsFullscreen ) + dwCoopFlags = DDSCL_ALLOWREBOOT|DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN; + + // By defualt, set the flag to allow D3D to optimize floating point calcs + if( 0L == ( dwFlags & D3DFW_NO_FPUSETUP ) ) + dwCoopFlags |= DDSCL_FPUSETUP; + + if( FAILED( m_pDD->SetCooperativeLevel( m_hWnd, dwCoopFlags ) ) ) + { + DEBUG_MSG( TEXT("Couldn't set coop level") ); + return D3DFWERR_COULDNTSETCOOPLEVEL; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateDirect3D() +// Desc: Create the Direct3D interface +//----------------------------------------------------------------------------- +HRESULT CD3DFramework::CreateDirect3D( GUID* pDeviceGUID, DWORD dwFlags ) +{ + // Query DirectDraw for access to Direct3D + if( FAILED( m_pDD->QueryInterface( IID_IDirect3D3, (VOID**)&m_pD3D ) ) ) + { + DEBUG_MSG( TEXT("Couldn't query the Direct3D interface") ); + return D3DFWERR_NODIRECT3D; + } + + // Use the FindDevice() method to test if the requested device + // exists, and if so, take note of what memory type it takes. + D3DFINDDEVICERESULT devResult; + D3DFINDDEVICESEARCH devSearch; + ZeroMemory( &devResult, sizeof(D3DFINDDEVICERESULT) ); + ZeroMemory( &devSearch, sizeof(D3DFINDDEVICESEARCH) ); + devResult.dwSize = sizeof(D3DFINDDEVICERESULT); + devSearch.dwSize = sizeof(D3DFINDDEVICESEARCH); + devSearch.dwFlags = D3DFDS_GUID; + CopyMemory( &devSearch.guid, pDeviceGUID, sizeof(GUID) ); + + if( FAILED( m_pD3D->FindDevice( &devSearch, &devResult ) ) ) + { + DEBUG_MSG( TEXT("Couldn't find the specified device") ); + return D3DFWERR_NODIRECT3D; + } + + // Whether device is SW or HW, get the devicedesc, and the defualt memtype + if( 0L == devResult.ddHwDesc.dwFlags ) + { + m_dwDeviceMemType = DDSCAPS_SYSTEMMEMORY; + memcpy( &m_ddDeviceDesc, &devResult.ddSwDesc, sizeof(D3DDEVICEDESC) ); + } + else + { + m_dwDeviceMemType = DDSCAPS_VIDEOMEMORY; + memcpy( &m_ddDeviceDesc, &devResult.ddHwDesc, sizeof(D3DDEVICEDESC) ); + } + + // Using the device GUID, let's enumerate a format for our z-buffer, in + // case we later decide to create one. + ZeroMemory( &m_ddpfZBuffer, sizeof(DDPIXELFORMAT) ); + + if( dwFlags & D3DFW_STENCILBUFFER ) + m_ddpfZBuffer.dwFlags = DDPF_ZBUFFER | DDPF_STENCILBUFFER; + else + m_ddpfZBuffer.dwFlags = DDPF_ZBUFFER; + + // Get an appropiate pixel format from enumeration of the formats. + m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback, + (VOID*)&m_ddpfZBuffer ); + + if( sizeof(DDPIXELFORMAT) != m_ddpfZBuffer.dwSize ) + { + DEBUG_MSG( TEXT("Device doesn't support requested zbuffer format") ); + return D3DFWERR_NOZBUFFER; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateBuffers() +// Desc: Creates the primary and (optional) backbuffer for rendering. +// Windowed mode and fullscreen mode are handled differently. +//----------------------------------------------------------------------------- +HRESULT CD3DFramework::CreateBuffers( DDSURFACEDESC2* pddsd, DWORD dwFlags ) +{ + HRESULT hr; + + if( dwFlags & D3DFW_FULLSCREEN ) + { + // Get the dimensions of the viewport and screen bounds + // Store the rectangle which contains the renderer + SetRect( &m_rcViewportRect, 0, 0, pddsd->dwWidth, pddsd->dwHeight ); + memcpy( &m_rcScreenRect, &m_rcViewportRect, sizeof(RECT) ); + m_dwRenderWidth = m_rcViewportRect.right; + m_dwRenderHeight = m_rcViewportRect.bottom; + + // Set the display mode to the requested dimensions. Check for + // 320x200x8 modes, and set flag to avoid using ModeX + DWORD dwModeFlags = 0; + + if( (320==m_dwRenderWidth) && (200==m_dwRenderHeight) && + (8==pddsd->ddpfPixelFormat.dwRGBBitCount) ) + dwModeFlags |= DDSDM_STANDARDVGAMODE; + + if( FAILED( m_pDD->SetDisplayMode( m_dwRenderWidth, m_dwRenderHeight, + pddsd->ddpfPixelFormat.dwRGBBitCount, + pddsd->dwRefreshRate, dwModeFlags ) ) ) + { + DEBUG_MSG( TEXT("Can't set display mode") ); + return D3DFWERR_BADDISPLAYMODE; + } + + // Create the primary surface + DDSURFACEDESC2 ddsd; + D3DUtil_InitSurfaceDesc( ddsd, DDSD_CAPS ); + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE; + + // With no backbuffer, the primary becomes the render target + if( dwFlags & D3DFW_BACKBUFFER ) + { + ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX; + ddsd.dwBackBufferCount = 1; + } + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) ) + { + DEBUG_MSG( TEXT("Error: Can't create primary surface") ); + if( hr != DDERR_OUTOFVIDEOMEMORY ) + return D3DFWERR_NOPRIMARY; + DEBUG_MSG( TEXT("Error: Out of video memory") ); + return DDERR_OUTOFVIDEOMEMORY; + } + + // Get the backbuffer. For fullscreen mode, the backbuffer was created + // along with the primary, but windowed mode still needs to create one. + if( dwFlags & D3DFW_BACKBUFFER ) + { + // Get a ptr to the back buffer, which will be our render target + DDSCAPS2 ddscaps; + ddscaps.dwCaps = DDSCAPS_BACKBUFFER; + if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps, + &m_pddsBackBuffer ) ) ) + { + DEBUG_MSG( TEXT("Error: Can't get/create the backbuffer") ); + if( hr != DDERR_OUTOFVIDEOMEMORY ) + return D3DFWERR_NOBACKBUFFER; + DEBUG_MSG( TEXT("Error: Out of video memory") ); + return DDERR_OUTOFVIDEOMEMORY; + } + } + } + else // Set up buffers for windowed rendering + { + // Get the dimensions of the viewport and screen bounds + GetClientRect( m_hWnd, &m_rcViewportRect ); + GetClientRect( m_hWnd, &m_rcScreenRect ); + ClientToScreen( m_hWnd, (POINT*)&m_rcScreenRect.left ); + ClientToScreen( m_hWnd, (POINT*)&m_rcScreenRect.right ); + m_dwRenderWidth = m_rcViewportRect.right; + m_dwRenderHeight = m_rcViewportRect.bottom; + + // Create the primary surface + DDSURFACEDESC2 ddsd; + D3DUtil_InitSurfaceDesc( ddsd, DDSD_CAPS ); + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + // With no backbuffer, the primary becomes the render target + if( 0L == ( dwFlags & D3DFW_BACKBUFFER ) ) + ddsd.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) ) + { + DEBUG_MSG( TEXT("Error: Can't create primary surface") ); + if( hr != DDERR_OUTOFVIDEOMEMORY ) + return D3DFWERR_NOPRIMARY; + DEBUG_MSG( TEXT("Error: Out of video memory") ); + return DDERR_OUTOFVIDEOMEMORY; + } + + // If in windowed-mode, create a clipper object + LPDIRECTDRAWCLIPPER pcClipper; + if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) ) + { + DEBUG_MSG( TEXT("Error: Couldn't create clipper") ); + return D3DFWERR_NOCLIPPER; + } + + // Associate the clipper with the window + pcClipper->SetHWnd( 0, m_hWnd ); + m_pddsFrontBuffer->SetClipper( pcClipper ); + SAFE_RELEASE( pcClipper ); + + // Get the backbuffer. For fullscreen mode, the backbuffer was created + // along with the primary, but windowed mode still needs to create one. + if( dwFlags & D3DFW_BACKBUFFER ) + { + // Create the back buffer (the render target) + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; + ddsd.dwWidth = m_dwRenderWidth; + ddsd.dwHeight = m_dwRenderHeight; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) ) + { + DEBUG_MSG( TEXT("Error: Couldn't create the backbuffer") ); + if( hr != DDERR_OUTOFVIDEOMEMORY ) + return D3DFWERR_NOBACKBUFFER; + DEBUG_MSG( TEXT("Error: Out of video memory") ); + return DDERR_OUTOFVIDEOMEMORY; + } + } + else // For rendering without a backbuffer + { + ClientToScreen( m_hWnd, (POINT*)&m_rcViewportRect.left ); + ClientToScreen( m_hWnd, (POINT*)&m_rcViewportRect.right ); + } + } + + // Set up backbuffer ptr and ref counts + if( dwFlags & D3DFW_BACKBUFFER ) + m_pddsRenderTarget = m_pddsBackBuffer; + else + m_pddsRenderTarget = m_pddsFrontBuffer; + m_pddsRenderTarget->AddRef(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateZBuffer() +// Desc: Internal function called by Create() to make and attach a zbuffer +// to the renderer +//----------------------------------------------------------------------------- +HRESULT CD3DFramework::CreateZBuffer() +{ + HRESULT hr; + + // Check if the device supports z-bufferless hidden surface removal. If so, + // we don't really need a z-buffer + DWORD dwRasterCaps = m_ddDeviceDesc.dpcTriCaps.dwRasterCaps; + if( dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR ) + return S_OK; + + // Get z-buffer dimensions from the render target + // Setup the surface desc for the z-buffer. + DDSURFACEDESC2 ddsd; + D3DUtil_InitSurfaceDesc( ddsd, DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | + DDSD_PIXELFORMAT ); + ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | m_dwDeviceMemType; + ddsd.dwWidth = m_dwRenderWidth; + ddsd.dwHeight = m_dwRenderHeight; + memcpy( &ddsd.ddpfPixelFormat, &m_ddpfZBuffer, sizeof(DDPIXELFORMAT) ); + + // Create and attach a z-buffer + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsZBuffer, NULL ) ) ) + { + DEBUG_MSG( TEXT("Error: Couldn't create a ZBuffer surface") ); + if( hr != DDERR_OUTOFVIDEOMEMORY ) + return D3DFWERR_NOZBUFFER; + DEBUG_MSG( TEXT("Error: Out of video memory") ); + return DDERR_OUTOFVIDEOMEMORY; + } + + if( FAILED( m_pddsRenderTarget->AddAttachedSurface( m_pddsZBuffer ) ) ) + { + DEBUG_MSG( TEXT("Error: Couldn't attach zbuffer to render surface") ); + return D3DFWERR_NOZBUFFER; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: Create3DDevice() +// Desc: Creates the 3D device for the render target +//----------------------------------------------------------------------------- +HRESULT CD3DFramework::Create3DDevice( GUID* pDeviceGUID ) +{ + // Check that we are NOT in a palettized display. That case will fail, + // since the framework doesn't use palettes. + DDSURFACEDESC2 ddsd; + ddsd.dwSize = sizeof(DDSURFACEDESC2); + m_pDD->GetDisplayMode( &ddsd ); + if( ddsd.ddpfPixelFormat.dwRGBBitCount <= 8 ) + return D3DFWERR_INVALIDMODE; + + // Create the device + if( FAILED( m_pD3D->CreateDevice( *pDeviceGUID, m_pddsRenderTarget, + &m_pd3dDevice, NULL ) ) ) + { + DEBUG_MSG( TEXT("Couldn't create the D3DDevice") ); + return D3DFWERR_NO3DDEVICE; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateViewport() +// Desc: Create the D3D viewport used by the renderer. +//----------------------------------------------------------------------------- +HRESULT CD3DFramework::CreateViewport() +{ + // Set up the viewport data parameters + HRESULT hr; + D3DVIEWPORT2 vdData; + D3DUtil_InitViewport( vdData, m_dwRenderWidth, m_dwRenderHeight ); + + // Create the viewport + if( FAILED( m_pD3D->CreateViewport( &m_pvViewport, NULL ) ) ) + { + DEBUG_MSG( TEXT("Error: Couldn't create a viewport") ); + return D3DFWERR_NOVIEWPORT; + } + + // Associate the viewport with the D3DDEVICE object + if( FAILED( hr = m_pd3dDevice->AddViewport( m_pvViewport ) ) ) + { + DEBUG_MSG( TEXT("Error: Couldn't add the viewport") ); + return D3DFWERR_NOVIEWPORT; + } + + // Set the parameters to the new viewport + if( FAILED( m_pvViewport->SetViewport2( &vdData ) ) ) + { + DEBUG_MSG( TEXT("Error: Couldn't set the viewport data") ); + return D3DFWERR_NOVIEWPORT; + } + + // Finally, set the current viewport for the current device + if( FAILED( m_pd3dDevice->SetCurrentViewport( m_pvViewport ) ) ) + { + DEBUG_MSG( TEXT("Error: Couldn't set current viewport to device") ); + return D3DFWERR_NOVIEWPORT; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: ShowFrame() +// Desc: Show the frame on the primary surface, via a blt or a flip. +//----------------------------------------------------------------------------- +HRESULT CD3DFramework::ShowFrame() +{ + if( NULL == m_pddsFrontBuffer ) + return D3DFWERR_NOTINITIALIZED; + + // Check for a backbuffer. If no backbuffer exists, then we have nothing to + // do. However, to be consistent let's check for lost surfaces + if( NULL == m_pddsBackBuffer ) + return m_pddsFrontBuffer->IsLost(); + + // If we are in fullscreen mode perform a flip. + if( m_bIsFullscreen ) + return m_pddsFrontBuffer->Flip( NULL, DDFLIP_WAIT ); + + // Else, we are in windowed mode, so perform a blit. + return m_pddsFrontBuffer->Blt( &m_rcScreenRect, m_pddsBackBuffer, + &m_rcViewportRect, DDBLT_WAIT, NULL ); +} + + + + +//----------------------------------------------------------------------------- +// Name: FlipToGDISurface() +// Desc: Puts the GDI surface in front of the primary, so that dialog +// boxes and other windows drawing funcs may happen. +//----------------------------------------------------------------------------- +HRESULT CD3DFramework::FlipToGDISurface( BOOL bDrawFrame ) +{ + if( m_pDD && m_bIsFullscreen ) + { + m_pDD->FlipToGDISurface(); + + if( bDrawFrame ) + { + DrawMenuBar( m_hWnd ); + RedrawWindow( m_hWnd, NULL, NULL, RDW_FRAME ); + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: RestoreSurfaces() +// Desc: Checks for lost surfaces and restores them if lost. Note: Don't +// restore render surface, since it's just a duplicate ptr. +//----------------------------------------------------------------------------- +HRESULT CD3DFramework::RestoreSurfaces() +{ + // Check/restore the primary surface + if( m_pddsFrontBuffer ) + if( m_pddsFrontBuffer->IsLost() ) + m_pddsFrontBuffer->Restore(); + + // Check/restore the back buffer + if( m_pddsBackBuffer ) + if( m_pddsBackBuffer->IsLost() ) + m_pddsBackBuffer->Restore(); + + // Check/restore the z-buffer surface + if( m_pddsZBuffer ) + if( m_pddsZBuffer->IsLost() ) + m_pddsZBuffer->Restore(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: Move() +// Desc: Moves the screen rect for windowed renderers +//----------------------------------------------------------------------------- +VOID CD3DFramework::Move( INT x, INT y ) +{ + if( FALSE == m_bIsFullscreen ) + { + SetRect( &m_rcScreenRect, x, y, + x + m_dwRenderWidth, y + m_dwRenderHeight ); + + // If we have no backbuffer, then update viewport rect as well + if( NULL == m_pddsBackBuffer ) + CopyMemory( &m_rcViewportRect, &m_rcScreenRect, sizeof(RECT) ); + } +} + + + + +//----------------------------------------------------------------------------- +// Name: ChangeRenderTarget() +// Desc: Wrapper for the IDirect3DDevice::SetRenderTarget() function, which +// adds functionality to handle an attached z-buffer. Note that this +// function does NOT alter the current viewport +//----------------------------------------------------------------------------- +HRESULT CD3DFramework::ChangeRenderTarget( LPDIRECTDRAWSURFACE4 pddsNewTarget ) +{ + if( NULL == pddsNewTarget ) + return E_INVALIDARG; + + // Get the new render target dimensions + DDSURFACEDESC2 ddsd; + D3DUtil_InitSurfaceDesc( ddsd ); + pddsNewTarget->GetSurfaceDesc( &ddsd ); + m_dwRenderWidth = ddsd.dwWidth; + m_dwRenderHeight = ddsd.dwHeight; + + // If a z-buffer is attached, delete and recreate it + if( NULL != m_pddsZBuffer ) + { + // Remove the old z-buffer + m_pddsRenderTarget->DeleteAttachedSurface( 0, m_pddsZBuffer ); + SAFE_RELEASE( m_pddsZBuffer ); + + // Keep track of reference counts + SAFE_RELEASE( m_pddsRenderTarget ); + m_pddsRenderTarget = pddsNewTarget; + m_pddsRenderTarget->AddRef(); + + // Create the new z-buffer + if( FAILED( CreateZBuffer() ) ) + { + DEBUG_MSG( TEXT("ChangeRenderTarget() - zbuffer create failed") ); + return D3DFWERR_NOZBUFFER; + } + } + else + { + // With no z-buffer, we just do accounting on the reference counts + SAFE_RELEASE( m_pddsRenderTarget ); + m_pddsRenderTarget = pddsNewTarget; + m_pddsRenderTarget->AddRef(); + } + + // Finally, perform the set render target call + if( FAILED( m_pd3dDevice->SetRenderTarget( m_pddsRenderTarget, 0 ) ) ) + { + return D3DFWERR_NORENDERTARGET; + } + + return S_OK; +} + + + + + diff --git a/arch/win32/d3dframe/d3dframe.h b/arch/win32/d3dframe/d3dframe.h new file mode 100644 index 00000000..ec41be5c --- /dev/null +++ b/arch/win32/d3dframe/d3dframe.h @@ -0,0 +1,136 @@ +//----------------------------------------------------------------------------- +// File: D3DFrame.h +// +// Desc: Class to manage the Direct3D environment objects such as buffers, +// viewports, and 3D devices. +// +// The class is initialized with the Initialize() function, after which +// the Get????() functions can be used to access the objects needed for +// rendering. If the device or display needs to be changed, the +// ChangeDevice() function can be called. If the display window is moved +// the changes need to be reported with the Move() function. +// +// After rendering a frame, the ShowFrame() function filps or blits the +// backbuffer contents to the primary. If surfaces are lost, they can be +// restored with the RestoreSurfaces() function. Finally, if normal +// Windows output is needed, the FlipToGDISurface() provides a GDI +// surface to draw on. +// +// +// Copyright (C) 1997 Microsoft Corporation. All rights reserved +//----------------------------------------------------------------------------- + + +#ifndef D3DFRAME_H +#define D3DFRAME_H + +#include +#include + + + + +//----------------------------------------------------------------------------- +// Name: CD3DFramework +// Desc: The Direct3D sample framework class. Maintains the D3D surfaces, +// device, and viewport used for 3D rendering. +//----------------------------------------------------------------------------- +class CD3DFramework +{ + // Internal variables for the framework class + HWND m_hWnd; // The window object + BOOL m_bIsFullscreen; // Fullscreen vs. windowed + RECT m_rcViewportRect; // Offscreen rect for VPort + LPDIRECTDRAWSURFACE4 m_pddsFrontBuffer; // The primary surface + LPDIRECTDRAWSURFACE4 m_pddsBackBuffer; // The backbuffer surface + LPDIRECTDRAWSURFACE4 m_pddsRenderTarget; // The render target surface + LPDIRECTDRAWSURFACE4 m_pddsZBuffer; // The zbuffer surface + LPDIRECT3DDEVICE3 m_pd3dDevice; // The D3D device + LPDIRECT3DVIEWPORT3 m_pvViewport; // The D3D viewport + LPDIRECTDRAW4 m_pDD; // The DirectDraw object + LPDIRECT3D3 m_pD3D; // The Direct3D object + D3DDEVICEDESC m_ddDeviceDesc; + DWORD m_dwDeviceMemType; + DDPIXELFORMAT m_ddpfZBuffer; // Enumerated zbuffer format + + // Internal functions for the framework class + HRESULT CreateViewport(); + HRESULT Create3DDevice( GUID* ); + HRESULT CreateZBuffer(); + HRESULT CreateBuffers( DDSURFACEDESC2*, DWORD ); + HRESULT CreateDirectDraw( GUID*, DWORD ); + HRESULT CreateDirect3D( GUID*, DWORD ); + HRESULT CreateEnvironment( GUID*, GUID*, DDSURFACEDESC2*, DWORD ); + +public: + DWORD m_dwRenderWidth; // Dimensions of the render target + DWORD m_dwRenderHeight; + RECT m_rcScreenRect; // Screen rect for window + + // Access functions for DirectX objects + LPDIRECTDRAW4 GetDirectDraw() { return m_pDD; } + LPDIRECT3D3 GetDirect3D() { return m_pD3D; } + LPDIRECT3DDEVICE3 GetD3DDevice() { return m_pd3dDevice; } + LPDIRECT3DVIEWPORT3 GetViewport() { return m_pvViewport; } + LPDIRECTDRAWSURFACE4 GetFrontBuffer() { return m_pddsFrontBuffer; } + LPDIRECTDRAWSURFACE4 GetBackBuffer() { return m_pddsBackBuffer; } + LPDIRECTDRAWSURFACE4 GetRenderSurface() { return m_pddsRenderTarget; } + + // Functions to aid rendering + HRESULT RestoreSurfaces(); + HRESULT ShowFrame(); + HRESULT FlipToGDISurface( BOOL bDrawFrame ); + + // Functions for managing screen and viewport bounds + BOOL IsFullscreen() { return m_bIsFullscreen; } + RECT* GetViewportRect() { return &m_rcViewportRect; } + VOID Move( INT x, INT y ); + + // Functions to support sprite-based rendering + HRESULT ChangeRenderTarget( LPDIRECTDRAWSURFACE4 pddsNewTarget ); + + // Creates the Framework + HRESULT Initialize( HWND hWnd, GUID* pDriverGUID, GUID* pDeviceGUID, + DDSURFACEDESC2* pddsd, DWORD dwFlags ); + HRESULT DestroyObjects(); + + CD3DFramework(); + ~CD3DFramework(); +}; + + + + +//----------------------------------------------------------------------------- +// Flags used for the Initialize() method of a CD3DFramework object +//----------------------------------------------------------------------------- +#define D3DFW_FULLSCREEN 0x00000001 // Use fullscreen mode +#define D3DFW_BACKBUFFER 0x00000002 // Create and use a backbuffer +#define D3DFW_ZBUFFER 0x00000004 // Create and use a zbuffer +#define D3DFW_STENCILBUFFER 0x00000008 // Use a z-buffer w/stenciling +#define D3DFW_NO_FPUSETUP 0x00000010 // Don't use default DDSCL_FPUSETUP flag + + + +//----------------------------------------------------------------------------- +// Errors that the Initialize() and ChangeDriver() calls may return +//----------------------------------------------------------------------------- +#define D3DFWERR_INITIALIZATIONFAILED 0x82000000 +#define D3DFWERR_NODIRECTDRAW 0x82000001 +#define D3DFWERR_COULDNTSETCOOPLEVEL 0x82000002 +#define D3DFWERR_NODIRECT3D 0x82000003 +#define D3DFWERR_NO3DDEVICE 0x82000004 +#define D3DFWERR_NOZBUFFER 0x82000005 +#define D3DFWERR_NOVIEWPORT 0x82000006 +#define D3DFWERR_NOPRIMARY 0x82000007 +#define D3DFWERR_NOCLIPPER 0x82000008 +#define D3DFWERR_BADDISPLAYMODE 0x82000009 +#define D3DFWERR_NOBACKBUFFER 0x8200000a +#define D3DFWERR_NONZEROREFCOUNT 0x8200000b +#define D3DFWERR_NORENDERTARGET 0x8200000c +#define D3DFWERR_INVALIDMODE 0x8200000d +#define D3DFWERR_NOTINITIALIZED 0x8200000e + + +#endif // D3DFRAME_H + diff --git a/arch/win32/d3dframe/d3dmath.cpp b/arch/win32/d3dframe/d3dmath.cpp new file mode 100644 index 00000000..4d2d50eb --- /dev/null +++ b/arch/win32/d3dframe/d3dmath.cpp @@ -0,0 +1,341 @@ +//----------------------------------------------------------------------------- +// File: D3DMath.cpp +// +// Desc: Shortcut macros and functions for using DX objects +// +// +// Copyright (c) 1997-1998 Microsoft Corporation. All rights reserved +//----------------------------------------------------------------------------- + +#define D3D_OVERLOADS +#include +#include +#include "D3DMath.h" + + + + +//----------------------------------------------------------------------------- +// Name: D3DMath_MatrixMultiply() +// Desc: Does the matrix operation: [Q] = [A] * [B]. +//----------------------------------------------------------------------------- +VOID D3DMath_MatrixMultiply( D3DMATRIX& q, D3DMATRIX& a, D3DMATRIX& b ) +{ + FLOAT* pA = (FLOAT*)&a; + FLOAT* pB = (FLOAT*)&b; + FLOAT pM[16]; + + ZeroMemory( pM, sizeof(D3DMATRIX) ); + + for( WORD i=0; i<4; i++ ) + for( WORD j=0; j<4; j++ ) + for( WORD k=0; k<4; k++ ) + pM[4*i+j] += pA[4*k+j] * pB[4*i+k]; + + memcpy( &q, pM, sizeof(D3DMATRIX) ); +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DMath_MatrixInvert() +// Desc: Does the matrix operation: [Q] = inv[A]. Note: this function only +// works for matrices with [0 0 0 1] for the 4th column. +//----------------------------------------------------------------------------- +HRESULT D3DMath_MatrixInvert( D3DMATRIX& q, D3DMATRIX& a ) +{ + if( fabs(a._44 - 1.0f) > .001f) + return E_INVALIDARG; + if( fabs(a._14) > .001f || fabs(a._24) > .001f || fabs(a._34) > .001f ) + return E_INVALIDARG; + + FLOAT fDetInv = 1.0f / ( a._11 * ( a._22 * a._33 - a._23 * a._32 ) - + a._12 * ( a._21 * a._33 - a._23 * a._31 ) + + a._13 * ( a._21 * a._32 - a._22 * a._31 ) ); + + q._11 = fDetInv * ( a._22 * a._33 - a._23 * a._32 ); + q._12 = -fDetInv * ( a._12 * a._33 - a._13 * a._32 ); + q._13 = fDetInv * ( a._12 * a._23 - a._13 * a._22 ); + q._14 = 0.0f; + + q._21 = -fDetInv * ( a._21 * a._33 - a._23 * a._31 ); + q._22 = fDetInv * ( a._11 * a._33 - a._13 * a._31 ); + q._23 = -fDetInv * ( a._11 * a._23 - a._13 * a._21 ); + q._24 = 0.0f; + + q._31 = fDetInv * ( a._21 * a._32 - a._22 * a._31 ); + q._32 = -fDetInv * ( a._11 * a._32 - a._12 * a._31 ); + q._33 = fDetInv * ( a._11 * a._22 - a._12 * a._21 ); + q._34 = 0.0f; + + q._41 = -( a._41 * q._11 + a._42 * q._21 + a._43 * q._31 ); + q._42 = -( a._41 * q._12 + a._42 * q._22 + a._43 * q._32 ); + q._43 = -( a._41 * q._13 + a._42 * q._23 + a._43 * q._33 ); + q._44 = 1.0f; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DMath_VectorMatrixMultiply() +// Desc: Multiplies a vector by a matrix +//----------------------------------------------------------------------------- +HRESULT D3DMath_VectorMatrixMultiply( D3DVECTOR& vDest, D3DVECTOR& vSrc, + D3DMATRIX& mat) +{ + FLOAT x = vSrc.x*mat._11 + vSrc.y*mat._21 + vSrc.z* mat._31 + mat._41; + FLOAT y = vSrc.x*mat._12 + vSrc.y*mat._22 + vSrc.z* mat._32 + mat._42; + FLOAT z = vSrc.x*mat._13 + vSrc.y*mat._23 + vSrc.z* mat._33 + mat._43; + FLOAT w = vSrc.x*mat._14 + vSrc.y*mat._24 + vSrc.z* mat._34 + mat._44; + + if( fabs( w ) < g_EPSILON ) + return E_INVALIDARG; + + vDest.x = x/w; + vDest.y = y/w; + vDest.z = z/w; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DMath_VertexMatrixMultiply() +// Desc: Multiplies a vertex by a matrix +//----------------------------------------------------------------------------- +HRESULT D3DMath_VertexMatrixMultiply( D3DVERTEX& vDest, D3DVERTEX& vSrc, + D3DMATRIX& mat ) +{ + HRESULT hr; + D3DVECTOR* pSrcVec = (D3DVECTOR*)&vSrc.x; + D3DVECTOR* pDestVec = (D3DVECTOR*)&vDest.x; + + if( SUCCEEDED( hr = D3DMath_VectorMatrixMultiply( *pDestVec, *pSrcVec, + mat ) ) ) + { + pSrcVec = (D3DVECTOR*)&vSrc.nx; + pDestVec = (D3DVECTOR*)&vDest.nx; + hr = D3DMath_VectorMatrixMultiply( *pDestVec, *pSrcVec, mat ); + } + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DMath_QuaternionFromRotation() +// Desc: Converts a normalized axis and angle to a unit quaternion. +//----------------------------------------------------------------------------- +VOID D3DMath_QuaternionFromRotation( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w, + D3DVECTOR& v, FLOAT fTheta ) +{ + x = (FLOAT)sin(fTheta/2) * v.x; + y = (FLOAT)sin(fTheta/2) * v.y; + z = (FLOAT)sin(fTheta/2) * v.z; + w = (FLOAT)cos(fTheta/2); +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DMath_RotationFromQuaternion() +// Desc: Converts a normalized axis and angle to a unit quaternion. +//----------------------------------------------------------------------------- +VOID D3DMath_RotationFromQuaternion( D3DVECTOR& v, FLOAT& fTheta, + FLOAT x, FLOAT y, FLOAT z, FLOAT w ) + +{ + fTheta = (FLOAT)( acos(w) * 2 ); + v.x = (FLOAT)( x / sin(fTheta/2) ); + v.y = (FLOAT)( y / sin(fTheta/2) ); + v.z = (FLOAT)( z / sin(fTheta/2) ); +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DMath_QuaternionFromAngles() +// Desc: Converts euler angles to a unit quaternion. +//----------------------------------------------------------------------------- +VOID D3DMath_QuaternionFromAngles( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w, + FLOAT fYaw, FLOAT fPitch, FLOAT fRoll ) + +{ + FLOAT fSinYaw = (FLOAT)sin(fYaw/2); + FLOAT fSinPitch = (FLOAT)sin(fPitch/2); + FLOAT fSinRoll = (FLOAT)sin(fRoll/2); + FLOAT fCosYaw = (FLOAT)cos(fYaw/2); + FLOAT fCosPitch = (FLOAT)cos(fPitch/2); + FLOAT fCosRoll = (FLOAT)cos(fRoll/2); + + x = fSinRoll * fCosPitch * fCosYaw - fCosRoll * fSinPitch * fSinYaw; + y = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw; + z = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw; + w = fCosRoll * fCosPitch * fCosYaw + fSinRoll * fSinPitch * fSinYaw; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DMath_MatrixFromQuaternion() +// Desc: Converts a unit quaternion into a rotation matrix. +//----------------------------------------------------------------------------- +VOID D3DMath_MatrixFromQuaternion( D3DMATRIX& mat, FLOAT x, FLOAT y, FLOAT z, + FLOAT w ) +{ + FLOAT xx = x*x; FLOAT yy = y*y; FLOAT zz = z*z; + FLOAT xy = x*y; FLOAT xz = x*z; FLOAT yz = y*z; + FLOAT wx = w*x; FLOAT wy = w*y; FLOAT wz = w*z; + + mat._11 = 1 - 2 * ( yy + zz ); + mat._12 = 2 * ( xy - wz ); + mat._13 = 2 * ( xz + wy ); + + mat._21 = 2 * ( xy + wz ); + mat._22 = 1 - 2 * ( xx + zz ); + mat._23 = 2 * ( yz - wx ); + + mat._31 = 2 * ( xz - wy ); + mat._32 = 2 * ( yz + wx ); + mat._33 = 1 - 2 * ( xx + yy ); + + mat._14 = mat._24 = mat._34 = 0.0f; + mat._41 = mat._42 = mat._43 = 0.0f; + mat._44 = 1.0f; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DMath_QuaternionFromMatrix() +// Desc: Converts a rotation matrix into a unit quaternion. +//----------------------------------------------------------------------------- +VOID D3DMath_QuaternionFromMatrix( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w, + D3DMATRIX& mat ) +{ + if( mat._11 + mat._22 + mat._33 > 0.0f ) + { + FLOAT s = (FLOAT)sqrt( mat._11 + mat._22 + mat._33 + mat._44 ); + + x = (mat._23-mat._32) / (2*s); + y = (mat._31-mat._13) / (2*s); + z = (mat._12-mat._21) / (2*s); + w = 0.5f * s; + } + else + { + + + } + FLOAT xx = x*x; FLOAT yy = y*y; FLOAT zz = z*z; + FLOAT xy = x*y; FLOAT xz = x*z; FLOAT yz = y*z; + FLOAT wx = w*x; FLOAT wy = w*y; FLOAT wz = w*z; + + mat._11 = 1 - 2 * ( yy + zz ); + mat._12 = 2 * ( xy - wz ); + mat._13 = 2 * ( xz + wy ); + + mat._21 = 2 * ( xy + wz ); + mat._22 = 1 - 2 * ( xx + zz ); + mat._23 = 2 * ( yz - wx ); + + mat._31 = 2 * ( xz - wy ); + mat._32 = 2 * ( yz + wx ); + mat._33 = 1 - 2 * ( xx + yy ); + + mat._14 = mat._24 = mat._34 = 0.0f; + mat._41 = mat._42 = mat._43 = 0.0f; + mat._44 = 1.0f; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DMath_QuaternionMultiply() +// Desc: Mulitples two quaternions together as in {Q} = {A} * {B}. +//----------------------------------------------------------------------------- +VOID D3DMath_QuaternionMultiply( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw, + FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw, + FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw ) +{ + FLOAT Dx = Bw*Ax + Bx*Aw + By*Az + Bz*Ay; + FLOAT Dy = Bw*Ay + By*Aw + Bz*Ax + Bx*Az; + FLOAT Dz = Bw*Az + Bz*Aw + Bx*Ay + By*Ax; + FLOAT Dw = Bw*Aw + Bx*Ax + By*Ay + Bz*Az; + + Qx = Dx; Qy = Dy; Qz = Dz; Qw = Dw; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DMath_SlerpQuaternions() +// Desc: Compute a quaternion which is the spherical linear interpolation +// between two other quaternions by dvFraction. +//----------------------------------------------------------------------------- +VOID D3DMath_QuaternionSlerp( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw, + FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw, + FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw, + FLOAT fAlpha ) +{ + FLOAT fScale1; + FLOAT fScale2; + + // Compute dot product, aka cos(theta): + FLOAT fCosTheta = Ax*Bx + Ay*By + Az*Bz + Aw*Bw; + + if( fCosTheta < 0.0f ) + { + // Flip start quaternion + Ax = -Ax; Ay = -Ay; Ax = -Az; Aw = -Aw; + fCosTheta = -fCosTheta; + } + + if( fCosTheta + 1.0f > 0.05f ) + { + // If the quaternions are close, use linear interploation + if( 1.0f - fCosTheta < 0.05f ) + { + fScale1 = 1.0f - fAlpha; + fScale2 = fAlpha; + } + else // Otherwise, do spherical interpolation + { + FLOAT fTheta = (FLOAT)acos( fCosTheta ); + FLOAT fSinTheta = (FLOAT)sin( fTheta ); + + fScale1 = (FLOAT)sin( fTheta * (1.0f-fAlpha) ) / fSinTheta; + fScale2 = (FLOAT)sin( fTheta * fAlpha ) / fSinTheta; + } + } + else + { + Bx = -Ay; + By = Ax; + Bz = -Aw; + Bw = Az; + fScale1 = (FLOAT)sin( g_PI * (0.5f - fAlpha) ); + fScale2 = (FLOAT)sin( g_PI * fAlpha ); + } + + Qx = fScale1 * Ax + fScale2 * Bx; + Qy = fScale1 * Ay + fScale2 * By; + Qz = fScale1 * Az + fScale2 * Bz; + Qw = fScale1 * Aw + fScale2 * Bw; +} + + + diff --git a/arch/win32/d3dframe/d3dmath.h b/arch/win32/d3dframe/d3dmath.h new file mode 100644 index 00000000..9532a47f --- /dev/null +++ b/arch/win32/d3dframe/d3dmath.h @@ -0,0 +1,85 @@ +//----------------------------------------------------------------------------- +// File: D3DMath.h +// +// Desc: Math functions and shortcuts for Direct3D programming. +// +// +// Copyright (C) 1997 Microsoft Corporation. All rights reserved +//----------------------------------------------------------------------------- + +#ifndef D3DMATH_H +#define D3DMATH_H + +#include +#include + + +//----------------------------------------------------------------------------- +// Useful Math constants +//----------------------------------------------------------------------------- +const FLOAT g_PI = 3.14159265358979323846f; // Pi +const FLOAT g_2_PI = 6.28318530717958623200f; // 2 * Pi +const FLOAT g_PI_DIV_2 = 1.57079632679489655800f; // Pi / 2 +const FLOAT g_PI_DIV_4 = 0.78539816339744827900f; // Pi / 4 +const FLOAT g_INV_PI = 0.31830988618379069122f; // 1 / Pi +const FLOAT g_DEGTORAD = 0.01745329251994329547f; // Degrees to Radians +const FLOAT g_RADTODEG = 57.29577951308232286465f; // Radians to Degrees +const FLOAT g_HUGE = 1.0e+38f; // Huge number for FLOAT +const FLOAT g_EPSILON = 1.0e-5f; // Tolerance for FLOATs + + + + +//----------------------------------------------------------------------------- +// Fuzzy compares (within tolerance) +//----------------------------------------------------------------------------- +inline BOOL D3DMath_IsZero( FLOAT a, FLOAT fTol = g_EPSILON ) +{ return ( a <= 0.0f ) ? ( a >= -fTol ) : ( a <= fTol ); } + + + + +//----------------------------------------------------------------------------- +// Matrix functions +//----------------------------------------------------------------------------- +VOID D3DMath_MatrixMultiply( D3DMATRIX& q, D3DMATRIX& a, D3DMATRIX& b ); +HRESULT D3DMath_MatrixInvert( D3DMATRIX& q, D3DMATRIX& a ); + + + + +//----------------------------------------------------------------------------- +// Vector functions +//----------------------------------------------------------------------------- +HRESULT D3DMath_VectorMatrixMultiply( D3DVECTOR& vDest, D3DVECTOR& vSrc, + D3DMATRIX& mat); +HRESULT D3DMath_VertexMatrixMultiply( D3DVERTEX& vDest, D3DVERTEX& vSrc, + D3DMATRIX& mat ); + + + + +//----------------------------------------------------------------------------- +// Quaternion functions +//----------------------------------------------------------------------------- +VOID D3DMath_QuaternionFromRotation( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w, + D3DVECTOR& v, FLOAT fTheta ); +VOID D3DMath_RotationFromQuaternion( D3DVECTOR& v, FLOAT& fTheta, + FLOAT x, FLOAT y, FLOAT z, FLOAT w ); +VOID D3DMath_QuaternionFromAngles( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w, + FLOAT fYaw, FLOAT fPitch, FLOAT fRoll ); +VOID D3DMath_MatrixFromQuaternion( D3DMATRIX& mat, FLOAT x, FLOAT y, FLOAT z, + FLOAT w ); +VOID D3DMath_QuaternionFromMatrix( FLOAT &x, FLOAT &y, FLOAT &z, FLOAT &w, + D3DMATRIX& mat ); +VOID D3DMath_QuaternionMultiply( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw, + FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw, + FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw ); +VOID D3DMath_QuaternionSlerp( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw, + FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw, + FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw, + FLOAT fAlpha ); + + +#endif // D3DMATH_H + diff --git a/arch/win32/d3dframe/d3dtextr.cpp b/arch/win32/d3dframe/d3dtextr.cpp new file mode 100644 index 00000000..901dae91 --- /dev/null +++ b/arch/win32/d3dframe/d3dtextr.cpp @@ -0,0 +1,788 @@ +//----------------------------------------------------------------------------- +// File: D3DTextr.cpp +// +// Desc: This file contains the member functions for the +// CD3DTextureEngine class. The class is responsible for loading and +// creating textures from files, as well as retrieving the +// corresponding ptrs and surfaces for the textures, given a +// texture's name. +// +// +// Copyright (c) 1996-1998 Microsoft Corporation. All rights reserved +//----------------------------------------------------------------------------- + +#include +#include +#include "D3DTextr.h" +#include "D3DUtil.h" + + + +//----------------------------------------------------------------------------- +// Name: TextureContainer +// Desc: Linked list tructure to hold info per texture +//----------------------------------------------------------------------------- +struct TextureContainer +{ + HBITMAP hbmBitmap; // Bitmap containing texture image + LPDIRECTDRAWSURFACE4 pddsSurface; // Surface of the texture + LPDIRECT3DTEXTURE2 ptexTexture; // Direct3D texture for the texture + DWORD dwStage; // Texture stage (for multi-textures) + TCHAR strName[80]; // Filename of assoc'd bitmap + BOOL bHasAlpha; + DWORD dwFlags; + + BYTE* pSurfaceBits[10]; + DDSURFACEDESC2 ddsd; + + TextureContainer *pPrev, *pNext; // Ptr to next texture in linked list + + ~TextureContainer(); +}; + + + + +//----------------------------------------------------------------------------- +// Macros, function prototypes and static variable +//----------------------------------------------------------------------------- +#define FOREACHTEXTURE(ptc) for( TextureContainer* ptc=g_ptcTextureList; \ + NULL!=ptc; ptc=ptc->pNext ) +inline BOOL FileExists( TCHAR* n ) +{ FILE* fp=_tfopen(n,TEXT("rb")); return fp?(0==fclose(fp)):FALSE; } + +static TextureContainer* g_ptcTextureList = NULL; // Textures list +static TCHAR g_strTexturePath[512] = TEXT("MEDIA\\"); // Path for files +static TCHAR* g_strRegValueName = TEXT("DX6SDK Samples Path"); + + + + +struct TEXTURESEARCHINFO +{ + DWORD dwDesiredBPP; // Input for texture format search + BOOL bUseAlpha; + BOOL bUsePalette; + BOOL bUseFourCC; + BOOL bFoundGoodFormat; + + DDPIXELFORMAT* pddpf; // Result of texture format search +}; + + + + +//----------------------------------------------------------------------------- +// Name: TextureSearchCallback() +// Desc: Enumeration callback routine to find a best-matching texture format. +// The param data is the DDPIXELFORMAT of the best-so-far matching +// texture. Note: the desired BPP is passed in the dwSize field, and the +// default BPP is passed in the dwFlags field. +//----------------------------------------------------------------------------- +static HRESULT CALLBACK TextureSearchCallback( DDPIXELFORMAT* pddpf, + VOID* param ) +{ + if( NULL==pddpf || NULL==param ) + return DDENUMRET_OK; + + TEXTURESEARCHINFO* ptsi = (TEXTURESEARCHINFO*)param; + + // Skip any funky modes + if( pddpf->dwFlags & (DDPF_LUMINANCE|DDPF_BUMPLUMINANCE|DDPF_BUMPDUDV) ) + return DDENUMRET_OK; + + // Check for palettized formats + if( ptsi->bUsePalette ) + { + if( !( pddpf->dwFlags & DDPF_PALETTEINDEXED8 ) ) + return DDENUMRET_OK; + + // Accept the first 8-bit palettized format we get + memcpy( ptsi->pddpf, pddpf, sizeof(DDPIXELFORMAT) ); + ptsi->bFoundGoodFormat = TRUE; + return DDENUMRET_CANCEL; + } + + // Else, skip any paletized formats (all modes under 16bpp) + if( pddpf->dwRGBBitCount < 16 ) + return DDENUMRET_OK; + + // Check for FourCC formats + if( ptsi->bUseFourCC ) + { + if( pddpf->dwFourCC == 0 ) + return DDENUMRET_OK; + + return DDENUMRET_CANCEL; + } + + // Else, skip any FourCC formats + if( pddpf->dwFourCC != 0 ) + return DDENUMRET_OK; + + // Make sure current alpha format agrees with requested format type + if( (ptsi->bUseAlpha==TRUE) && !(pddpf->dwFlags&DDPF_ALPHAPIXELS) ) + return DDENUMRET_OK; + if( (ptsi->bUseAlpha==FALSE) && (pddpf->dwFlags&DDPF_ALPHAPIXELS) ) + return DDENUMRET_OK; + + // Check if we found a good match + if( pddpf->dwRGBBitCount == ptsi->dwDesiredBPP ) + { + memcpy( ptsi->pddpf, pddpf, sizeof(DDPIXELFORMAT) ); + ptsi->bFoundGoodFormat = TRUE; + return DDENUMRET_CANCEL; + } + + return DDENUMRET_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: ~TextureContainer() +// Desc: Destructs the contents of the texture container +//----------------------------------------------------------------------------- +TextureContainer::~TextureContainer() +{ + SAFE_DELETE( pNext ); + SAFE_RELEASE( ptexTexture ); + SAFE_RELEASE( pddsSurface ); + DeleteObject( hbmBitmap ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CD3DStaticTextureEngine +// Desc: Class used to automatically construct and destruct the static +// texture engine class. +//----------------------------------------------------------------------------- +class CD3DTextureEngine +{ +public: + CD3DTextureEngine(); + ~CD3DTextureEngine(); +} g_StaticTextureEngine; + + + + +//----------------------------------------------------------------------------- +// Name: CD3DTextureEngine() +// Desc: Constructs the texture engine. Creates a DDraw object +//----------------------------------------------------------------------------- +CD3DTextureEngine::CD3DTextureEngine() +{ +} + + + + +//----------------------------------------------------------------------------- +// Name: ~CD3DTextureEngine() +// Desc: Deletes the internal list of textures +//----------------------------------------------------------------------------- +CD3DTextureEngine::~CD3DTextureEngine() +{ + // Delete the list of textures + SAFE_DELETE( g_ptcTextureList ); +} + + + + +//----------------------------------------------------------------------------- +// Name: FindTexture() +// Desc: Searches the internal list of textures for a texture specified by +// its name. Returns the structure associated with that texture. +//----------------------------------------------------------------------------- +static TextureContainer* FindTexture( TCHAR* strTextureName ) +{ + FOREACHTEXTURE( ptcTexture ) + { + if( !lstrcmpi( strTextureName, ptcTexture->strName ) ) + return ptcTexture; + } + + return NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: FindTextureFile() +// Desc: Looks for the specified file in the current directory, in the path +// specified in the environment variables, or in the path specified in +// the registry. After finding it, the function returns the full path. +//----------------------------------------------------------------------------- +static HRESULT FindTextureFile( TCHAR* strFilename, TCHAR* strTexturePath, + TCHAR* strFullPath ) +{ + // First, check the current directory + _tcscpy( strFullPath, strFilename ); + if( FileExists( strFullPath ) ) + return DD_OK; + + // Next, check to see if an environment variable specifies the path + TCHAR* strPath = _tgetenv( TEXT("D3DPATH") ); + if( NULL != strPath ) + { + _stprintf( strFullPath, TEXT("%s\\%s"), strPath, strFilename ); + if( FileExists( strFullPath ) ) + return DD_OK; + } + + // Finally, check the system registry for a path + HKEY key; + LONG result = RegOpenKeyEx( HKEY_LOCAL_MACHINE, + TEXT("Software\\Microsoft\\DirectX"), + 0, KEY_READ, &key ); + if( ERROR_SUCCESS == result ) + { + TCHAR strPath[512]; + DWORD type, size = 512; + result = RegQueryValueEx( key, g_strRegValueName, NULL, &type, + (BYTE*)strPath, &size ); + + RegCloseKey( key ); + + if( ERROR_SUCCESS == result ) + { + _stprintf( strFullPath, TEXT("%s\\D3DIM\\Media\\%s"), strPath, + strFilename ); + if( FileExists( strFullPath ) ) + return DD_OK; + + _stprintf( strFullPath, TEXT("%s\\%s%s"), strPath, + strTexturePath, strFilename ); + if( FileExists( strFullPath ) ) + return DD_OK; + } + } + + return DDERR_NOTFOUND; +} + + + + +//----------------------------------------------------------------------------- +// Name: LoadTextureImage() +// Desc: Loads a texture map file into a BITMAP surface. +//----------------------------------------------------------------------------- +static HRESULT LoadTextureImage( TextureContainer* ptcTexture ) +{ + TCHAR* strFilename = ptcTexture->strName; + TCHAR* strExtension; + TCHAR strPathname[256]; + + // Get the filename extension + if( NULL == ( strExtension = _tcsrchr( strFilename, TEXT('.') ) ) ) + return DDERR_UNSUPPORTED; + + // Check the executable's resource. If it's there, we're done! + if( NULL != ( ptcTexture->hbmBitmap = (HBITMAP)LoadImage( + GetModuleHandle(NULL), + strFilename, IMAGE_BITMAP, + 0, 0, LR_CREATEDIBSECTION) ) ) + return S_OK; + + // Check the current path and system registry path for the file + if( FAILED( FindTextureFile( strFilename, g_strTexturePath, strPathname ) ) ) + return DDERR_NOTFOUND; + + if( !lstrcmpi( strExtension, ".bmp" ) ) + { + // Try to load the bitmap as a resource. + ptcTexture->hbmBitmap = (HBITMAP)LoadImage( GetModuleHandle(NULL), + strPathname, IMAGE_BITMAP, 0, 0, + LR_CREATEDIBSECTION ); + + // If the bitmap wasn't a resource, try it as a file. + if( NULL == ptcTexture->hbmBitmap ) + ptcTexture->hbmBitmap = (HBITMAP)LoadImage( NULL, strPathname, + IMAGE_BITMAP, 0, 0, + LR_LOADFROMFILE|LR_CREATEDIBSECTION ); + + return (ptcTexture->hbmBitmap) ? DD_OK : DDERR_NOTFOUND; + } + + // Can check for other file formats here + + return DDERR_UNSUPPORTED; +} + + + + +//----------------------------------------------------------------------------- +// Name: CopyBitmapToSurface() +// Desc: Copies the image of a bitmap into a surface +//----------------------------------------------------------------------------- +static HRESULT CopyBitmapToSurface( LPDIRECTDRAWSURFACE4 pddsTarget, + HBITMAP hbmBitmap, DWORD dwFlags ) +{ + // Get a DDraw object to create a temporary surface + LPDIRECTDRAW4 pDD; + pddsTarget->GetDDInterface( (VOID**)&pDD ); + pDD->Release(); + + // Get the bitmap structure (to extract width, height, and bpp) + BITMAP bm; + GetObject( hbmBitmap, sizeof(BITMAP), &bm ); + + // Setup the new surface desc + DDSURFACEDESC2 ddsd; + D3DUtil_InitSurfaceDesc( ddsd ); + pddsTarget->GetSurfaceDesc( &ddsd ); + ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT| + DDSD_TEXTURESTAGE; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY; + ddsd.ddsCaps.dwCaps2 = 0L; + ddsd.dwWidth = bm.bmWidth; + ddsd.dwHeight = bm.bmHeight; + + // Create a new surface for the texture + LPDIRECTDRAWSURFACE4 pddsTempSurface; + HRESULT hr; + if( FAILED( hr = pDD->CreateSurface( &ddsd, &pddsTempSurface, NULL ) ) ) + return NULL; + + // Get a DC for the bitmap + HDC hdcBitmap = CreateCompatibleDC( NULL ); + if( NULL == hdcBitmap ) + { + pddsTempSurface->Release(); + return NULL; + } + SelectObject( hdcBitmap, hbmBitmap ); + + // Handle palettized textures. Need to attach a palette + if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) + { + // Create the color table and parse in the palette + DWORD pe[256]; + WORD wNumColors = GetDIBColorTable( hdcBitmap, 0, 256, + (RGBQUAD*)pe ); + for( WORD i=0; iCreatePalette( DDPCAPS_8BIT|DDPCAPS_ALPHA, (PALETTEENTRY*)pe, &pPalette, NULL ); + else + pDD->CreatePalette( DDPCAPS_8BIT, (PALETTEENTRY*)pe, &pPalette, NULL ); + pddsTempSurface->SetPalette( pPalette ); + pddsTarget->SetPalette( pPalette ); + SAFE_RELEASE( pPalette ); + } + + // Copy the bitmap image to the surface. + HDC hdcSurface; + if( SUCCEEDED( pddsTempSurface->GetDC( &hdcSurface ) ) ) + { + BitBlt( hdcSurface, 0, 0, bm.bmWidth, bm.bmHeight, hdcBitmap, 0, 0, + SRCCOPY ); + pddsTempSurface->ReleaseDC( hdcSurface ); + } + DeleteDC( hdcBitmap ); + + // Copy the temp surface to the real texture surface + pddsTarget->Blt( NULL, pddsTempSurface, NULL, DDBLT_WAIT, NULL ); + + if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) + { + LPDIRECTDRAWPALETTE pPalette; + DWORD pe[256]; + pddsTempSurface->GetPalette( &pPalette ); + pPalette->GetEntries( 0, 0, 256, (PALETTEENTRY*)&pe ); + pPalette->Release(); + + pddsTarget->GetPalette( &pPalette ); + pPalette->GetEntries( 0, 0, 256, (PALETTEENTRY*)&pe ); + pPalette->Release(); + } + + pddsTempSurface->Release(); + + // For textures with real alpha (not palettized), set transparent bits + if( ddsd.ddpfPixelFormat.dwRGBAlphaBitMask ) + { + if( dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) ) + { + // Lock the texture surface + DDSURFACEDESC2 ddsd; + D3DUtil_InitSurfaceDesc( ddsd ); + while( pddsTarget->Lock( NULL, &ddsd, 0, NULL ) == + DDERR_WASSTILLDRAWING ); + + DWORD dwAlphaMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask; + DWORD dwRGBMask = ( ddsd.ddpfPixelFormat.dwRBitMask | + ddsd.ddpfPixelFormat.dwGBitMask | + ddsd.ddpfPixelFormat.dwBBitMask ); + DWORD dwColorkey = 0x00000000; // Colorkey on black + if( dwFlags & D3DTEXTR_TRANSPARENTWHITE ) + dwColorkey = dwRGBMask; // Colorkey on white + + // Add an opaque alpha value to each non-colorkeyed pixel + for( DWORD y=0; yUnlock( NULL ); + } + } + + return S_OK;; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DTextr_GetSurface() +// Desc: Returns a pointer to a d3dSurface from the name of the texture +//----------------------------------------------------------------------------- +LPDIRECTDRAWSURFACE4 D3DTextr_GetSurface( TCHAR* strName ) +{ + TextureContainer* ptcTexture = FindTexture( strName ); + + return ptcTexture ? ptcTexture->pddsSurface : NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DTextr_GetTexture() +// Desc: Returns a pointer to a d3dTexture from the name of the texture +//----------------------------------------------------------------------------- +LPDIRECT3DTEXTURE2 D3DTextr_GetTexture( TCHAR* strName ) +{ + TextureContainer* ptcTexture = FindTexture( strName ); + + return ptcTexture ? ptcTexture->ptexTexture: NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DTextr_SetTexturePath() +// Desc: Enumeration callback routine to find a best-matching texture format. +//----------------------------------------------------------------------------- +VOID D3DTextr_SetTexturePath( TCHAR* strTexturePath ) +{ + if( NULL==strTexturePath ) + strTexturePath = TEXT(""); + _tcscpy( g_strTexturePath, strTexturePath ); +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DTextr_CreateTexture() +// Desc: Is passed a filename and creates a local Bitmap from that file. +// The texture can not be used until it is restored, however. +//----------------------------------------------------------------------------- +HRESULT D3DTextr_CreateTexture( TCHAR* strName, DWORD dwStage, DWORD dwFlags ) +{ + // Check first to see if the texture is already loaded + if( NULL != FindTexture( strName ) ) + return S_OK; + + // Allocate and add the texture to the linked list of textures; + TextureContainer* ptcTexture = new TextureContainer(); + if( NULL == ptcTexture ) + return E_OUTOFMEMORY; + ZeroMemory( ptcTexture, sizeof(TextureContainer) ); + lstrcpy( ptcTexture->strName, strName ); + ptcTexture->dwStage = dwStage; + ptcTexture->dwFlags = dwFlags; + + // Create a bitmap and load the texture file into it, + if( FAILED( LoadTextureImage( ptcTexture ) ) ) + { + delete ptcTexture; + return E_FAIL; + } + + // Add the texture to the global linked list + if( g_ptcTextureList ) + g_ptcTextureList->pPrev = ptcTexture; + ptcTexture->pNext = g_ptcTextureList; + g_ptcTextureList = ptcTexture; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: RestoreFromBitmap() +// Desc: Invalidates the current texture objects and rebuilds new ones +// using the new device. +//----------------------------------------------------------------------------- +static HRESULT RestoreFromBitmap( TextureContainer* ptcTexture, + LPDIRECT3DDEVICE3 pd3dDevice ) +{ + // Get the DirectDraw interface for creating surfaces + LPDIRECTDRAW4 pDD; + if( NULL == ( pDD = D3DUtil_GetDirectDrawFromDevice( pd3dDevice ) ) ) + return E_FAIL; + pDD->Release(); + + // Get the device caps + D3DDEVICEDESC ddHwDesc, ddSwDesc; + DWORD dwDeviceCaps; + ddHwDesc.dwSize = sizeof(D3DDEVICEDESC); + ddSwDesc.dwSize = sizeof(D3DDEVICEDESC); + if( FAILED( pd3dDevice->GetCaps( &ddHwDesc, &ddSwDesc ) ) ) + return E_FAIL; + if( ddHwDesc.dwFlags ) dwDeviceCaps = ddHwDesc.dpcTriCaps.dwTextureCaps; + else dwDeviceCaps = ddSwDesc.dpcTriCaps.dwTextureCaps; + + // Get the bitmap structure (to extract width, height, and bpp) + BITMAP bm; + HBITMAP hbmBitmap = ptcTexture->hbmBitmap; + GetObject( hbmBitmap, sizeof(BITMAP), &bm ); + DWORD dwWidth = (DWORD)bm.bmWidth; + DWORD dwHeight = (DWORD)bm.bmHeight; + + // Setup the new surface desc + DDSURFACEDESC2 ddsd; + D3DUtil_InitSurfaceDesc( ddsd ); + ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH| + DDSD_PIXELFORMAT|DDSD_TEXTURESTAGE; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; + ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE; + ddsd.dwTextureStage = ptcTexture->dwStage; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + // Adjust width and height, if the driver requires it + if( dwDeviceCaps & D3DPTEXTURECAPS_POW2 ) + { + for( ddsd.dwWidth=1; dwWidth>ddsd.dwWidth; ddsd.dwWidth<<=1 ); + for( ddsd.dwHeight=1; dwHeight>ddsd.dwHeight; ddsd.dwHeight<<=1 ); + } + if( dwDeviceCaps & D3DPTEXTURECAPS_SQUAREONLY ) + { + if( ddsd.dwWidth > ddsd.dwHeight ) ddsd.dwHeight = ddsd.dwWidth; + else ddsd.dwWidth = ddsd.dwHeight; + } + + BOOL bUsePalette = ( bm.bmBitsPixel <= 8 ); + BOOL bUseAlpha = FALSE; + + if( ptcTexture->bHasAlpha ) + bUseAlpha = TRUE; + + if( ptcTexture->dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) ) + { + if( bUsePalette ) + { + if( dwDeviceCaps & D3DPTEXTURECAPS_ALPHAPALETTE ) + { + bUseAlpha = TRUE; + bUsePalette = TRUE; + } + else + { + bUseAlpha = TRUE; + bUsePalette = FALSE; + } + } + } + + // Setup the structure to be used for texture enumration. + TEXTURESEARCHINFO tsi; + tsi.pddpf = &ddsd.ddpfPixelFormat; + tsi.bUseAlpha = bUseAlpha; + tsi.bUsePalette = bUsePalette; + tsi.bUseFourCC = ( ddsd.ddpfPixelFormat.dwFlags & DDPF_FOURCC ); + tsi.dwDesiredBPP = 16; + tsi.bFoundGoodFormat = FALSE; + if( ptcTexture->dwFlags & D3DTEXTR_32BITSPERPIXEL ) + tsi.dwDesiredBPP = 32; + + // Enumerate the texture formats, and find the closest device-supported + // texture pixel format + pd3dDevice->EnumTextureFormats( TextureSearchCallback, &tsi ); + + // If a palettized format was requested, but not found, default to a + // 16-bit texture format + if( FALSE == tsi.bFoundGoodFormat && bUsePalette ) + { + tsi.bUsePalette = FALSE; + tsi.dwDesiredBPP = 16; + pd3dDevice->EnumTextureFormats( TextureSearchCallback, &tsi ); + if( FALSE == tsi.bFoundGoodFormat ) + return E_FAIL; + } + + // Create a new surface for the texture + HRESULT hr; + if( FAILED( hr = pDD->CreateSurface( &ddsd, &ptcTexture->pddsSurface, NULL ) ) ) + return E_FAIL; + + // Create the texture + if( FAILED( ptcTexture->pddsSurface->QueryInterface( IID_IDirect3DTexture2, + (VOID**)&ptcTexture->ptexTexture ) ) ) + return E_FAIL; + + + // Copy the bitmap to the texture surface + return CopyBitmapToSurface( ptcTexture->pddsSurface, hbmBitmap, + ptcTexture->dwFlags ); + +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DTextr_Restore() +// Desc: Invalidates the current texture objects and rebuilds new ones +// using the new device. +//----------------------------------------------------------------------------- +HRESULT D3DTextr_Restore( TCHAR* strName, LPDIRECT3DDEVICE3 pd3dDevice ) +{ + // Check params + if( NULL == pd3dDevice ) + return DDERR_INVALIDPARAMS; + + TextureContainer* ptcTexture = FindTexture( strName ); + if( NULL == ptcTexture ) + return DDERR_NOTFOUND; + + // Release any previously created objects + SAFE_RELEASE( ptcTexture->ptexTexture ); + SAFE_RELEASE( ptcTexture->pddsSurface ); + + // Restore the texture surface from the bitmap image. At this point, code + // can be added to handle other texture formats, such as those created from + // .dds files, .jpg files, or whatever else. + return RestoreFromBitmap( ptcTexture, pd3dDevice ); +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DTextr_RestoreAllTextures() +// Desc: This function is called when a mode is changed. It updates all +// texture objects to be valid with the new device. +//----------------------------------------------------------------------------- +HRESULT D3DTextr_RestoreAllTextures( LPDIRECT3DDEVICE3 pd3dDevice ) +{ + FOREACHTEXTURE( ptcTexture ) + { + D3DTextr_Restore( ptcTexture->strName, pd3dDevice ); + } + + return DD_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DTextr_Invalidate() +// Desc: Used to bump a texture out of (video) memory, this function +// actually destroys the d3dtexture and ddsurface of the texture +//----------------------------------------------------------------------------- +HRESULT D3DTextr_Invalidate( TCHAR* strName ) +{ + TextureContainer* ptcTexture = FindTexture( strName ); + if( NULL == ptcTexture ) + return DDERR_NOTFOUND; + + SAFE_RELEASE( ptcTexture->ptexTexture ); + SAFE_RELEASE( ptcTexture->pddsSurface ); + + return DD_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DTextr_InvalidateAllTextures() +// Desc: This function is called when a mode is changed. It invalidates +// all texture objects so their device can be safely released. +//----------------------------------------------------------------------------- +HRESULT D3DTextr_InvalidateAllTextures() +{ + FOREACHTEXTURE( ptcTexture ) + { + SAFE_RELEASE( ptcTexture->ptexTexture ); + SAFE_RELEASE( ptcTexture->pddsSurface ); + } + + return DD_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DTextr_DestroyTexture() +// Desc: Frees the resources for the specified texture container +//----------------------------------------------------------------------------- +HRESULT D3DTextr_DestroyTexture( TCHAR* strName ) +{ + TextureContainer* ptcTexture = FindTexture( strName ); + if( NULL == ptcTexture ) + return DDERR_NOTFOUND; + + // Remove the texture container from the global list + if( ptcTexture->pPrev ) + ptcTexture->pPrev->pNext = ptcTexture->pNext; + else + g_ptcTextureList = ptcTexture->pNext; + ptcTexture->pNext = NULL; + + SAFE_DELETE( ptcTexture ); + + return DD_OK; +} + diff --git a/arch/win32/d3dframe/d3dtextr.h b/arch/win32/d3dframe/d3dtextr.h new file mode 100644 index 00000000..2b7d681a --- /dev/null +++ b/arch/win32/d3dframe/d3dtextr.h @@ -0,0 +1,62 @@ +//----------------------------------------------------------------------------- +// File: D3DTextr.h +// +// Desc: Functions to manage textures, including creating (loading from a +// file), restoring lost surfaces, invalidating, and destroying. +// +// Note: the implementation of these fucntions maintain an internal list +// of loaded textures. After creation, individual textures are referenced +// via their ASCII names. +// +// +// Copyright (C) 1997 Microsoft Corporation. All rights reserved +//----------------------------------------------------------------------------- + +#ifndef D3DTEXTR_H +#define D3DTEXTR_H + +#include +#include + + + + +//----------------------------------------------------------------------------- +// Access functions for loaded textures. Note: these functions search +// an internal list of the textures, and use the texture associated with the +// ASCII name. +//----------------------------------------------------------------------------- +LPDIRECTDRAWSURFACE4 D3DTextr_GetSurface( TCHAR* strName ); +LPDIRECT3DTEXTURE2 D3DTextr_GetTexture( TCHAR* strName ); + + + + +//----------------------------------------------------------------------------- +// Texture invalidation and restoration functions +//----------------------------------------------------------------------------- +HRESULT D3DTextr_Invalidate( TCHAR* strName ); +HRESULT D3DTextr_Restore( TCHAR* strName, LPDIRECT3DDEVICE3 pd3dDevice ); +HRESULT D3DTextr_InvalidateAllTextures(); +HRESULT D3DTextr_RestoreAllTextures( LPDIRECT3DDEVICE3 pd3dDevice ); + + + + +//----------------------------------------------------------------------------- +// Texture creation and deletion functions +//----------------------------------------------------------------------------- +#define D3DTEXTR_TRANSPARENTWHITE 0x00000001 +#define D3DTEXTR_TRANSPARENTBLACK 0x00000002 +#define D3DTEXTR_32BITSPERPIXEL 0x00000004 + +HRESULT D3DTextr_CreateTexture( TCHAR* strName, DWORD dwStage=0L, + DWORD dwFlags=0L ); +HRESULT D3DTextr_DestroyTexture( TCHAR* strName ); +VOID D3DTextr_SetTexturePath( TCHAR* strTexturePath ); + + + + +#endif // D3DTEXTR_H + diff --git a/arch/win32/d3dframe/d3dutil.cpp b/arch/win32/d3dframe/d3dutil.cpp new file mode 100644 index 00000000..0f37d2f7 --- /dev/null +++ b/arch/win32/d3dframe/d3dutil.cpp @@ -0,0 +1,390 @@ +//----------------------------------------------------------------------------- +// File: D3DUtil.cpp +// +// Desc: Shortcut macros and functions for using DX objects +// +// +// Copyright (c) 1997-1998 Microsoft Corporation. All rights reserved +//----------------------------------------------------------------------------- + +#define D3D_OVERLOADS +#include +#include +#include "D3DUtil.h" + + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_InitDeviceDesc() +// Desc: Helper function called to initialize a D3DDEVICEDESC structure, +//----------------------------------------------------------------------------- +VOID D3DUtil_InitDeviceDesc( D3DDEVICEDESC& ddDevDesc ) +{ + ZeroMemory( &ddDevDesc, sizeof(D3DDEVICEDESC) ); + ddDevDesc.dwSize = sizeof(D3DDEVICEDESC); + ddDevDesc.dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS); + ddDevDesc.dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS); + ddDevDesc.dpcLineCaps.dwSize = sizeof(D3DPRIMCAPS); + ddDevDesc.dpcTriCaps.dwSize = sizeof(D3DPRIMCAPS); +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_InitSurfaceDesc() +// Desc: Helper function called to build a DDSURFACEDESC2 structure, +// typically before calling CreateSurface() or GetSurfaceDesc() +//----------------------------------------------------------------------------- +VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags, + DWORD dwCaps ) +{ + ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) ); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + ddsd.dwFlags = dwFlags; + ddsd.ddsCaps.dwCaps = dwCaps; + ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_InitViewport() +// Desc: Helper function called to build a D3DVIEWPORT3 structure +//----------------------------------------------------------------------------- +VOID D3DUtil_InitViewport( D3DVIEWPORT2& vp, DWORD dwWidth, DWORD dwHeight ) +{ + ZeroMemory( &vp, sizeof(D3DVIEWPORT2) ); + vp.dwSize = sizeof(D3DVIEWPORT2); + vp.dwWidth = dwWidth; + vp.dwHeight = dwHeight; + vp.dvMaxZ = 1.0f; + + vp.dvClipX = -1.0f; + vp.dvClipWidth = 2.0f; + vp.dvClipY = 1.0f; + vp.dvClipHeight = 2.0f; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_InitMaterial() +// Desc: Helper function called to build a D3DMATERIAL structure +//----------------------------------------------------------------------------- +VOID D3DUtil_InitMaterial( D3DMATERIAL& mtrl, FLOAT r, FLOAT g, FLOAT b ) +{ + ZeroMemory( &mtrl, sizeof(D3DMATERIAL) ); + mtrl.dwSize = sizeof(D3DMATERIAL); + mtrl.dcvDiffuse.r = mtrl.dcvAmbient.r = r; + mtrl.dcvDiffuse.g = mtrl.dcvAmbient.g = g; + mtrl.dcvDiffuse.b = mtrl.dcvAmbient.b = b; + mtrl.dwRampSize = 16L; // A default ramp size +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_InitLight() +// Desc: Initializes a D3DLIGHT structure +//----------------------------------------------------------------------------- +VOID D3DUtil_InitLight( D3DLIGHT& light, D3DLIGHTTYPE ltType, + FLOAT x, FLOAT y, FLOAT z ) +{ + ZeroMemory( &light, sizeof(D3DLIGHT) ); + light.dwSize = sizeof(D3DLIGHT); + light.dltType = ltType; + light.dcvColor.r = 1.0f; + light.dcvColor.g = 1.0f; + light.dcvColor.b = 1.0f; + light.dvPosition.x = light.dvDirection.x = x; + light.dvPosition.y = light.dvDirection.y = y; + light.dvPosition.z = light.dvDirection.z = z; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_GetDirectDrawFromDevice() +// Desc: Get the DDraw interface from a D3DDevice. +//----------------------------------------------------------------------------- +LPDIRECTDRAW4 D3DUtil_GetDirectDrawFromDevice( LPDIRECT3DDEVICE3 pd3dDevice ) +{ + LPDIRECTDRAW4 pDD = NULL; + LPDIRECTDRAWSURFACE4 pddsRender; + + if( pd3dDevice ) + { + // Get the current render target + if( SUCCEEDED( pd3dDevice->GetRenderTarget( &pddsRender ) ) ) + { + // Get the DDraw4 interface from the render target + pddsRender->GetDDInterface( (VOID**)&pDD ); + pddsRender->Release(); + } + } + return pDD; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_GetDeviceMemoryType() +// Desc: Retreives the default memory type used for the device. +//----------------------------------------------------------------------------- +DWORD D3DUtil_GetDeviceMemoryType( LPDIRECT3DDEVICE3 pd3dDevice ) +{ + D3DDEVICEDESC ddHwDesc, ddSwDesc; + ddHwDesc.dwSize = sizeof(D3DDEVICEDESC); + ddSwDesc.dwSize = sizeof(D3DDEVICEDESC); + if( FAILED( pd3dDevice->GetCaps( &ddHwDesc, &ddSwDesc ) ) ) + return 0L; + + if( ddHwDesc.dwFlags ) + return DDSCAPS_VIDEOMEMORY; + + return DDSCAPS_SYSTEMMEMORY; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetViewMatrix() +// Desc: Given an eye point, a lookat point, and an up vector, this +// function builds a 4x4 view matrix. +//----------------------------------------------------------------------------- +HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom, + D3DVECTOR& vAt, D3DVECTOR& vWorldUp ) +{ + // Get the z basis vector, which points straight ahead. This is the + // difference from the eyepoint to the lookat point. + D3DVECTOR vView = vAt - vFrom; + + FLOAT fLength = Magnitude( vView ); + if( fLength < 1e-6f ) + return E_INVALIDARG; + + // Normalize the z basis vector + vView /= fLength; + + // Get the dot product, and calculate the projection of the z basis + // vector onto the up vector. The projection is the y basis vector. + FLOAT fDotProduct = DotProduct( vWorldUp, vView ); + + D3DVECTOR vUp = vWorldUp - fDotProduct * vView; + + // If this vector has near-zero length because the input specified a + // bogus up vector, let's try a default up vector + if( 1e-6f > ( fLength = Magnitude( vUp ) ) ) + { + vUp = D3DVECTOR( 0.0f, 1.0f, 0.0f ) - vView.y * vView; + + // If we still have near-zero length, resort to a different axis. + if( 1e-6f > ( fLength = Magnitude( vUp ) ) ) + { + vUp = D3DVECTOR( 0.0f, 0.0f, 1.0f ) - vView.z * vView; + + if( 1e-6f > ( fLength = Magnitude( vUp ) ) ) + return E_INVALIDARG; + } + } + + // Normalize the y basis vector + vUp /= fLength; + + // The x basis vector is found simply with the cross product of the y + // and z basis vectors + D3DVECTOR vRight = CrossProduct( vUp, vView ); + + // Start building the matrix. The first three rows contains the basis + // vectors used to rotate the view to point at the lookat point + D3DUtil_SetIdentityMatrix( mat ); + mat._11 = vRight.x; mat._12 = vUp.x; mat._13 = vView.x; + mat._21 = vRight.y; mat._22 = vUp.y; mat._23 = vView.y; + mat._31 = vRight.z; mat._32 = vUp.z; mat._33 = vView.z; + + // Do the translation values (rotations are still about the eyepoint) + mat._41 = - DotProduct( vFrom, vRight ); + mat._42 = - DotProduct( vFrom, vUp ); + mat._43 = - DotProduct( vFrom, vView ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetProjectionMatrix() +// Desc: Sets the passed in 4x4 matrix to a perpsective projection matrix built +// from the field-of-view (fov, in y), aspect ratio, near plane (D), +// and far plane (F). Note that the projection matrix is normalized for +// element [3][4] to be 1.0. This is performed so that W-based range fog +// will work correctly. +//----------------------------------------------------------------------------- +HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV, FLOAT fAspect, + FLOAT fNearPlane, FLOAT fFarPlane ) +{ + if( fabs(fFarPlane-fNearPlane) < 0.01f ) + return E_INVALIDARG; + if( fabs(sin(fFOV/2)) < 0.01f ) + return E_INVALIDARG; + + FLOAT w = fAspect * (FLOAT)( cos(fFOV/2)/sin(fFOV/2) ); + FLOAT h = 1.0f * (FLOAT)( cos(fFOV/2)/sin(fFOV/2) ); + FLOAT Q = fFarPlane / ( fFarPlane - fNearPlane ); + + ZeroMemory( &mat, sizeof(D3DMATRIX) ); + mat._11 = w; + mat._22 = h; + mat._33 = Q; + mat._34 = 1.0f; + mat._43 = -Q*fNearPlane; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetRotateXMatrix() +// Desc: Create Rotation matrix about X axis +//----------------------------------------------------------------------------- +VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads ) +{ + D3DUtil_SetIdentityMatrix( mat ); + mat._22 = (FLOAT)cos( fRads ); + mat._23 = (FLOAT)sin( fRads ); + mat._32 = -(FLOAT)sin( fRads ); + mat._33 = (FLOAT)cos( fRads ); +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetRotateYMatrix() +// Desc: Create Rotation matrix about Y axis +//----------------------------------------------------------------------------- +VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads ) +{ + D3DUtil_SetIdentityMatrix( mat ); + mat._11 = (FLOAT)cos( fRads ); + mat._13 = -(FLOAT)sin( fRads ); + mat._31 = (FLOAT)sin( fRads ); + mat._33 = (FLOAT)cos( fRads ); +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetRotateZMatrix() +// Desc: Create Rotation matrix about Z axis +//----------------------------------------------------------------------------- +VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads ) +{ + D3DUtil_SetIdentityMatrix( mat ); + mat._11 = (FLOAT)cos( fRads ); + mat._12 = (FLOAT)sin( fRads ); + mat._21 = -(FLOAT)sin( fRads ); + mat._22 = (FLOAT)cos( fRads ); +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetRotationMatrix +// Desc: Create a Rotation matrix about vector direction +//----------------------------------------------------------------------------- +VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir, FLOAT fRads ) +{ + FLOAT fCos = (FLOAT)cos( fRads ); + FLOAT fSin = (FLOAT)sin( fRads ); + D3DVECTOR v = Normalize( vDir ); + + mat._11 = ( v.x * v.x ) * ( 1.0f - fCos ) + fCos; + mat._12 = ( v.x * v.y ) * ( 1.0f - fCos ) - (v.z * fSin); + mat._13 = ( v.x * v.z ) * ( 1.0f - fCos ) + (v.y * fSin); + + mat._21 = ( v.y * v.x ) * ( 1.0f - fCos ) + (v.z * fSin); + mat._22 = ( v.y * v.y ) * ( 1.0f - fCos ) + fCos ; + mat._23 = ( v.y * v.z ) * ( 1.0f - fCos ) - (v.x * fSin); + + mat._31 = ( v.z * v.x ) * ( 1.0f - fCos ) - (v.y * fSin); + mat._32 = ( v.z * v.y ) * ( 1.0f - fCos ) + (v.x * fSin); + mat._33 = ( v.z * v.z ) * ( 1.0f - fCos ) + fCos; + + mat._14 = mat._24 = mat._34 = 0.0f; + mat._41 = mat._42 = mat._43 = 0.0f; + mat._44 = 1.0f; +} + + + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_GetDisplayDepth() +// Desc: Returns the depth of the current display mode. +//----------------------------------------------------------------------------- +DWORD D3DUtil_GetDisplayDepth( LPDIRECTDRAW4 pDD4 ) +{ + // If the caller did not supply a DDraw object, just create a temp one. + if( NULL == pDD4 ) + { + LPDIRECTDRAW pDD1; + if( FAILED( DirectDrawCreate( NULL, &pDD1, NULL ) ) ) + return 0L; + + HRESULT hr = pDD1->QueryInterface( IID_IDirectDraw4, (VOID**)&pDD4 ); + pDD1->Release(); + if( FAILED(hr) ) + return 0L; + } + else + pDD4->AddRef(); + + // Get the display mode description + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) ); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + pDD4->GetDisplayMode( &ddsd ); + pDD4->Release(); + + // Return the display mode's depth + return ddsd.ddpfPixelFormat.dwRGBBitCount; +} + + + + +//----------------------------------------------------------------------------- +// Name: _DbgOut() +// Desc: Outputs a message to the debug stream +//----------------------------------------------------------------------------- +HRESULT _DbgOut( TCHAR* strFile, DWORD dwLine, HRESULT hr, TCHAR* strMsg ) +{ + TCHAR buffer[256]; + sprintf( buffer, "%s(%ld): ", strFile, dwLine ); + OutputDebugString( buffer ); + OutputDebugString( strMsg ); + + if( hr ) + { + sprintf( buffer, "(hr=%08lx)\n", hr ); + OutputDebugString( buffer ); + } + + OutputDebugString( "\n" ); + + return hr; +} + diff --git a/arch/win32/d3dframe/d3dutil.h b/arch/win32/d3dframe/d3dutil.h new file mode 100644 index 00000000..f26a6ced --- /dev/null +++ b/arch/win32/d3dframe/d3dutil.h @@ -0,0 +1,110 @@ +//----------------------------------------------------------------------------- +// File: D3DUtil.h +// +// Desc: Helper functions and typing shortcuts for Direct3D programming. +// +// +// Copyright (C) 1997 Microsoft Corporation. All rights reserved +//----------------------------------------------------------------------------- + +#ifndef D3DUTIL_H +#define D3DUTIL_H + +#include +#include + + +//----------------------------------------------------------------------------- +// Typing shortcuts for deleting and freeing objects. +//----------------------------------------------------------------------------- +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + +//----------------------------------------------------------------------------- +// Short cut functions for creating and using DX structures +//----------------------------------------------------------------------------- +VOID D3DUtil_InitDeviceDesc( D3DDEVICEDESC& ddDevDesc ); +VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags=0, + DWORD dwCaps=0 ); +VOID D3DUtil_InitViewport( D3DVIEWPORT2& vdViewData, DWORD dwWidth=0, + DWORD dwHeight=0 ); +VOID D3DUtil_InitMaterial( D3DMATERIAL& mdMtrlData, FLOAT r=0.0f, FLOAT g=0.0f, + FLOAT b=0.0f ); +VOID D3DUtil_InitLight( D3DLIGHT& ldLightData, D3DLIGHTTYPE ltType, + FLOAT x=0.0f, FLOAT y=0.0f, FLOAT z=0.0f ); + + + + +//----------------------------------------------------------------------------- +// Miscellaneous helper functions +//----------------------------------------------------------------------------- +LPDIRECTDRAW4 D3DUtil_GetDirectDrawFromDevice( LPDIRECT3DDEVICE3 pd3dDevice ); +DWORD D3DUtil_GetDeviceMemoryType( LPDIRECT3DDEVICE3 pd3dDevice ); +DWORD D3DUtil_GetDisplayDepth( LPDIRECTDRAW4 pDD4=NULL ); + + + + +//----------------------------------------------------------------------------- +// D3D Matrix functions. For performance reasons, some functions are inline. +//----------------------------------------------------------------------------- +HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom, + D3DVECTOR& vAt, D3DVECTOR& vUp ); +HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV = 1.570795f, + FLOAT fAspect = 1.0f, + FLOAT fNearPlane = 1.0f, + FLOAT fFarPlane = 1000.0f ); + +inline VOID D3DUtil_SetIdentityMatrix( D3DMATRIX& m ) +{ + m._12 = m._13 = m._14 = m._21 = m._23 = m._24 = 0.0f; + m._31 = m._32 = m._34 = m._41 = m._42 = m._43 = 0.0f; + m._11 = m._22 = m._33 = m._44 = 1.0f; +} + +inline VOID D3DUtil_SetTranslateMatrix( D3DMATRIX& m, FLOAT tx, FLOAT ty, + FLOAT tz ) +{ D3DUtil_SetIdentityMatrix( m ); m._41 = tx; m._42 = ty; m._43 = tz; } + +inline VOID D3DUtil_SetTranslateMatrix( D3DMATRIX& m, D3DVECTOR& v ) +{ D3DUtil_SetTranslateMatrix( m, v.x, v.y, v.z ); } + +inline VOID D3DUtil_SetScaleMatrix( D3DMATRIX& m, FLOAT sx, FLOAT sy, + FLOAT sz ) +{ D3DUtil_SetIdentityMatrix( m ); m._11 = sx; m._22 = sy; m._33 = sz; } + +inline VOID SetScaleMatrix( D3DMATRIX& m, D3DVECTOR& v ) +{ D3DUtil_SetScaleMatrix( m, v.x, v.y, v.z ); } + +VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads ); +VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads ); +VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads ); +VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir, + FLOAT fRads ); + + + + +//----------------------------------------------------------------------------- +// Debug printing support +//----------------------------------------------------------------------------- + +HRESULT _DbgOut( TCHAR*, DWORD, HRESULT, TCHAR* ); + +#if defined(DEBUG) | defined(_DEBUG) + #define DEBUG_MSG(str) _DbgOut( __FILE__, (DWORD)__LINE__, 0, str ) + #define DEBUG_ERR(hr,str) _DbgOut( __FILE__, (DWORD)__LINE__, hr, str ) +#else + #define DEBUG_MSG(str) (0L) + #define DEBUG_ERR(hr,str) (hr) +#endif + + + + +#endif // D3DUTIL_H + diff --git a/arch/win32/d3dframe/ddenum.cpp b/arch/win32/d3dframe/ddenum.cpp new file mode 100644 index 00000000..a5ea6706 --- /dev/null +++ b/arch/win32/d3dframe/ddenum.cpp @@ -0,0 +1,314 @@ +//----------------------------------------------------------------------------- +// File: ddenum.cpp +// +// Desc: This sample demonstrates how to enumerate all of the devices and show +// the driver information about each. +// +// +// Copyright (c) 1998 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +//----------------------------------------------------------------------------- +// Include files +//----------------------------------------------------------------------------- +#include +#include +#include +#include +#include "resource.h" + +//----------------------------------------------------------------------------- +// Local definitions +//----------------------------------------------------------------------------- +#define NAME "DDEnum" +#define TITLE "DirectDraw Enumeration Example" + +//----------------------------------------------------------------------------- +// Default settings +//----------------------------------------------------------------------------- +#define MAX_DEVICES 16 + +//----------------------------------------------------------------------------- +// Global Variables +//----------------------------------------------------------------------------- +int g_iMaxDevices = 0; +struct{ + DDDEVICEIDENTIFIER DeviceInfo; + DDDEVICEIDENTIFIER DeviceInfoHost; +} g_DeviceInfo[MAX_DEVICES]; + + + + +//----------------------------------------------------------------------------- +// Name: InitFail() +// Desc: This function is called if an initialization function fails +//----------------------------------------------------------------------------- +void +InitFail(LPCTSTR szError, ...) +{ + char szBuff[128]; + va_list vl; + + va_start(vl, szError); + vsprintf(szBuff, szError, vl); + MessageBox(NULL, szBuff, TITLE, MB_OK); + va_end(vl); +} + + + + +//----------------------------------------------------------------------------- +// Name: SetInfoDlgText() +// Desc: Update all of the text and buttons in the dialog +//----------------------------------------------------------------------------- +void +SetInfoDlgText(HWND hDlg, int iCurrent, DWORD dwHost) +{ + char szBuff[128]; + GUID *pGUID; + LPDDDEVICEIDENTIFIER pDI; + + if (dwHost == DDGDI_GETHOSTIDENTIFIER) + CheckRadioButton( hDlg, IDC_RADIO_DEVICE, IDC_RADIO_HOST, IDC_RADIO_HOST ); + else + CheckRadioButton( hDlg, IDC_RADIO_DEVICE, IDC_RADIO_DEVICE, IDC_RADIO_DEVICE ); + + pDI = &g_DeviceInfo[iCurrent].DeviceInfo; + if (dwHost == DDGDI_GETHOSTIDENTIFIER) + pDI = &g_DeviceInfo[iCurrent].DeviceInfoHost; + + wsprintf(szBuff, "Device information for device %d of %d",iCurrent + 1,g_iMaxDevices); + SetDlgItemText( hDlg, IDC_RADIO_DEVICE, szBuff); + + //Device ID stuff: + wsprintf(szBuff,"%08X",pDI->dwVendorId); + SetDlgItemText( hDlg, IDC_DWVENDORID, szBuff); + wsprintf(szBuff,"%08X",pDI->dwDeviceId); + SetDlgItemText( hDlg, IDC_DWDEVICEID, szBuff); + wsprintf(szBuff,"%08X",pDI->dwSubSysId); + SetDlgItemText( hDlg, IDC_DWSUBSYS, szBuff); + wsprintf(szBuff,"%08X",pDI->dwRevision); + SetDlgItemText( hDlg, IDC_DWREVISION, szBuff); + + //Driver version: + wsprintf(szBuff,"%d.%02d.%02d.%04d", + HIWORD(pDI->liDriverVersion.u.HighPart), + LOWORD(pDI->liDriverVersion.u.HighPart), + HIWORD(pDI->liDriverVersion.u.LowPart), + LOWORD(pDI->liDriverVersion.u.LowPart) ); + SetDlgItemText( hDlg, IDC_VERSION, szBuff); + + //Device description and HAL filename + SetDlgItemText( hDlg, IDC_DESCRIPTION, pDI->szDescription); + SetDlgItemText( hDlg, IDC_FILENAME, pDI->szDriver); + + //Unique driver/device identifier: + pGUID = &pDI->guidDeviceIdentifier; + wsprintf(szBuff, "%08X-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X", + pGUID->Data1, pGUID->Data2, pGUID->Data3, + pGUID->Data4[0], pGUID->Data4[1], pGUID->Data4[2], pGUID->Data4[3], + pGUID->Data4[4], pGUID->Data4[5], pGUID->Data4[6], pGUID->Data4[7]); + SetDlgItemText( hDlg, IDC_GUID, szBuff); + + // Change the state and style of the Prev and Next buttons if needed + if (0 == iCurrent) + { + // The Prev button should be disabled + SetFocus(GetDlgItem(hDlg, IDOK)); + SendDlgItemMessage( hDlg, IDC_PREV, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); + SendMessage(hDlg, DM_SETDEFID, IDOK, 0); + EnableWindow(GetDlgItem(hDlg, IDC_PREV), FALSE); + } + else + if (IsWindowEnabled(GetDlgItem(hDlg, IDC_PREV)) == FALSE) + EnableWindow(GetDlgItem(hDlg, IDC_PREV), TRUE); + + if (iCurrent >= (g_iMaxDevices - 1)) + { + // The Next button should be disabled + SetFocus(GetDlgItem(hDlg, IDOK)); + SendDlgItemMessage( hDlg, IDC_NEXT, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); + SendMessage(hDlg, DM_SETDEFID, IDOK, 0); + EnableWindow(GetDlgItem(hDlg, IDC_NEXT), FALSE); + } + else + if (IsWindowEnabled(GetDlgItem(hDlg, IDC_NEXT)) == FALSE) + EnableWindow(GetDlgItem(hDlg, IDC_NEXT), TRUE); +} + + + + +//----------------------------------------------------------------------------- +// Name: InfoDlgProc() +// Desc: The dialog window proc +//----------------------------------------------------------------------------- +LRESULT CALLBACK +InfoDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ +// RECT rc; + static int iCurrent = 0; + static DWORD dwHost = 0; + + switch (uMsg) + { + case WM_INITDIALOG: + // Setup the first devices text + SetInfoDlgText(hDlg, iCurrent, dwHost); + return TRUE; + case WM_COMMAND: + switch (HIWORD(wParam)) + { + case BN_CLICKED: + switch (LOWORD(wParam)) + { + case IDOK: + case IDCANCEL: + EndDialog(hDlg, TRUE); + return TRUE; + case IDC_PREV: + // Show the previous device + if (iCurrent) + iCurrent--; + SetInfoDlgText(hDlg, iCurrent, dwHost); + break; + case IDC_NEXT: + // Show the next device + if (iCurrent < g_iMaxDevices) + iCurrent++; + SetInfoDlgText(hDlg, iCurrent, dwHost); + break; + case IDC_RADIO_HOST: + case IDC_RADIO_DEVICE: + if (dwHost == DDGDI_GETHOSTIDENTIFIER ) + dwHost = 0; + else + dwHost = DDGDI_GETHOSTIDENTIFIER; + SetInfoDlgText(hDlg, iCurrent, dwHost); + break; + } + break; + } + break; + } + + return FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: DDEnumCallbackEx() +// Desc: This callback gets the information for each device enumerated +//----------------------------------------------------------------------------- +BOOL WINAPI +DDEnumCallbackEx(GUID *pGUID, LPSTR pDescription, LPSTR pName, + LPVOID pContext, HMONITOR hm) +{ + LPDIRECTDRAW pDD; // DD1 interface, used to get DD4 interface + LPDIRECTDRAW4 pDD4 = NULL; // DirectDraw4 interface + HRESULT hRet; + + // Create the main DirectDraw object + hRet = DirectDrawCreate(pGUID, &pDD, NULL); + if (hRet != DD_OK) + { + InitFail("DirectDrawCreate FAILED"); + return DDENUMRET_CANCEL; + } + + // Fetch DirectDraw4 interface + hRet = pDD->QueryInterface(IID_IDirectDraw4, (LPVOID *)&pDD4); + if (hRet != DD_OK) + { + InitFail("QueryInterface FAILED"); + return DDENUMRET_CANCEL; + } + + // Get the device information and save it + hRet = pDD4->GetDeviceIdentifier(&g_DeviceInfo[g_iMaxDevices].DeviceInfo,0); + hRet = pDD4->GetDeviceIdentifier(&g_DeviceInfo[g_iMaxDevices].DeviceInfoHost,DDGDI_GETHOSTIDENTIFIER); + + // Finished with the DirectDraw object, so release it + if (pDD4) + pDD4->Release(); + + // Bump to the next open slot or finish the callbacks if full + if (g_iMaxDevices < MAX_DEVICES) + g_iMaxDevices++; + else + return DDENUMRET_CANCEL; + return DDENUMRET_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DDEnumCallback() +// Desc: Old style callback retained for backwards compatibility +//----------------------------------------------------------------------------- +BOOL WINAPI +DDEnumCallback(GUID *pGUID, LPSTR pDescription, LPSTR pName, LPVOID context) +{ + return (DDEnumCallbackEx(pGUID, pDescription, pName, context, NULL)); +} + + + + +//----------------------------------------------------------------------------- +// Name: WinMain() +// Desc: Entry point to the program. Initializes everything and calls +// DirectDrawEnumerateEx() to get all of the device info. +//----------------------------------------------------------------------------- +int PASCAL +WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpszCmdLine, + int nCmdShow) +{ + LPDIRECTDRAWENUMERATEEX pDirectDrawEnumerateEx; + HINSTANCE hDDrawDLL; + + // Do a GetModuleHandle and GetProcAddress in order to get the + // DirectDrawEnumerateEx function + hDDrawDLL = GetModuleHandle("DDRAW"); + if (!hDDrawDLL) + { + InitFail("LoadLibrary() FAILED"); + return -1; + } + pDirectDrawEnumerateEx = (LPDIRECTDRAWENUMERATEEX )GetProcAddress(hDDrawDLL,"DirectDrawEnumerateExA"); + if (pDirectDrawEnumerateEx) + { + pDirectDrawEnumerateEx(DDEnumCallbackEx, NULL, + DDENUM_ATTACHEDSECONDARYDEVICES | + DDENUM_DETACHEDSECONDARYDEVICES | + DDENUM_NONDISPLAYDEVICES); + } + else + { + // Old DirectDraw, so do it the old way + DirectDrawEnumerate(DDEnumCallback, NULL); + } + + if (0 == g_iMaxDevices) + { + InitFail("No devices to enumerate."); + return -1; + } + + // Bring up the dialog to show all the devices + DialogBox(hInstance, MAKEINTRESOURCE(IDD_DRIVERINFO), GetDesktopWindow(), (DLGPROC) InfoDlgProc); + + return 0; +} + + diff --git a/arch/win32/d3dframe/ddmm.h b/arch/win32/d3dframe/ddmm.h new file mode 100644 index 00000000..c77dc9bd --- /dev/null +++ b/arch/win32/d3dframe/ddmm.h @@ -0,0 +1,21 @@ +/*========================================================================== + * + * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved. + * + * File: ddmm.cpp + * Content: Routines for using DirectDraw on a multimonitor system + * + ***************************************************************************/ + +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +IDirectDraw * DirectDrawCreateFromDevice(LPSTR szDevice); +IDirectDraw * DirectDrawCreateFromWindow(HWND hwnd); +int DirectDrawDeviceFromWindow(HWND hwnd, LPSTR szDevice, RECT*prc); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + diff --git a/arch/win32/d3dframe/ddutil.h b/arch/win32/d3dframe/ddutil.h new file mode 100644 index 00000000..7be66461 --- /dev/null +++ b/arch/win32/d3dframe/ddutil.h @@ -0,0 +1,24 @@ +/*========================================================================== + * + * Copyright (C) 1998 Microsoft Corporation. All Rights Reserved. + * + * File: ddutil.cpp + * Content: Routines for loading bitmap and palettes from resources + * + ***************************************************************************/ + +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +extern IDirectDrawPalette *DDLoadPalette(IDirectDraw4 *pdd, LPCSTR szBitmap); +extern IDirectDrawSurface4 *DDLoadBitmap(IDirectDraw4 *pdd, LPCSTR szBitmap, int dx, int dy); +extern HRESULT DDReLoadBitmap(IDirectDrawSurface4 *pdds, LPCSTR szBitmap); +extern HRESULT DDCopyBitmap(IDirectDrawSurface4 *pdds, HBITMAP hbm, int x, int y, int dx, int dy); +extern DWORD DDColorMatch(IDirectDrawSurface4 *pdds, COLORREF rgb); +extern HRESULT DDSetColorKey(IDirectDrawSurface4 *pdds, COLORREF rgb); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + diff --git a/arch/win32/d3dframe/ddutil2.h b/arch/win32/d3dframe/ddutil2.h new file mode 100644 index 00000000..f826f2b2 --- /dev/null +++ b/arch/win32/d3dframe/ddutil2.h @@ -0,0 +1,24 @@ +/*========================================================================== + * + * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved. + * + * File: ddutil.cpp + * Content: Routines for loading bitmap and palettes from resources + * + ***************************************************************************/ + +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +extern IDirectDrawPalette * DDLoadPalette2(IDirectDraw2 *pdd, LPCSTR szBitmap); +extern IDirectDrawSurface3 * DDLoadBitmap2(IDirectDraw2 *pdd, LPCSTR szBitmap, int dx, int dy); +extern HRESULT DDReLoadBitmap2(IDirectDrawSurface3 *pdds, LPCSTR szBitmap); +extern HRESULT DDCopyBitmap2(IDirectDrawSurface3 *pdds, HBITMAP hbm, int x, int y, int dx, int dy); +extern DWORD DDColorMatch2(IDirectDrawSurface3 *pdds, COLORREF rgb); +extern HRESULT DDSetColorKey2(IDirectDrawSurface3 *pdds, COLORREF rgb); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + diff --git a/arch/win32/d3dframe/dsutil.h b/arch/win32/d3dframe/dsutil.h new file mode 100644 index 00000000..66d5363f --- /dev/null +++ b/arch/win32/d3dframe/dsutil.h @@ -0,0 +1,216 @@ +/*========================================================================== + * + * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved. + * + * File: dsutil.cpp + * Content: Routines for dealing with sounds from resources + * + * + ***************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////// +// +// DSLoadSoundBuffer Loads an IDirectSoundBuffer from a Win32 resource in +// the current application. +// +// Params: +// pDS -- Pointer to an IDirectSound that will be used to create +// the buffer. +// +// lpName -- Name of WAV resource to load the data from. Can be a +// resource id specified using the MAKEINTRESOURCE macro. +// +// Returns an IDirectSoundBuffer containing the wave data or NULL on error. +// +// example: +// in the application's resource script (.RC file) +// Turtle WAV turtle.wav +// +// some code in the application: +// IDirectSoundBuffer *pDSB = DSLoadSoundBuffer(pDS, "Turtle"); +// +// if (pDSB) +// { +// IDirectSoundBuffer_Play(pDSB, 0, 0, DSBPLAY_TOEND); +// /* ... */ +// +/////////////////////////////////////////////////////////////////////////////// +IDirectSoundBuffer *DSLoadSoundBuffer(IDirectSound *pDS, LPCTSTR lpName); + +/////////////////////////////////////////////////////////////////////////////// +// +// DSReloadSoundBuffer Reloads an IDirectSoundBuffer from a Win32 resource in +// the current application. normally used to handle +// a DSERR_BUFFERLOST error. +// Params: +// pDSB -- Pointer to an IDirectSoundBuffer to be reloaded. +// +// lpName -- Name of WAV resource to load the data from. Can be a +// resource id specified using the MAKEINTRESOURCE macro. +// +// Returns a BOOL indicating whether the buffer was successfully reloaded. +// +// example: +// in the application's resource script (.RC file) +// Turtle WAV turtle.wav +// +// some code in the application: +// TryAgain: +// HRESULT hres = IDirectSoundBuffer_Play(pDSB, 0, 0, DSBPLAY_TOEND); +// +// if (FAILED(hres)) +// { +// if ((hres == DSERR_BUFFERLOST) && +// DSReloadSoundBuffer(pDSB, "Turtle")) +// { +// goto TryAgain; +// } +// /* deal with other errors... */ +// } +// +/////////////////////////////////////////////////////////////////////////////// +BOOL DSReloadSoundBuffer(IDirectSoundBuffer *pDSB, LPCTSTR lpName); + +/////////////////////////////////////////////////////////////////////////////// +// +// DSGetWaveResource Finds a WAV resource in a Win32 module. +// +// Params: +// hModule -- Win32 module handle of module containing WAV resource. +// Pass NULL to indicate current application. +// +// lpName -- Name of WAV resource to load the data from. Can be a +// resource id specified using the MAKEINTRESOURCE macro. +// +// ppWaveHeader-- Optional pointer to WAVEFORMATEX * to receive a pointer to +// the WAVEFORMATEX header in the specified WAV resource. +// Pass NULL if not required. +// +// ppbWaveData -- Optional pointer to BYTE * to receive a pointer to the +// waveform data in the specified WAV resource. Pass NULL if +// not required. +// +// pdwWaveSize -- Optional pointer to DWORD to receive the size of the +// waveform data in the specified WAV resource. Pass NULL if +// not required. +// +// Returns a BOOL indicating whether a valid WAV resource was found. +// +/////////////////////////////////////////////////////////////////////////////// +BOOL DSGetWaveResource(HMODULE hModule, LPCTSTR lpName, + WAVEFORMATEX **ppWaveHeader, BYTE **ppbWaveData, DWORD *pdwWaveSize); + +/////////////////////////////////////////////////////////////////////////////// +// +// HSNDOBJ Handle to a SNDOBJ object. +// +// SNDOBJs are implemented in dsutil as an example layer built on top +// of DirectSound. +// +// A SNDOBJ is generally used to manage individual +// sounds which need to be played multiple times concurrently. A +// SNDOBJ represents a queue of IDirectSoundBuffer objects which +// all refer to the same buffer memory. +// +// A SNDOBJ also automatically reloads the sound resource when +// DirectSound returns a DSERR_BUFFERLOST +// +/////////////////////////////////////////////////////////////////////////////// +#ifndef _HSNDOBJ_DEFINED +DECLARE_HANDLE32(HSNDOBJ); +#endif + +/////////////////////////////////////////////////////////////////////////////// +// +// SndObjCreate Loads a SNDOBJ from a Win32 resource in +// the current application. +// +// Params: +// pDS -- Pointer to an IDirectSound that will be used to create +// the SNDOBJ. +// +// lpName -- Name of WAV resource to load the data from. Can be a +// resource id specified using the MAKEINTRESOURCE macro. +// +// iConcurrent -- Integer representing the number of concurrent playbacks of +// to plan for. Attempts to play more than this number will +// succeed but will restart the least recently played buffer +// even if it is not finished playing yet. +// +// Returns an HSNDOBJ or NULL on error. +// +// NOTES: +// SNDOBJs automatically restore and reload themselves as required. +// +/////////////////////////////////////////////////////////////////////////////// +HSNDOBJ SndObjCreate(IDirectSound *pDS, LPCTSTR lpName, int iConcurrent); + +/////////////////////////////////////////////////////////////////////////////// +// +// SndObjDestroy Frees a SNDOBJ and releases all of its buffers. +// +// Params: +// hSO -- Handle to a SNDOBJ to free. +// +/////////////////////////////////////////////////////////////////////////////// +void SndObjDestroy(HSNDOBJ hSO); + +/////////////////////////////////////////////////////////////////////////////// +// +// SndObjPlay Plays a buffer in a SNDOBJ. +// +// Params: +// hSO -- Handle to a SNDOBJ to play a buffer from. +// +// dwPlayFlags -- Flags to pass to IDirectSoundBuffer::Play. It is not +// legal to play an SndObj which has more than one buffer +// with the DSBPLAY_LOOPING flag. Pass 0 to stop playback. +// +/////////////////////////////////////////////////////////////////////////////// +BOOL SndObjPlay(HSNDOBJ hSO, DWORD dwPlayFlags); + +/////////////////////////////////////////////////////////////////////////////// +// +// SndObjStop Stops one or more buffers in a SNDOBJ. +// +// Params: +// hSO -- Handle to a SNDOBJ to play a buffer from. +// +/////////////////////////////////////////////////////////////////////////////// +BOOL SndObjStop(HSNDOBJ hSO); + +/////////////////////////////////////////////////////////////////////////////// +// +// SndObjGetFreeBuffer returns one of the cloned buffers that is +// not currently playing +// +// Params: +// hSO -- Handle to a SNDOBJ +// +// NOTES: +// This function is provided so that callers can set things like pan etc +// before playing the buffer. +// +// EXAMPLE: +// ... +// +/////////////////////////////////////////////////////////////////////////////// +IDirectSoundBuffer *SndObjGetFreeBuffer(HSNDOBJ hSO); + +/////////////////////////////////////////////////////////////////////////////// +// +// helper routines +// +/////////////////////////////////////////////////////////////////////////////// + +BOOL DSFillSoundBuffer(IDirectSoundBuffer *pDSB, BYTE *pbWaveData, DWORD dwWaveSize); +BOOL DSParseWaveResource(void *pvRes, WAVEFORMATEX **ppWaveHeader, BYTE **ppbWaveData, DWORD *pdwWaveSize); + +#ifdef __cplusplus +} +#endif + diff --git a/arch/win32/d3dframe/lbprintf.h b/arch/win32/d3dframe/lbprintf.h new file mode 100644 index 00000000..63f1ad39 --- /dev/null +++ b/arch/win32/d3dframe/lbprintf.h @@ -0,0 +1,26 @@ +/*========================================================================== + * + * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved. + * + * File: lbprintf.h + * Content: list box printf header file + * + ***************************************************************************/ +#ifndef __LBPRINTF_INCLUDED__ + +#define __LBPRINTF_INCLUDED__ +#ifdef __cplusplus +extern "C" { +#endif +extern void LBCreate( HWND hWnd, DWORD pos ); +extern void LBSize( DWORD dwWidth, DWORD dwHeight ); +extern void LBClear( void ); +extern void __cdecl LBPrintf( LPSTR fmt, ... ); +extern void __cdecl LBPrintfDDRC( HRESULT rc, LPSTR fmt, ... ); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/arch/win32/d3dframe/resource.h b/arch/win32/d3dframe/resource.h new file mode 100644 index 00000000..cd1a0cc3 --- /dev/null +++ b/arch/win32/d3dframe/resource.h @@ -0,0 +1,32 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by ddenum.rc +// +#define IDI_MAIN_ICON 101 +#define IDD_DRIVERINFO 102 +#define IDC_PREV 1001 +#define IDC_NEXT 1002 +#define IDC_DEVICEID 1003 +#define IDC_VERSION 1004 +#define IDC_DESCRIPTION 1005 +#define IDC_FILENAME 1006 +#define IDC_COUNT 1007 +#define IDC_GUID 1010 +#define IDC_DWVENDORID 1012 +#define IDC_DWDEVICEID 1014 +#define IDC_DWSUBSYS 1015 +#define IDC_DWREVISION 1016 +#define IDC_RADIO_DEVICE 1018 +#define IDC_RADIO_HOST 1019 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 103 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1020 +#define _APS_NEXT_SYMED_VALUE 103 +#endif +#endif diff --git a/arch/win32/d3dframe/userdlg.cpp b/arch/win32/d3dframe/userdlg.cpp new file mode 100644 index 00000000..5bf2bf84 --- /dev/null +++ b/arch/win32/d3dframe/userdlg.cpp @@ -0,0 +1,383 @@ +//----------------------------------------------------------------------------- +// File: UserDlg.cpp +// +// Desc: Support functions for the user select driver dialog. + +// Note: Since this code is destined for a static link library, the +// dialog dox is constructed manually. Otherwise, we would use a resource +// and save many lines of code. Manually constructing dialog boxes is not +// trivial and there are many issues (unicode, dword alignment, etc.) +// involved. +// +// +// Copyright (c) 1997-1998 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- + +#include +#include "D3DEnum.h" +#include +#include "d3dutil.h" + + + +//----------------------------------------------------------------------------- +// Constants and function prototypes for the user select driver dialog +//----------------------------------------------------------------------------- +#define IDC_STATIC 0xffff +#define IDC_DRIVER_COMBO 1000 +#define IDC_DEVICE_COMBO 1001 +#define IDC_MODE_COMBO 1002 + + + + +//----------------------------------------------------------------------------- +// External variables (declared in the D3DEnum.cpp file) +//----------------------------------------------------------------------------- +extern D3DEnum_DriverInfo* g_pCurrentDriver; // The selected DD driver + + + + +//----------------------------------------------------------------------------- +// Name: CopyToWideChar +//----------------------------------------------------------------------------- +static VOID CopyToWideChar( WCHAR** pstrOut, LPTSTR strIn ) +{ + DWORD dwLen = lstrlen( strIn ); + WCHAR* strOut = *pstrOut; + +#ifdef UNICODE // Copy Unicode to Unicode + _wcsncpy( strOut, strIn, dwLen ); + strOut[dwLen] = L'\0'; +#else // Copy Ansi to Unicode + dwLen = MultiByteToWideChar( CP_ACP, 0, strIn, dwLen, strOut, dwLen ); + strOut[dwLen++] = L'\0'; // Add the null terminator +#endif + *pstrOut += dwLen; +} + + + + +//----------------------------------------------------------------------------- +// Name: AddDialogControl() +// Desc: Internal function to help build the user select dialog +//----------------------------------------------------------------------------- +static VOID AddDialogControl( WORD** pp, DWORD dwStyle, SHORT x, SHORT y, + SHORT cx, SHORT cy, WORD id, + LPTSTR strClassName, LPTSTR strTitle ) +{ + // DWORD align the current ptr + DLGITEMTEMPLATE* p = (DLGITEMTEMPLATE*)(((((ULONG)(*pp))+3)>>2)<<2); + + p->style = dwStyle | WS_CHILD | WS_VISIBLE; + p->dwExtendedStyle = 0L; + p->x = x; + p->y = y; + p->cx = cx; + p->cy = cy; + p->id = id; + + *pp = (WORD*)(++p); // Advance ptr + + CopyToWideChar( (WCHAR**)pp, strClassName ); // Set Class name + CopyToWideChar( (WCHAR**)pp, strTitle ); // Set Title + + (*pp)++; // Skip Extra Stuff +} + + + + +//----------------------------------------------------------------------------- +// Name: _BuildUserSelectDialog() +// Desc: Internal function to build the user select dialog +//----------------------------------------------------------------------------- +DLGTEMPLATE* _BuildDriverSelectTemplate() +{ + // Allocate ample memory for building the template + DLGTEMPLATE* pDlgTemplate = new DLGTEMPLATE[50]; + if( NULL == pDlgTemplate ) + return NULL; + ZeroMemory( pDlgTemplate, 50*sizeof(DLGTEMPLATE) ); + + // Fill in the DLGTEMPLATE info + DLGTEMPLATE* pdt = pDlgTemplate; + pdt->style = DS_MODALFRAME | DS_NOIDLEMSG | DS_SETFOREGROUND | + DS_3DLOOK | DS_CENTER | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU | DS_SETFONT; + pdt->dwExtendedStyle = 0L; + pdt->cdit = 8; + pdt->x = 0; + pdt->y = 0; + pdt->cx = 179; + pdt->cy = 84; + + // Add menu array, class array, dlg title, font size and font name + WORD* pw = (WORD*)(++pdt); + *pw++ = L'\0'; // Set Menu array to nothing + *pw++ = L'\0'; // Set Class array to nothing + CopyToWideChar( (WCHAR**)&pw, TEXT( "Select New Direct3D Driver" ) ); // Dlg title + *pw++ = 8; // Font Size + CopyToWideChar( (WCHAR**)&pw, TEXT("Arial") ); // Font Name + + // Add the okay button + AddDialogControl( &pw, BS_PUSHBUTTON | WS_TABSTOP, 65, 65, 51, 14, + IDOK, TEXT("BUTTON"), TEXT("OK") ); + + // Add the cancel button + AddDialogControl( &pw, BS_PUSHBUTTON | WS_TABSTOP, 123, 65, 51, 14, + IDCANCEL, TEXT("BUTTON"), TEXT("Cancel") ); + + // Add the driver select combobox + AddDialogControl( &pw, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP, + 36, 5, 138, 45, + IDC_DRIVER_COMBO, TEXT("COMBOBOX"), TEXT("") ); + + // Add the device select combobox + AddDialogControl( &pw, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP, + 36, 24, 138, 45, + IDC_DEVICE_COMBO, TEXT("COMBOBOX"), TEXT("") ); + + // Add the mode select combobox + AddDialogControl( &pw, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP, + 36, 44, 138, 45, + IDC_MODE_COMBO, TEXT("COMBOBOX"), TEXT("") ); + + // Add the "Driver:" text + AddDialogControl( &pw, SS_LEFT, 5, 5, 22, 13, + IDC_STATIC, TEXT("STATIC"), TEXT("Driver:") ); + + // Add the "Device:" text + AddDialogControl( &pw, SS_LEFT, 5, 24, 25, 13, + IDC_STATIC, TEXT("STATIC"), TEXT("Device:") ); + + // Add the "Mode:" text + AddDialogControl( &pw, SS_LEFT, 5, 44, 22, 13, + IDC_STATIC, TEXT("STATIC"), TEXT("Mode:") ); + + return pDlgTemplate; +} + + + + +//----------------------------------------------------------------------------- +// Name: UpdateComboBoxesContent() +// Desc: Builds the list of drivers, devices and modes for the combo boxes +// in the driver select dialog box. +//----------------------------------------------------------------------------- +static VOID UpdateComboBoxesContent( HWND hDlg, + D3DEnum_DriverInfo** ppCurrentDriver, + D3DEnum_DeviceInfo** ppCurrentDevice, + D3DEnum_ModeInfo** ppCurrentMode, + BOOL bWindowed ) +{ + // Check the parameters + if( (NULL==ppCurrentDriver) || (NULL==ppCurrentDevice) || + (NULL==ppCurrentMode) ) + return; + + // If the specified driver is NULL, use the first one in the list + if( NULL == *ppCurrentDriver) + (*ppCurrentDriver) = D3DEnum_GetFirstDriver(); + + // If the specified device is NULL, use the first one in the list + if( NULL == *ppCurrentDevice) + (*ppCurrentDevice) = (*ppCurrentDriver)->pFirstDevice; + + // Reset the content in each of the combo boxes + SendDlgItemMessage( hDlg, IDC_DRIVER_COMBO, CB_RESETCONTENT, 0, 0 ); + SendDlgItemMessage( hDlg, IDC_DEVICE_COMBO, CB_RESETCONTENT, 0, 0 ); + SendDlgItemMessage( hDlg, IDC_MODE_COMBO, CB_RESETCONTENT, 0, 0 ); + + // Build the list of drivers for the combo box + for( D3DEnum_DriverInfo* pDriver = D3DEnum_GetFirstDriver(); pDriver; + pDriver = pDriver->pNext ) + { + // Add driver desc to the combo box + DWORD dwItem = SendDlgItemMessage( hDlg, IDC_DRIVER_COMBO, + CB_ADDSTRING, 0, (LPARAM)pDriver->strDesc ); + + // Associate DriverInfo ptr with the item in the combo box + SendDlgItemMessage( hDlg, IDC_DRIVER_COMBO, CB_SETITEMDATA, + (WPARAM)dwItem, (LPARAM)pDriver ); + + // If this is the current driver, set is as the current selection + if( pDriver == (*ppCurrentDriver) ) + SendDlgItemMessage( hDlg, IDC_DRIVER_COMBO, CB_SETCURSEL, + (WPARAM)dwItem, 0L ); + } + + // Build the list of devices for the combo box + for( D3DEnum_DeviceInfo* pDevice = (*ppCurrentDriver)->pFirstDevice; pDevice; + pDevice = pDevice->pNext ) + { + // Add device name to the combo box + DWORD dwItem = SendDlgItemMessage( hDlg, IDC_DEVICE_COMBO, + CB_ADDSTRING, 0, (LPARAM)pDevice->strName ); + + // Associate DeviceInfo ptr with the item in the combo box + SendDlgItemMessage( hDlg, IDC_DEVICE_COMBO, CB_SETITEMDATA, + (WPARAM)dwItem, (LPARAM)pDevice ); + + // If this is the current device, set this as the current selection + if( pDevice == (*ppCurrentDevice) ) + SendDlgItemMessage( hDlg, IDC_DEVICE_COMBO, CB_SETCURSEL, + (WPARAM)dwItem, 0L ); + } + + if( (*ppCurrentDriver)->ddDriverCaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED + && ( NULL == (*ppCurrentDriver)->pGUID ) + && (*ppCurrentDevice)->bCompatbileWithDesktop ) + { + // Add windowed mode to the combo box of available modes + DWORD dwItem = SendDlgItemMessage( hDlg, IDC_MODE_COMBO, + CB_ADDSTRING, 0, (LPARAM)TEXT("Windowed mode") ); + + // Associate ModeInfo ptr with the item in the combo box + SendDlgItemMessage( hDlg, IDC_MODE_COMBO, CB_SETITEMDATA, + (WPARAM)dwItem, (LPARAM)NULL ); + + // If the current device is windowed, set this as current + if( bWindowed ) + SendDlgItemMessage( hDlg, IDC_MODE_COMBO, CB_SETCURSEL, + (WPARAM)dwItem, 0L ); + } + + // Build the list of modes for the combo box + for( D3DEnum_ModeInfo* pMode = (*ppCurrentDevice)->pFirstMode; pMode; + pMode = pMode->pNext ) + { + // Add mode desc to the combo box + DWORD dwItem = SendDlgItemMessage( hDlg, IDC_MODE_COMBO, + CB_ADDSTRING, 0, + (LPARAM)pMode->strDesc ); + + // Associate ModeInfo ptr with the item in the combo box + SendDlgItemMessage( hDlg, IDC_MODE_COMBO, CB_SETITEMDATA, + (WPARAM)dwItem, (LPARAM)pMode ); + + // If this is the current mode, set is as the current selection + if( !bWindowed && ( pMode == (*ppCurrentMode) ) ) + SendDlgItemMessage( hDlg, IDC_MODE_COMBO, CB_SETCURSEL, + (WPARAM)dwItem, 0L ); + } +} + + + + +//----------------------------------------------------------------------------- +// Name: _DriverSelectProc() +// Desc: Windows message handling function for the driver select dialog +//----------------------------------------------------------------------------- +BOOL CALLBACK _DriverSelectProc( HWND hDlg, UINT uiMsg, WPARAM wParam, + LPARAM lParam ) +{ + static D3DEnum_DriverInfo *pOldDriver, *pNewDriver; + static D3DEnum_DeviceInfo *pOldDevice, *pNewDevice; + static D3DEnum_ModeInfo *pOldMode, *pNewMode; + static BOOL bOldWindowed, bNewWindowed; + + // Handle the initialization message + if( WM_INITDIALOG == uiMsg ) + { + // Setup temp storage pointers for dialog + pNewDriver = pOldDriver = g_pCurrentDriver; + pNewDevice = pOldDevice = pOldDriver->pCurrentDevice; + pNewMode = pOldMode = pOldDevice->pCurrentMode; + bNewWindowed = bOldWindowed = pOldDevice->bWindowed; + + UpdateComboBoxesContent( hDlg, &pOldDriver, &pOldDevice, + &pOldMode, bOldWindowed ); + return TRUE; + } + + if( WM_COMMAND == uiMsg ) + { + // Handle the case when the user hits the OK button + if( IDOK == LOWORD(wParam) ) + { + // Check if any of the options were changed + if( ( pOldDriver != pNewDriver ) || ( pOldDevice != pNewDevice ) || + ( pOldMode != pNewMode ) || ( bOldWindowed != bNewWindowed ) ) + { + // Set actual ptrs from the temp ptrs used for the dialog + g_pCurrentDriver = pNewDriver; + g_pCurrentDriver->pCurrentDevice = pNewDevice; + g_pCurrentDriver->pCurrentDevice->pCurrentMode = pNewMode; + g_pCurrentDriver->pCurrentDevice->bWindowed = bNewWindowed; + + EndDialog( hDlg, IDOK ); + return TRUE; + } + else + { + EndDialog( hDlg, IDCANCEL ); + return TRUE; + } + } + + // Handle the case when the user hits the Cancel button + else if( IDCANCEL == LOWORD(wParam) ) + { + EndDialog( hDlg, IDCANCEL ); + return TRUE; + } + + // Handle the case when the user chooses an item in the combo boxes. + else if( CBN_SELENDOK == HIWORD(wParam) ) + { + DWORD dwIndex = SendMessage( (HWND)lParam, CB_GETCURSEL, + 0, 0 ); + LONG pNewObject = SendMessage( (HWND)lParam, CB_GETITEMDATA, + dwIndex, 0 ); + + if( (CB_ERR==dwIndex) ) + return TRUE; + + // Handle the case where one of these may have changed. The + // combo boxes will need to be updated to reflect the changes. + switch( LOWORD( wParam ) ) + { + case IDC_DRIVER_COMBO: + if( pNewObject && pNewObject != (LONG)pNewDriver ) + { + pNewDriver = (D3DEnum_DriverInfo*)pNewObject; + pNewDevice = pNewDriver->pCurrentDevice;; + pNewMode = pNewDevice->pCurrentMode; + bNewWindowed = pNewDevice->bWindowed; + } + break; + case IDC_DEVICE_COMBO: + if( pNewObject && pNewObject != (LONG)pNewDevice ) + { + pNewDevice = (D3DEnum_DeviceInfo*)pNewObject; + pNewMode = pNewDevice->pCurrentMode; + bNewWindowed = pNewDevice->bWindowed; + } + break; + case IDC_MODE_COMBO: + if( pNewObject ) + { + pNewMode = (D3DEnum_ModeInfo*)pNewObject; + bNewWindowed = FALSE; + } + else + bNewWindowed = TRUE; + break; + } + + UpdateComboBoxesContent( hDlg, &pNewDriver, &pNewDevice, + &pNewMode, bNewWindowed ); + + return TRUE; + } + } + return FALSE; +} + + + diff --git a/arch/win32/debug.cpp b/arch/win32/debug.cpp new file mode 100644 index 00000000..f823ced0 --- /dev/null +++ b/arch/win32/debug.cpp @@ -0,0 +1,1168 @@ +/* +**----------------------------------------------------------------------------- +** Name: Debug.cpp +** Purpose: Example debug code for D3D sample +** Notes: +** +** Copyright (C) 199 - 1997 Microsoft Corporation. All Rights Reserved. +**----------------------------------------------------------------------------- +*/ + +/* +**----------------------------------------------------------------------------- +** Includes +**----------------------------------------------------------------------------- +*/ + +#include "pch.h" +#include "Debug.h" +extern "C" { +#include "WinMain.h" +} + + +/* +**----------------------------------------------------------------------------- +** Global variables +**----------------------------------------------------------------------------- +*/ +#define MAX_STRING 256 + +#ifndef NDEBUG + DWORD g_dwDebugLevel = DEBUG_ALWAYS; + BOOL g_fDebug = TRUE; +#else + BOOL g_fDebug = FALSE; +#endif + + + +/* +**----------------------------------------------------------------------------- +** Local prototypes +**----------------------------------------------------------------------------- +*/ + +extern "C" +BOOL GetDDErrorString (HRESULT hResult, LPTSTR lpszError, DWORD cchError); + + + +/* +**----------------------------------------------------------------------------- +** Functions +**----------------------------------------------------------------------------- +*/ + + +/* +**----------------------------------------------------------------------------- +** Name: dprintf +** Purpose: Printf to debug output +**----------------------------------------------------------------------------- +*/ + +#ifndef NDEBUG +void __cdecl dprintf (DWORD dwDebugLevel, LPCTSTR szFormat, ...) +{ + TCHAR szBuffer[MAX_STRING]; + va_list va; + + // Check if current debug level + if (dwDebugLevel < g_dwDebugLevel) + return; + + lstrcpy (szBuffer, START_STR); + va_start(va, szFormat); + wvsprintf (szBuffer+lstrlen (szBuffer), szFormat, va); + va_end(va); + lstrcat (szBuffer, END_STR); + OutputDebugString (szBuffer); +} +#endif // NDEBUG + + + +/* +**----------------------------------------------------------------------------- +** Name: ReportDDError +** Purpose: +**----------------------------------------------------------------------------- +*/ + +void _cdecl ReportDDError (HRESULT hResult, LPCTSTR szFormat, ...) +{ + TCHAR szMsg[MAX_STRING]; + TCHAR szErr[MAX_STRING]; + TCHAR szUnknown[] = TEXT("Unknown"); + DWORD cchErr = sizeof(szErr)/sizeof(TCHAR); + va_list va; + + // Check for Success Error code + if (hResult == DD_OK) + return; + + va_start( va, szFormat ); + wvsprintf (szMsg, szFormat, va); + va_end( va ); + + // Get DD/D3D error string + szErr[0] = 0; + GetDDErrorString (hResult, szErr, cchErr); + wsprintf (szMsg + strlen (szMsg), TEXT(" : DD/D3D Error = %s\r\n"), szErr); + + + // Dump to debugger + DPF (DEBUG_ERROR, TEXT("%s"), szMsg); + + // + // Define the following if you want an in your face Messagebox on errors + // +//#define DEBUG_PROMPTME +#ifdef DEBUG_PROMPTME + HWND hWindow; + + // Pause App + if (g_hWnd) + OnPause (g_hWnd, TRUE); + + // Display Error Message to user + if (g_hWnd) + hWindow = g_hWnd; + else + hWindow = NULL; + + MessageBox (hWindow, szMsg, g_szMainTitle, MB_OK | MB_APPLMODAL); + + // Unpause app + if (g_hWnd) + OnPause (g_hWnd, FALSE); +#endif + +} // ReportDDError + + +#ifndef NDEBUG +ULONG CDebugTracker::s_cLevels = 0; +char CDebugTracker::szsp [80]; + +CDebugTracker::CDebugTracker (LPCSTR lpsz) +{ + m_psz = strdup (lpsz); + m_bReturned = FALSE; + + szsp [s_cLevels] = '/'; + szsp [s_cLevels + 1] = '\0'; + DPF (DEBUG_ALWAYS, "%s%s start", szsp, m_psz); + szsp [s_cLevels] = '|'; + s_cLevels++; +} + +CDebugTracker::~CDebugTracker () +{ + s_cLevels--; + if (!m_bReturned) + { + szsp [s_cLevels + 1] = '\0'; + szsp [s_cLevels] = '\\'; + DPF (DEBUG_ALWAYS, "%s%s end", szsp, m_psz); + } + free ((LPVOID) m_psz); +} + +void __cdecl Return (LPCSTR szFormat, ...) +{ +} +#endif + +/* +**----------------------------------------------------------------------------- +** Name: GetDDErrorString +** Purpose: outputs a debug string to debugger +**----------------------------------------------------------------------------- +*/ + +extern "C" +BOOL GetDDErrorString (HRESULT hResult, LPTSTR lpszErrorBuff, DWORD cchError) +{ + DWORD cLen; + LPTSTR lpszError; + TCHAR szMsg[MAX_STRING]; + + // Check parameters + if (!lpszErrorBuff || !cchError) + { + // Error, invalid parameters + return FALSE; + } + + switch (hResult) + { + case DD_OK: + // The request completed successfully. + lpszError = TEXT("DD_OK"); + break; + + case DDERR_ALREADYINITIALIZED: + // The object has already been initialized. + lpszError = TEXT("DDERR_ALREADYINITIALIZED"); + break; + + case DDERR_BLTFASTCANTCLIP: + // A DirectDrawClipper object is attached to a source surface + // that has passed into a call to the IDirectDrawSurface4::BltFast method. + lpszError = TEXT("DDERR_BLTFASTCANTCLIP"); + break; + + case DDERR_CANNOTATTACHSURFACE: + // A surface cannot be attached to another requested surface. + lpszError = TEXT("DDERR_CANNOTATTACHSURFACE"); + break; + + case DDERR_CANNOTDETACHSURFACE: + // A surface cannot be detached from another requested surface. + lpszError = TEXT("DDERR_CANNOTDETACHSURFACE"); + break; + + case DDERR_CANTCREATEDC: + // Windows cannot create any more device contexts (DCs). + lpszError = TEXT("DDERR_CANTCREATEDC"); + break; + + case DDERR_CANTDUPLICATE: + // Primary and 3D surfaces, or surfaces that are + // implicitly created, cannot be duplicated. + lpszError = TEXT("DDERR_CANTDUPLICATE"); + break; + + case DDERR_CANTLOCKSURFACE: + // Access to this surface is refused because an + // attempt was made to lock the primary surface without DCI support. + lpszError = TEXT("DDERR_CANTLOCKSURFACE"); + break; + + case DDERR_CANTPAGELOCK: + // An attempt to page lock a surface failed. + // Page lock will not work on a display-memory + // surface or an emulated primary surface. + lpszError = TEXT("DDERR_CANTPAGELOCK"); + break; + + case DDERR_CANTPAGEUNLOCK: + // An attempt to page unlock a surface failed. + // Page unlock will not work on a display-memory + // surface or an emulated primary surface. + lpszError = TEXT("DDERR_CANTPAGEUNLOCK"); + break; + + case DDERR_CLIPPERISUSINGHWND: + // An attempt was made to set a clip list for a DirectDrawClipper + // object that is already monitoring a window handle. + lpszError = TEXT("DDERR_CLIPPERISUSINGHWND"); + break; + + case DDERR_COLORKEYNOTSET: + // No source color key is specified for this operation + lpszError = TEXT("DDERR_COLORKEYNOTSET"); + break; + + case DDERR_CURRENTLYNOTAVAIL: + // No support is currently available. + lpszError = TEXT("DDERR_CURRENTLYNOTAVAIL"); + break; + + case DDERR_DCALREADYCREATED: + // A device context (DC) has already been returned for this surface. + // Only one DC can be retrieved for each surface. + lpszError = TEXT("DDERR_DCALREADYCREATED"); + break; + + case DDERR_DIRECTDRAWALREADYCREATED: + // A DirectDraw object representing this driver + // has already been created for this process. + lpszError = TEXT("DDERR_DIRECTDRAWALREADYCREATED"); + break; + + case DDERR_EXCEPTION: + // An exception was encountered while + // performing the requested operation. + lpszError = TEXT("DDERR_EXCEPTION"); + break; + + case DDERR_EXCLUSIVEMODEALREADYSET: + // An attempt was made to set the cooperative + // level when it was already set to exclusive. + lpszError = TEXT("DDERR_EXCLUSIVEMODEALREADYSET"); + break; + + case DDERR_GENERIC: + // There is an undefined error condition. + lpszError = TEXT("DDERR_GENERIC"); + break; + + case DDERR_HEIGHTALIGN: + // The height of the provided rectangle + // is not a multiple of the required alignment. + lpszError = TEXT("DDERR_HEIGHTALIGN"); + break; + + case DDERR_HWNDALREADYSET: + // The DirectDraw cooperative level window + // handle has already been set. It cannot + // be reset while the process has surfaces or palettes created. + lpszError = TEXT("DDERR_HWNDALREADYSET"); + break; + + case DDERR_HWNDSUBCLASSED: + // DirectDraw is prevented from restoring state because the + // DirectDraw cooperative level window handle has been subclassed. + lpszError = TEXT("DDERR_HWNDSUBCLASSED"); + break; + + case DDERR_IMPLICITLYCREATED: + // The surface cannot be restored because + // it is an implicitly created surface. + lpszError = TEXT("DDERR_IMPLICITLYCREATED"); + break; + + case DDERR_INCOMPATIBLEPRIMARY: + // The primary surface creation request + // does not match with the existing primary surface. + lpszError = TEXT("DDERR_INCOMPATIBLEPRIMARY"); + break; + + case DDERR_INVALIDCAPS: + // One or more of the capability bits + // passed to the callback function are incorrect. + lpszError = TEXT("DDERR_INVALIDCAPS"); + break; + + case DDERR_INVALIDCLIPLIST: + // DirectDraw does not support the provided clip list. + lpszError = TEXT("DDERR_INVALIDCLIPLIST"); + break; + + case DDERR_INVALIDDIRECTDRAWGUID: + // The globally unique identifier (GUID) passed to the + // DirectDrawCreate function is not a valid DirectDraw driver identifier. + lpszError = TEXT("DDERR_INVALIDDIRECTDRAWGUID"); + break; + + case DDERR_INVALIDMODE: + // DirectDraw does not support the requested mode. + lpszError = TEXT("DDERR_INVALIDMODE"); + break; + + case DDERR_INVALIDOBJECT: + // DirectDraw received a pointer that was an invalid DirectDraw object. + lpszError = TEXT("DDERR_INVALIDOBJECT"); + break; + + case DDERR_INVALIDPARAMS: + // One or more of the parameters passed to the method are incorrect. + lpszError = TEXT("DDERR_INVALIDPARAMS"); + break; + + case DDERR_INVALIDPIXELFORMAT: + // The pixel format was invalid as specified. + lpszError = TEXT("DDERR_INVALIDPIXELFORMAT"); + break; + + case DDERR_INVALIDPOSITION: + // The position of the overlay on the destination is no longer legal. + lpszError = TEXT("DDERR_INVALIDPOSITION"); + break; + + case DDERR_INVALIDRECT: + // The provided rectangle was invalid. + lpszError = TEXT("DDERR_INVALIDRECT"); + break; + + case DDERR_INVALIDSURFACETYPE: + // The requested operation could not be performed + // because the surface was of the wrong type. + lpszError = TEXT("DDERR_INVALIDSURFACETYPE"); + break; + + case DDERR_LOCKEDSURFACES: + // One or more surfaces are locked, + // causing the failure of the requested operation. + lpszError = TEXT("DDERR_LOCKEDSURFACES"); + break; + + case DDERR_MOREDATA: + // There is more data available than the specified + // buffer size could hold. + lpszError = TEXT("DDERR_MOREDATA"); + break; + + case DDERR_NO3D: + // No 3D hardware or emulation is present. + lpszError = TEXT("DDERR_NO3D"); + break; + + case DDERR_NOALPHAHW: + // No alpha acceleration hardware is present or available, + // causing the failure of the requested operation. + lpszError = TEXT("DDERR_NOALPHAHW"); + break; + + case DDERR_NOBLTHW: + // No blitter hardware is present. + lpszError = TEXT("DDERR_NOBLTHW"); + break; + + case DDERR_NOCLIPLIST: + // No clip list is available. + lpszError = TEXT("DDERR_NOCLIPLIST"); + break; + + case DDERR_NOCLIPPERATTACHED: + // No DirectDrawClipper object is attached to the surface object. + lpszError = TEXT("DDERR_NOCLIPPERATTACHED"); + break; + + case DDERR_NOCOLORCONVHW: + // The operation cannot be carried out because + // no color-conversion hardware is present or available. + lpszError = TEXT("DDERR_NOCOLORCONVHW"); + break; + + case DDERR_NOCOLORKEY: + // The surface does not currently have a color key. + lpszError = TEXT("DDERR_NOCOLORKEY"); + break; + + case DDERR_NOCOLORKEYHW: + // The operation cannot be carried out because there + // is no hardware support for the destination color key. + lpszError = TEXT("DDERR_NOCOLORKEYHW"); + break; + + case DDERR_NOCOOPERATIVELEVELSET: + // A create function is called without the + // IDirectDraw2::SetCooperativeLevel method being called. + lpszError = TEXT("DDERR_NOCOOPERATIVELEVELSET"); + break; + + case DDERR_NODC: + // No DC has ever been created for this surface. + lpszError = TEXT("DDERR_NODC"); + break; + + case DDERR_NODDROPSHW: + // No DirectDraw raster operation (ROP) hardware is available. + lpszError = TEXT("DDERR_NODDROPSHW"); + break; + + case DDERR_NODIRECTDRAWHW: + // Hardware-only DirectDraw object creation is not possible; + // the driver does not support any hardware. + lpszError = TEXT("DDERR_NODIRECTDRAWHW"); + break; + + case DDERR_NODIRECTDRAWSUPPORT: + // DirectDraw support is not possible with the current display driver. + lpszError = TEXT("DDERR_NODIRECTDRAWSUPPORT"); + break; + + case DDERR_NOEMULATION: + // Software emulation is not available. + lpszError = TEXT("DDERR_NOEMULATION"); + break; + + case DDERR_NOEXCLUSIVEMODE: + // The operation requires the application to have + // exclusive mode, but the application does not have exclusive mode. + lpszError = TEXT("DDERR_NOEXCLUSIVEMODE"); + break; + + case DDERR_NOFLIPHW: + // Flipping visible surfaces is not supported. + lpszError = TEXT("DDERR_NOFLIPHW"); + break; + + case DDERR_NOGDI: + // No GDI is present. + lpszError = TEXT("DDERR_NOGDI"); + break; + + case DDERR_NOHWND: + // Clipper notification requires a window handle, + // or no window handle has been previously set + // as the cooperative level window handle. + lpszError = TEXT("DDERR_NOHWND"); + break; + + case DDERR_NOMIPMAPHW: + // The operation cannot be carried out because no + // mipmap texture mapping hardware is present or available. + lpszError = TEXT("DDERR_NOMIPMAPHW"); + break; + + case DDERR_NOMIRRORHW: + // The operation cannot be carried out because + // no mirroring hardware is present or available. + lpszError = TEXT("DDERR_NOMIRRORHW"); + break; + + case DDERR_NONONLOCALVIDMEM: + // An attempt was made to allocate non-local video memory + // from a device that does not support non-local video memory. + lpszError = TEXT("DDERR_NONONLOCALVIDMEM"); + break; + + case DDERR_NOOVERLAYDEST: + // The IDirectDrawSurface4::GetOverlayPosition method + // is called on an overlay that the IDirectDrawSurface4::UpdateOverlay + // method has not been called on to establish a destination. + lpszError = TEXT("DDERR_NOOVERLAYDEST"); + break; + + case DDERR_NOOVERLAYHW: + // The operation cannot be carried out because + // no overlay hardware is present or available. + lpszError = TEXT("DDERR_NOOVERLAYHW"); + break; + + case DDERR_NOPALETTEATTACHED: + // No palette object is attached to this surface. + lpszError = TEXT("DDERR_NOPALETTEATTACHED"); + break; + + case DDERR_NOPALETTEHW: + // There is no hardware support for 16- or 256-color palettes. + lpszError = TEXT("DDERR_NOPALETTEHW"); + break; + + case DDERR_NORASTEROPHW: + // The operation cannot be carried out because + // no appropriate raster operation hardware is present or available. + lpszError = TEXT("DDERR_NORASTEROPHW"); + break; + + case DDERR_NOROTATIONHW: + // The operation cannot be carried out because + // no rotation hardware is present or available. + lpszError = TEXT("DDERR_NOROTATIONHW"); + break; + + case DDERR_NOSTRETCHHW: + // The operation cannot be carried out because + // there is no hardware support for stretching. + lpszError = TEXT("DDERR_NOSTRETCHHW"); + break; + + case DDERR_NOT4BITCOLOR: + // The DirectDrawSurface object is not using a + // 4-bit color palette and the requested operation + // requires a 4-bit color palette. + lpszError = TEXT("DDERR_NOT4BITCOLOR"); + break; + + case DDERR_NOT4BITCOLORINDEX: + // The DirectDrawSurface object is not using a 4-bit + // color index palette and the requested operation + // requires a 4-bit color index palette. + lpszError = TEXT("DDERR_NOT4BITCOLORINDEX"); + break; + + case DDERR_NOT8BITCOLOR: + // The DirectDrawSurface object is not using an 8-bit + // color palette and the requested operation requires + // an 8-bit color palette. + lpszError = TEXT("DDERR_NOT8BITCOLOR"); + break; + + case DDERR_NOTAOVERLAYSURFACE: + // An overlay component is called for a non-overlay surface. + lpszError = TEXT("DDERR_NOTAOVERLAYSURFACE"); + break; + + case DDERR_NOTEXTUREHW: + // The operation cannot be carried out because no + // texture-mapping hardware is present or available. + lpszError = TEXT("DDERR_NOTEXTUREHW"); + break; + + case DDERR_NOTFLIPPABLE: + // An attempt has been made to flip a surface that cannot be flipped. + lpszError = TEXT("DDERR_NOTFLIPPABLE"); + break; + + case DDERR_NOTFOUND: + // The requested item was not found. + lpszError = TEXT("DDERR_NOTFOUND"); + break; + + case DDERR_NOTINITIALIZED: + // An attempt was made to call an interface method of a DirectDraw object + // created by CoCreateInstance before the object was initialized. + lpszError = TEXT("DDERR_NOTINITIALIZED"); + break; + + case DDERR_NOTLOCKED: + // An attempt is made to unlock a surface that was not locked. + lpszError = TEXT("DDERR_NOTLOCKED"); + break; + + case DDERR_NOTPAGELOCKED: + // An attempt is made to page unlock a surface + // with no outstanding page locks. + lpszError = TEXT("DDERR_NOTPAGELOCKED"); + break; + + case DDERR_NOTPALETTIZED: + // The surface being used is not a palette-based surface. + lpszError = TEXT("DDERR_NOTPALETTIZED"); + break; + + case DDERR_NOVSYNCHW: + // The operation cannot be carried out because + // there is no hardware support for vertical blank synchronized operations. + lpszError = TEXT("DDERR_NOVSYNCHW"); + break; + + case DDERR_NOZBUFFERHW: + // The operation to create a z-buffer in display memory + // or to perform a blit using a z-buffer cannot be carried + // out because there is no hardware support for z-buffers. + lpszError = TEXT("DDERR_NOZBUFFERHW"); + break; + + case DDERR_NOZOVERLAYHW: + // The overlay surfaces cannot be z-layered based + // on the z-order because the hardware does not + // support z-ordering of overlays. + lpszError = TEXT("DDERR_NOZOVERLAYHW"); + break; + + case DDERR_OUTOFCAPS: + // The hardware needed for the requested operation has already been allocated. + lpszError = TEXT("DDERR_OUTOFCAPS"); + break; + + case DDERR_OUTOFMEMORY: + // DirectDraw does not have enough memory to perform the operation. + lpszError = TEXT("DDERR_OUTOFMEMORY"); + break; + + case DDERR_OUTOFVIDEOMEMORY: + // DirectDraw does not have enough display memory to perform the operation. + lpszError = TEXT("DDERR_OUTOFVIDEOMEMORY"); + break; + + case DDERR_OVERLAYCANTCLIP: + // The hardware does not support clipped overlays. + lpszError = TEXT("DDERR_OVERLAYCANTCLIP"); + break; + + case DDERR_OVERLAYCOLORKEYONLYONEACTIVE: + // An attempt was made to have more than one color key active on an overlay. + lpszError = TEXT("DDERR_OVERLAYCOLORKEYONLYONEACTIVE"); + break; + + case DDERR_OVERLAYNOTVISIBLE: + // The IDirectDrawSurface4::GetOverlayPosition method is called on a hidden overlay. + lpszError = TEXT("DDERR_OVERLAYNOTVISIBLE"); + break; + + case DDERR_PALETTEBUSY: + // Access to this palette is refused + // because the palette is locked by another thread. + lpszError = TEXT("DDERR_PALETTEBUSY"); + break; + + case DDERR_PRIMARYSURFACEALREADYEXISTS: + // This process has already created a primary surface. + lpszError = TEXT("DDERR_PRIMARYSURFACEALREADYEXISTS"); + break; + + case DDERR_REGIONTOOSMALL: + // The region passed to the + // IDirectDrawClipper::GetClipList method is too small. + lpszError = TEXT("DDERR_REGIONTOOSMALL"); + break; + + case DDERR_SURFACEALREADYATTACHED: + // An attempt was made to attach a surface to + // another surface to which it is already attached. + lpszError = TEXT("DDERR_SURFACEALREADYATTACHED"); + break; + + case DDERR_SURFACEALREADYDEPENDENT: + // An attempt was made to make a surface a dependency + // of another surface to which it is already dependent. + lpszError = TEXT("DDERR_SURFACEALREADYDEPENDENT"); + break; + + case DDERR_SURFACEBUSY: + // Access to the surface is refused because the + // surface is locked by another thread. + lpszError = TEXT("DDERR_SURFACEBUSY"); + break; + + case DDERR_SURFACEISOBSCURED: + // Access to the surface is refused + // because the surface is obscured. + lpszError = TEXT("DDERR_SURFACEISOBSCURED"); + break; + + case DDERR_SURFACELOST: + // Access to the surface is refused because the + // surface memory is gone. The DirectDrawSurface + // object representing this surface should have + // the IDirectDrawSurface4::Restore method called on it. + lpszError = TEXT("DDERR_SURFACELOST"); + break; + + case DDERR_SURFACENOTATTACHED: + // The requested surface is not attached. + lpszError = TEXT("DDERR_SURFACENOTATTACHED"); + break; + + case DDERR_TOOBIGHEIGHT: + // The height requested by DirectDraw is too large. + lpszError = TEXT("DDERR_TOOBIGHEIGHT"); + break; + + case DDERR_TOOBIGSIZE: + // The size requested by DirectDraw is too large. + // However, the individual height and width are OK. + lpszError = TEXT("DDERR_TOOBIGSIZE"); + break; + + case DDERR_TOOBIGWIDTH: + // The width requested by DirectDraw is too large. + lpszError = TEXT("DDERR_TOOBIGWIDTH"); + break; + + case DDERR_UNSUPPORTED: + // The operation is not supported. + lpszError = TEXT("DDERR_UNSUPPORTED"); + break; + + case DDERR_UNSUPPORTEDFORMAT: + // The FourCC format requested is not supported by DirectDraw. + lpszError = TEXT("DDERR_UNSUPPORTEDFORMAT"); + break; + + case DDERR_UNSUPPORTEDMASK: + // The bitmask in the pixel format requested is not supported by DirectDraw. + lpszError = TEXT("DDERR_UNSUPPORTEDMASK"); + break; + + case DDERR_UNSUPPORTEDMODE: + // The display is currently in an unsupported mode. + lpszError = TEXT("DDERR_UNSUPPORTEDMODE"); + break; + + case DDERR_VERTICALBLANKINPROGRESS: + // A vertical blank is in progress. + lpszError = TEXT("DDERR_VERTICALBLANKINPROGRESS"); + break; + + case DDERR_WASSTILLDRAWING: + // The previous blit operation that is transferring + // information to or from this surface is incomplete. + lpszError = TEXT("DDERR_WASSTILLDRAWING"); + break; + + case DDERR_WRONGMODE: + // This surface cannot be restored because it was created in a different mode. + lpszError = TEXT("DDERR_WRONGMODE"); + break; + + case DDERR_XALIGN: + // The provided rectangle was not horizontally aligned on a required boundary. + lpszError = TEXT("DDERR_XALIGN"); + break; + + case DDERR_VIDEONOTACTIVE: + // The video port is not active + lpszError = TEXT("DDERR_VIDEONOTACTIVE"); + break; + + + // + // D3D Immediate Mode Errors + // + + case D3DERR_BADMAJORVERSION: + // ??? + lpszError = TEXT("D3DERR_BADMAJORVERSION"); + break; + + case D3DERR_BADMINORVERSION: + // ??? + lpszError = TEXT("D3DERR_BADMINORVERSION"); + break; + + case D3DERR_INVALID_DEVICE: + // ??? + lpszError = TEXT("D3DERR_INVALID_DEVICE"); + break; + + case D3DERR_INITFAILED: + // ??? + lpszError = TEXT("D3DERR_INITFAILED"); + break; + + case D3DERR_EXECUTE_CREATE_FAILED: + // ??? + lpszError = TEXT("D3DERR_EXECUTE_CREATE_FAILED"); + break; + + case D3DERR_EXECUTE_DESTROY_FAILED: + // ??? + lpszError = TEXT("D3DERR_EXECUTE_DESTROY_FAILED"); + break; + + case D3DERR_EXECUTE_LOCK_FAILED: + // ??? + lpszError = TEXT("D3DERR_EXECUTE_LOCK_FAILED"); + break; + + case D3DERR_EXECUTE_UNLOCK_FAILED: + // ??? + lpszError = TEXT("D3DERR_EXECUTE_UNLOCK_FAILED"); + break; + + case D3DERR_EXECUTE_LOCKED: + // ??? + lpszError = TEXT("D3DERR_EXECUTE_LOCKED"); + break; + + case D3DERR_EXECUTE_NOT_LOCKED: + // ??? + lpszError = TEXT("D3DERR_EXECUTE_NOT_LOCKED"); + break; + + case D3DERR_EXECUTE_FAILED: + // ??? + lpszError = TEXT("D3DERR_EXECUTE_FAILED"); + break; + + case D3DERR_EXECUTE_CLIPPED_FAILED: + // ??? + lpszError = TEXT("D3DERR_CLIPPED_FAILED"); + break; + + case D3DERR_TEXTURE_NO_SUPPORT: + // ??? + lpszError = TEXT("D3DERR_TEXTURE_NO_SUPPORT"); + break; + + case D3DERR_TEXTURE_CREATE_FAILED: + // ??? + lpszError = TEXT("D3DERR_TEXTURE_CREATE_FAILED"); + break; + + case D3DERR_TEXTURE_DESTROY_FAILED: + // ??? + lpszError = TEXT("D3DERR_TEXTURE_DESTROY_FAILED"); + break; + + case D3DERR_TEXTURE_LOCK_FAILED: + // ??? + lpszError = TEXT("D3DERR_TEXTURE_LOCK_FAILED"); + break; + + case D3DERR_TEXTURE_UNLOCK_FAILED: + // ??? + lpszError = TEXT("D3DERR_TEXTURE_UNLOCK_FAILED"); + break; + + case D3DERR_TEXTURE_LOAD_FAILED: + // ??? + lpszError = TEXT("D3DERR_LOAD_FAILED"); + break; + + case D3DERR_TEXTURE_SWAP_FAILED: + // ??? + lpszError = TEXT("D3DERR_SWAP_FAILED"); + break; + + case D3DERR_TEXTURE_LOCKED: + // ??? + lpszError = TEXT("D3DERR_TEXTURE_LOCKED"); + break; + + case D3DERR_TEXTURE_NOT_LOCKED: + // ??? + lpszError = TEXT("D3DERR_TEXTURE_NOT_LOCKED"); + break; + + case D3DERR_TEXTURE_GETSURF_FAILED: + // ??? + lpszError = TEXT("D3DERR_TEXTURE_GETSURF_FAILED"); + break; + + case D3DERR_MATRIX_CREATE_FAILED: + // ??? + lpszError = TEXT("D3DERR_MATRIX_CREATE_FAILED"); + break; + + case D3DERR_MATRIX_DESTROY_FAILED: + // ??? + lpszError = TEXT("D3DERR_MATRIX_DESTROY_FAILED"); + break; + + case D3DERR_MATRIX_SETDATA_FAILED: + // ??? + lpszError = TEXT("D3DERR_MATRIX_SETDATA_FAILED"); + break; + + case D3DERR_MATRIX_GETDATA_FAILED: + // ??? + lpszError = TEXT("D3DERR_MAXTRIX_GETDATA_FAILED"); + break; + + case D3DERR_SETVIEWPORTDATA_FAILED: + // ??? + lpszError = TEXT("D3DERR_SETVIEWPORTDATA_FAILED"); + break; + + case D3DERR_INVALIDCURRENTVIEWPORT: + // ??? + lpszError = TEXT("D3DERR_INVALIDCURRENTVIEWPORT"); + break; + + case D3DERR_INVALIDPRIMITIVETYPE: + // ??? + lpszError = TEXT("D3DERR_INVALIDPRIMITIVETYPE"); + break; + + case D3DERR_INVALIDVERTEXTYPE: + // ??? + lpszError = TEXT("D3DERR_INVALIDVERTEXTYPE"); + break; + + case D3DERR_TEXTURE_BADSIZE: + // ??? + lpszError = TEXT("D3DERR_TEXTURE_BADSIZE"); + break; + + case D3DERR_MATERIAL_CREATE_FAILED: + // ??? + lpszError = TEXT("D3DERR_MATERIAL_CREATE_FAILED"); + break; + + case D3DERR_MATERIAL_DESTROY_FAILED: + // ??? + lpszError = TEXT("D3DERR_MATERIAL_DESTROY_FAILED"); + break; + + case D3DERR_MATERIAL_SETDATA_FAILED: + // ??? + lpszError = TEXT("D3DERR_MATERIAL_SETDATA_FAILED"); + break; + + case D3DERR_MATERIAL_GETDATA_FAILED: + // ??? + lpszError = TEXT("D3DERR_MATERIAL_GETDATA_FAILED"); + break; + + case D3DERR_INVALIDPALETTE: + // ??? + lpszError = TEXT("D3DERR_INVALIDPALETTE"); + break; + + case D3DERR_ZBUFF_NEEDS_SYSTEMMEMORY: + // ??? + lpszError = TEXT("D3DERR_ZBUFF_NEEDS_SYSTEMMEMORY"); + break; + + case D3DERR_ZBUFF_NEEDS_VIDEOMEMORY: + // ??? + lpszError = TEXT("D3DERR_ZBUFF_NEEDS_VIDEOMEMORY"); + break; + + case D3DERR_SURFACENOTINVIDMEM: + // ??? + lpszError = TEXT("D3DERR_SURFACENOTINVIDMEM"); + break; + + case D3DERR_LIGHT_SET_FAILED: + // ??? + lpszError = TEXT("D3DERR_LIGHT_SET_FAILED"); + break; + + case D3DERR_LIGHTHASVIEWPORT: + // ??? + lpszError = TEXT("D3DERR_LIGHTHASVIEWPORT"); + break; + + case D3DERR_LIGHTNOTINTHISVIEWPORT: + // ??? + lpszError = TEXT("D3DERR_LIGHTNOTINTHISVIEWPORT"); + break; + + case D3DERR_SCENE_IN_SCENE: + // ??? + lpszError = TEXT("D3DERR_SCENE_IN_SCENE"); + break; + + case D3DERR_SCENE_NOT_IN_SCENE: + // ??? + lpszError = TEXT("D3DERR_SCENE_NOT_IN_SCENE"); + break; + + case D3DERR_SCENE_BEGIN_FAILED: + // ??? + lpszError = TEXT("D3DERR_SCENE_BEGIN_FAILED"); + break; + + case D3DERR_SCENE_END_FAILED: + // ??? + lpszError = TEXT("D3DERR_SCENE_END_FAILED"); + break; + + case D3DERR_INBEGIN: + // ??? + lpszError = TEXT("D3DERR_INBEGIN"); + break; + + case D3DERR_NOTINBEGIN: + // ??? + lpszError = TEXT("D3DERR_NOTINBEGIN"); + break; + + case D3DERR_NOVIEWPORTS: + // ??? + lpszError = TEXT("D3DERR_NOVIEWPORTS"); + break; + + case D3DERR_VIEWPORTDATANOTSET: + // ??? + lpszError = TEXT("D3DERR_VIEWPORTDATANOTSET"); + break; + + case D3DERR_VIEWPORTHASNODEVICE: + // ??? + lpszError = TEXT("D3DERR_VIEWPORTHASNODEVICE"); + break; + + + // + // D3D Retained Mode Errors + // +#if 0 + case D3DRMERR_BADOBJECT: + // ??? + lpszError = TEXT("D3DRMERR_BADOBJECT"); + break; + + case D3DRMERR_BADTYPE: + // ??? + lpszError = TEXT("D3DRMERR_BADTYPE"); + break; + + case D3DRMERR_BADALLOC: + // ??? + lpszError = TEXT("D3DRMERR_BADALLOC"); + break; + + case D3DRMERR_FACEUSED: + // ??? + lpszError = TEXT("D3DRMERR_FACEUSED"); + break; + + case D3DRMERR_NOTFOUND: + // ??? + lpszError = TEXT("D3DRMERR_NOTFOUND"); + break; + + case D3DRMERR_NOTDONEYET: + // ??? + lpszError = TEXT("D3DRMERR_NOTDONEYET"); + break; + + case D3DRMERR_FILENOTFOUND: + // ??? + lpszError = TEXT("D3DRMERR_FILENOTFOUND"); + break; + + case D3DRMERR_BADFILE: + // ??? + lpszError = TEXT("D3DRMERR_BADFILE"); + break; + + case D3DRMERR_BADDEVICE: + // ??? + lpszError = TEXT("D3DRMERR_BADDEVICE"); + break; + + case D3DRMERR_BADVALUE: + // ??? + lpszError = TEXT("D3DRMERR_BADVALUE"); + break; + + case D3DRMERR_BADMAJORVERSION: + // ??? + lpszError = TEXT("D3DRMERR_BADMAJORVERSION"); + break; + + case D3DRMERR_BADMINORVERSION: + // ??? + lpszError = TEXT("D3DRMERR_BADMINORVERSION"); + break; + + case D3DRMERR_UNABLETOEXECUTE: + // ??? + lpszError = TEXT("D3DRMERR_BADMINORVERSION"); + break; +#endif // D3DRM_ERRORS + + + // + // Application defined errors + // + case APPERR_GENERIC: + // Generic Error + lpszError = TEXT("APPERR_GENERIC"); + break; + + case APPERR_INVALIDPARAMS: + // Invalid Parameters passed into function + lpszError = TEXT("APPERR_INVALIDPARAMS"); + break; + + case APPERR_NOTINITIALIZED: + // Programmer error, called function without proper initialization + lpszError = TEXT("APPERR_NOT_INITIALIZED"); + break; + + default: + // Unknown DD/D3D/App Error + wsprintf (szMsg, "Unknown Error #%ld", (DWORD)(hResult & 0x0000FFFFL)); + lpszError = szMsg; + break; + } + + // Copy DD/D3D Error string to buff + cLen = strlen (lpszError); + if (cLen >= cchError) + { + cLen = cchError - 1; + } + + if (cLen) + { + strncpy (lpszErrorBuff, lpszError, cLen); + lpszErrorBuff[cLen] = 0; + } + + return TRUE; +} // End GetDDErrorString + + + + +/* +**----------------------------------------------------------------------------- +** End of File +**----------------------------------------------------------------------------- +*/ + + diff --git a/arch/win32/descent.ico b/arch/win32/descent.ico new file mode 100644 index 0000000000000000000000000000000000000000..cf75b7457372f2266b007bfdfe42049afd98a133 GIT binary patch literal 766 zcmbV~u};G<6h&`Rq&QRR1%;^@`3w3@P%OVJoOZi-ZXG+HL88 zI`HD_m*e}MT`L6=K2!!_n$NHx1 z;0(FW`-Ys@?w&SlioMky_NElWHq~|A}PCPZt(`-PRy#s}`2WDTu-8ZF7)>>4R7W +#include +#include +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +#include + +#include "error.h" +#include "mono.h" +#include "fix.h" +#include "vecmat.h" +#include "gr.h" // needed for piggy.h +#include "piggy.h" +#include "digi.h" +#include "sounds.h" +#include "wall.h" +#include "newdemo.h" +#include "kconfig.h" +#include "hmpfile.h" +hmp_file *hmp = NULL; + +#ifdef DIGI_SOUND +#define MAX_SOUND_SLOTS 32 +#define MIN_VOLUME 10 + + +#define SOF_USED 1 // Set if this sample is used +#define SOF_PLAYING 2 // Set if this sample is playing on a channel +#define SOF_LINK_TO_OBJ 4 // Sound is linked to a moving object. If object dies, then finishes play and quits. +#define SOF_LINK_TO_POS 8 // Sound is linked to segment, pos +#define SOF_PLAY_FOREVER 16 // Play forever (or until level is stopped), otherwise plays once + +typedef struct sound_object { + short signature; // A unique signature to this sound + ubyte flags; // Used to tell if this slot is used and/or currently playing, and how long. + fix max_volume; // Max volume that this sound is playing at + fix max_distance; // The max distance that this sound can be heard at... + int volume; // Volume that this sound is playing at + int pan; // Pan value that this sound is playing at + int handle; // What handle this sound is playing on. Valid only if SOF_PLAYING is set. + short soundnum; // The sound number that is playing + union { + struct { + short segnum; // Used if SOF_LINK_TO_POS field is used + short sidenum; + vms_vector position; + }pos; + struct { + short objnum; // Used if SOF_LINK_TO_OBJ field is used + short objsignature; + }obj; + }link; +} sound_object; +#define lp_segnum link.pos.segnum +#define lp_sidenum link.pos.sidenum +#define lp_position link.pos.position + +#define lo_objnum link.obj.objnum +#define lo_objsignature link.obj.objsignature + +#define MAX_SOUND_OBJECTS 16 +sound_object SoundObjects[MAX_SOUND_OBJECTS]; +short next_signature=0; + + +//added/changed on 980905 by adb to make sfx volume work +#define SOUND_MAX_VOLUME F1_0 +int digi_volume = SOUND_MAX_VOLUME; +//end edit by adb + +LPDIRECTSOUND lpds; +WAVEFORMATEX waveformat; +DSBUFFERDESC dsbd; + +extern HWND g_hWnd; + +struct sound_slot { + int soundno; + int playing; // Is there a sample playing on this channel? + int looped; // Play this sample looped? + fix pan; // 0 = far left, 1 = far right + fix volume; // 0 = nothing, 1 = fully on + //changed on 980905 by adb from char * to unsigned char * + unsigned char *samples; + //end changes by adb + unsigned int length; // Length of the sample + unsigned int position; // Position we are at at the moment. + LPDIRECTSOUNDBUFFER lpsb; +} SoundSlots[MAX_SOUND_SLOTS]; + + +int digi_lomem = 0; +int midi_volume = 255; +int digi_midi_song_playing = 0; +int digi_last_midi_song = 0; +int digi_last_midi_song_loop = 0; + +static int digi_initialised = 0; +static int digi_atexit_initialised=0; + +static int digi_sounds_initialized = 0; + +//added on 980905 by adb to add rotating/volume based sound kill system +static int digi_max_channels = 16; +static int next_handle = 0; +int SampleHandles[32]; +void reset_sounds_on_channel(int channel); +//end edit by adb + +void digi_reset_digi_sounds(void); + +void digi_reset() { } + +void digi_close(void) { + if(digi_initialised) + IDirectSound_Release(lpds); + digi_initialised = 0; +} + +/* Initialise audio devices. */ +int digi_init() +{ + HRESULT hr; + + if (!digi_initialised && g_hWnd){ + + memset(&waveformat, 0, sizeof(waveformat)); + waveformat.wFormatTag=WAVE_FORMAT_PCM; + waveformat.wBitsPerSample=8; + waveformat.nChannels = 1; + waveformat.nSamplesPerSec = 11025; + waveformat.nBlockAlign = + waveformat.nChannels * (waveformat.wBitsPerSample/8); + waveformat.nAvgBytesPerSec = + waveformat.nSamplesPerSec * waveformat.nBlockAlign; + + if ((hr = DirectSoundCreate(NULL, &lpds, NULL)) != DS_OK) + return -1; + + if ((hr = IDirectSound_SetCooperativeLevel(lpds, g_hWnd, DSSCL_PRIORITY)) //hWndMain + != DS_OK) + { + IDirectSound_Release(lpds); + return -1; + } + + memset(&dsbd, 0, sizeof(dsbd)); + dsbd.dwSize = sizeof(dsbd); + dsbd.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_GETCURRENTPOSITION2; + dsbd.dwBufferBytes = 8192; + dsbd.dwReserved=0; + dsbd.lpwfxFormat = &waveformat; + + digi_initialised = 1; +} + + if (!digi_atexit_initialised){ + atexit(digi_close); + digi_atexit_initialised=1; + } + return 0; +} + +/* Find the sound which actually equates to a sound number */ +int digi_xlat_sound(int soundno) +{ + if ( soundno < 0 ) return -1; + + if ( digi_lomem ) { + soundno = AltSounds[soundno]; + if ( soundno == 255 ) return -1; + } + return Sounds[soundno]; +} + +static int get_free_slot() +{ + int i; + unsigned int s; + for (i=0; i x=a^y +// a + if (d1v<=0) + return -10000; + else +// return log2(f2fl(d1v))*1000;//no log2? hm. + return log(f2fl(d1v))/log(2)*1000.0; +} + +int digi_start_sound(int soundnum, fix volume, fix pan) +{ + int ntries; + int slot; + HRESULT hr; + + if (!digi_initialised) return -1; + + //added on 980905 by adb from original source to add sound kill system + // play at most digi_max_channel samples, if possible kill sample with low volume + ntries = 0; + +TryNextChannel: + if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) ) + { + if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries= digi_max_channels ) + next_handle = 0; + ntries++; + goto TryNextChannel; + } + //mprintf(( 0, "[SS:%d]", next_handle )); + SoundSlots[SampleHandles[next_handle]].playing = 0; + SampleHandles[next_handle] = -1; + } + //end edit by adb + + slot = get_free_slot(); + if (slot<0) return -1; + + SoundSlots[slot].soundno = soundnum; + SoundSlots[slot].samples = GameSounds[soundnum].data; + SoundSlots[slot].length = GameSounds[soundnum].length; + SoundSlots[slot].volume = fixmul(digi_volume, volume); + SoundSlots[slot].pan = pan; + SoundSlots[slot].position = 0; + SoundSlots[slot].looped = 0; + SoundSlots[slot].playing = 1; + + memset(&waveformat, 0, sizeof(waveformat)); + waveformat.wFormatTag=WAVE_FORMAT_PCM; + waveformat.wBitsPerSample=8; + waveformat.nChannels = 1; + waveformat.nSamplesPerSec = 11025; + waveformat.nBlockAlign = + waveformat.nChannels * (waveformat.wBitsPerSample/8); + waveformat.nAvgBytesPerSec = + waveformat.nSamplesPerSec * waveformat.nBlockAlign; + + memset(&dsbd, 0, sizeof(dsbd)); + dsbd.dwSize = sizeof(dsbd); + dsbd.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_GETCURRENTPOSITION2; + dsbd.dwReserved=0; + dsbd.dwBufferBytes = SoundSlots[slot].length; + dsbd.lpwfxFormat = &waveformat; + + hr = IDirectSound_CreateSoundBuffer(lpds, &dsbd, &SoundSlots[slot].lpsb, NULL); + if ( hr != DS_OK ) { + printf("Createsoundbuffer failed! hr=0x%X\n", (int)hr); + abort(); + } + { + char *ptr1, *ptr2; + int len1, len2; + IDirectSoundBuffer_Lock(SoundSlots[slot].lpsb, 0, GameSounds[soundnum].length, + (void **)&ptr1, &len1, (void **)&ptr2, &len2, 0); + memcpy(ptr1,GameSounds[soundnum].data, MIN(len1, GameSounds[soundnum].length)); + IDirectSoundBuffer_Unlock(SoundSlots[slot].lpsb, ptr1, len1, ptr2, len2); + } + IDirectSoundBuffer_SetPan(SoundSlots[slot].lpsb, ((int)(f2fl(pan) * 20000.0))-10000); +// IDirectSoundBuffer_SetVolume(SoundSlots[slot].lpsb, MIN(((int)(f2fl(SoundSlots[slot].volume) * 15000.0)) - 10000, 0));//nope + IDirectSoundBuffer_SetVolume(SoundSlots[slot].lpsb, D1vol2DSvol(SoundSlots[slot].volume)); + + IDirectSoundBuffer_Play(SoundSlots[slot].lpsb, 0, 0, 0); + + //added on 980905 by adb to add sound kill system from original sos digi.c + reset_sounds_on_channel(slot); + SampleHandles[next_handle] = slot; + next_handle++; + if ( next_handle >= digi_max_channels ) + next_handle = 0; + //end edit by adb + + return slot; +} + + //added on 980905 by adb to add sound kill system from original sos digi.c +void reset_sounds_on_channel( int channel ) +{ + int i; + + for (i=0; i -1 ) { + *volume = max_volume - fixdiv(path_distance,max_distance); + //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume )); + if (*volume > 0 ) { + angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec); + fix_sincos(angle_from_ear,&sinang,&cosang); + //mprintf( (0, "volume is %.2f\n", f2fl(*volume) )); + if (Config_channels_reversed) cosang *= -1; + *pan = (cosang + F1_0)/2; + } else { + *volume = 0; + } + } + } +} + +int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance ) +{ + int i,volume,pan; + object * objp; + int soundnum; + + soundnum = digi_xlat_sound(org_soundnum); + + if ( max_volume < 0 ) return -1; +// if ( max_volume > F1_0 ) max_volume = F1_0; + + if (!digi_initialised) return -1; + if (soundnum < 0 ) return -1; + if (GameSounds[soundnum].data==NULL) { + Int3(); + return -1; + } + if ((objnum<0)||(objnum>Highest_object_index)) + return -1; + + if ( !forever ) { + // Hack to keep sounds from building up... + digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance ); + digi_play_sample_3d( org_soundnum, pan, volume, 0 ); + return -1; + } + + for (i=0; iorient, &Viewer->pos, Viewer->segnum, + &objp->pos, objp->segnum, SoundObjects[i].max_volume, + &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); + + if (!forever || SoundObjects[i].volume >= MIN_VOLUME) + digi_start_sound_object(i); + + return SoundObjects[i].signature; +} + +int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume ) +{ return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); } + +int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance ) +{ + int i, volume, pan; + int soundnum; + + soundnum = digi_xlat_sound(org_soundnum); + + if ( max_volume < 0 ) return -1; +// if ( max_volume > F1_0 ) max_volume = F1_0; + + if (!digi_initialised) return -1; + if (soundnum < 0 ) return -1; + if (GameSounds[soundnum].data==NULL) { + Int3(); + return -1; + } + + if ((segnum<0)||(segnum>Highest_segment_index)) + return -1; + + if ( !forever ) { + // Hack to keep sounds from building up... + digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance ); + digi_play_sample_3d( org_soundnum, pan, volume, 0 ); + return -1; + } + + for (i=0; iorient, &Viewer->pos, Viewer->segnum, + &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum, + SoundObjects[i].max_volume, + &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); + + if (!forever || SoundObjects[i].volume >= MIN_VOLUME) + digi_start_sound_object(i); + + return SoundObjects[i].signature; +} + +int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume ) +{ + return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 ); +} + +void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum ) +{ + int i,killed; + + soundnum = digi_xlat_sound(soundnum); + + if (!digi_initialised) return; + + killed = 0; + + for (i=0; i 1 ) { + mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum )); + } +} + +void digi_kill_sound_linked_to_object( int objnum ) +{ + int i,killed; + + if (!digi_initialised) return; + + killed = 0; + + for (i=0; i 1 ) { + mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum )); + } +} + +void digi_sync_sounds() +{ + int i; + int oldvolume, oldpan; + + if (!digi_initialised) return; + + for (i=0; iorient, &Viewer->pos, Viewer->segnum, + &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum, + SoundObjects[i].max_volume, + &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); + + } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) { + object * objp; + + objp = &Objects[SoundObjects[i].lo_objnum]; + + if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) { + // The object that this is linked to is dead, so just end this sound if it is looping. + if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) { + SoundSlots[SoundObjects[i].handle].playing = 0; + if (SoundSlots[SoundObjects[i].handle].lpsb) { + unsigned int s; + IDirectSoundBuffer_GetStatus(SoundSlots[SoundObjects[i].handle].lpsb, &s); + if (s & DSBSTATUS_PLAYING) IDirectSoundBuffer_Stop(SoundSlots[SoundObjects[i].handle].lpsb); + IDirectSoundBuffer_Release(SoundSlots[SoundObjects[i].handle].lpsb); + SoundSlots[SoundObjects[i].handle].playing = 0; + SoundSlots[SoundObjects[i].handle].lpsb = NULL; + } + } + SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound + continue; // Go on to next sound... + } else { + digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, + &objp->pos, objp->segnum, SoundObjects[i].max_volume, + &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); + } + } + + if (oldvolume != SoundObjects[i].volume) { + if ( SoundObjects[i].volume < MIN_VOLUME ) { + // Sound is too far away, so stop it from playing. + if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) { + SoundSlots[SoundObjects[i].handle].playing = 0; + if (SoundSlots[SoundObjects[i].handle].lpsb) { + unsigned int s; + IDirectSoundBuffer_GetStatus(SoundSlots[SoundObjects[i].handle].lpsb, &s); + if (s & DSBSTATUS_PLAYING) IDirectSoundBuffer_Stop(SoundSlots[SoundObjects[i].handle].lpsb); + IDirectSoundBuffer_Release(SoundSlots[SoundObjects[i].handle].lpsb); + SoundSlots[SoundObjects[i].handle].playing = 0; + SoundSlots[SoundObjects[i].handle].lpsb = NULL; + } + SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing + } + } else { + if (!(SoundObjects[i].flags & SOF_PLAYING)) { + digi_start_sound_object(i); + } else { + SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0); + } + } + } + + if (oldpan != SoundObjects[i].pan) { + if (SoundObjects[i].flags & SOF_PLAYING) + SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan; + } + } + } +} + +void digi_init_sounds() +{ + int i; + + if (!digi_initialised) return; + + digi_reset_digi_sounds(); + + for (i=0; i SOUND_MAX_VOLUME ) + digi_volume = SOUND_MAX_VOLUME; + else if ( dvolume < 0 ) + digi_volume = 0; + else + digi_volume = dvolume; + + if ( !digi_initialised ) return; + + digi_sync_sounds(); +} +//end edit by adb + +void digi_set_volume( int dvolume, int mvolume ) +{ + digi_set_digi_volume(dvolume); + digi_set_midi_volume(mvolume); +} + +int digi_is_sound_playing(int soundno) +{ + int i; + + soundno = digi_xlat_sound(soundno); + + for (i = 0; i < MAX_SOUND_SLOTS; i++) + //changed on 980905 by adb: added SoundSlots[i].playing && + if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno) + //end changes by adb + return 1; + return 0; +} + + +void digi_pause_all() { } +void digi_resume_all() { } +void digi_stop_all() { } + + //added on 980905 by adb to make sound channel setting work +void digi_set_max_channels(int n) { + digi_max_channels = n; + + if ( digi_max_channels < 1 ) + digi_max_channels = 1; + if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) ) + digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS); + + if ( !digi_initialised ) return; + + digi_reset_digi_sounds(); +} + +int digi_get_max_channels() { + return digi_max_channels; +} +// end edit by adb + +void digi_reset_digi_sounds() { + int i; + unsigned int s; + + for (i=0; i< MAX_SOUND_SLOTS; i++) { + SoundSlots[i].playing=0; + if (SoundSlots[i].lpsb) { + IDirectSoundBuffer_GetStatus(SoundSlots[i].lpsb, &s); + if (s & DSBSTATUS_PLAYING) IDirectSoundBuffer_Stop(SoundSlots[i].lpsb); + IDirectSoundBuffer_Release(SoundSlots[i].lpsb); + SoundSlots[i].playing = 0; + SoundSlots[i].lpsb = NULL; + } + + } + + //added on 980905 by adb to reset sound kill system + memset(SampleHandles, 255, sizeof(SampleHandles)); + next_handle = 0; + //end edit by adb +} +#else +int digi_lomem = 0; +int digi_midi_song_playing = 0; +static int digi_initialised = 0; +int midi_volume = 255; + +int digi_get_settings() { return 0; } +int digi_init() { digi_initialised = 1; return 0; } +void digi_reset() {} +void digi_close() {} + +void digi_play_sample( int sndnum, fix max_volume ) {} +void digi_play_sample_once( int sndnum, fix max_volume ) {} +int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume ) { return 0; } +int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume ) { return 0; } +// Same as above, but you pass the max distance sound can be heard. The old way uses f1_0*256 for max_distance. +int digi_link_sound_to_object2( int soundnum, short objnum, int forever, fix max_volume, fix max_distance ) { return 0; } +int digi_link_sound_to_pos2( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance ) { return 0; } + +void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) {} // Volume from 0-0x7fff + +void digi_init_sounds() {} +void digi_sync_sounds() {} +void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum ) {} +void digi_kill_sound_linked_to_object( int objnum ) {} + +void digi_set_digi_volume( int dvolume ) {} +void digi_set_volume( int dvolume, int mvolume ) {} + +int digi_is_sound_playing(int soundno) { return 0; } + +void digi_pause_all() {} +void digi_resume_all() {} +void digi_stop_all() {} + +void digi_set_max_channels(int n) {} +int digi_get_max_channels() { return 0; } + +#endif + +#ifdef MIDI_SOUND +// MIDI stuff follows. + +void digi_stop_current_song() +{ + if ( digi_midi_song_playing ) { + hmp_close(hmp); + hmp = NULL; + digi_midi_song_playing = 0; + } +} + +void digi_set_midi_volume( int n ) +{ + int mm_volume; + + if (n < 0) + midi_volume = 0; + else if (n > 127) + midi_volume = 127; + else + midi_volume = n; + + // scale up from 0-127 to 0-0xffff + mm_volume = (midi_volume << 1) | (midi_volume & 1); + mm_volume |= (mm_volume << 8); + + if (hmp) + midiOutSetVolume((HMIDIOUT)hmp->hmidi, mm_volume | mm_volume << 16); +} + +void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) +{ + if (!digi_initialised) return; + + digi_stop_current_song(); + + //added on 5/20/99 by Victor Rachels to fix crash/etc + if(filename == NULL) return; + if(midi_volume < 1) return; + //end this section addition - VR + + if ((hmp = hmp_open(filename))) { + hmp_play(hmp); + digi_midi_song_playing = 1; + digi_set_midi_volume(midi_volume); + } + else + printf("hmp_open failed\n"); +} +#else +void digi_stop_current_song() {} +void digi_set_midi_volume( int n ) {} +void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {} +#endif diff --git a/arch/win32/glinit.c b/arch/win32/glinit.c new file mode 100644 index 00000000..9093db13 --- /dev/null +++ b/arch/win32/glinit.c @@ -0,0 +1,8 @@ +//nothing to do, everything is in wgl.c. Just some empty funcs to make it happy. -MM + +void arch_init_start() +{ +} +void arch_init() +{ +} diff --git a/arch/win32/gr.c b/arch/win32/gr.c new file mode 100644 index 00000000..ccce5f56 --- /dev/null +++ b/arch/win32/gr.c @@ -0,0 +1,397 @@ +// Windows video functions. + +#include +#include +#include +#include +#include +#include +#ifdef __GCC__ +#include +#endif +#include "gr.h" +#include "grdef.h" +#include "palette.h" +#include "u_mem.h" +#include "error.h" +#include "vers_id.h" + +#include "gamefont.h" + +//added 10/05/98 by Matt Mueller - make fullscreen mode optional +#include "args.h" + +//removed 07/11/99 by adb - now option +////added 02/20/99 by adb - put descent in a window, sort of. Needed for debugging +////(needs a 256 color mode to be useful) +//#ifndef NDEBUG +//#define DD_NOT_EXCL +//#endif +//end remove - adb + +char *backbuffer = NULL; + +int gr_installed = 0; + +// Min without sideeffects. +#ifdef _MSC_VER +#define inline __inline +#endif + +#undef min +inline static int min(int x, int y) { return x < y ? x : y; } + +// Windows specific +HINSTANCE hInst; +HWND g_hWnd; +LPDIRECTDRAW lpDD; +LPDIRECTDRAWSURFACE lpDDSPrimary; +LPDIRECTDRAWSURFACE lpDDSOne; +LPDIRECTDRAWPALETTE lpDDPal; +PALETTEENTRY pe[256]; + +//added 02/20/99 by adb - put descent in a window, sort of. Needed for debugging +//(needs a 256 color mode to be useful) +//#define DD_NOT_EXCL + +void gr_palette_clear(); // Function prototype for gr_init; + + +static char *DDerror(int code) +{ + static char *error; + switch (code) { +/* case DDERR_GENERIC: + error = "Undefined error!"; + break;*/ + case DDERR_EXCEPTION: + error = "Exception encountered"; + break; + case DDERR_INVALIDOBJECT: + error = "Invalid object"; + break; +/* case DDERR_INVALIDPARAMS: + error = "Invalid parameters"; + break;*/ + case DDERR_NOTFOUND: + error = "Object not found"; + break; + case DDERR_INVALIDRECT: + error = "Invalid rectangle"; + break; + case DDERR_INVALIDCAPS: + error = "Invalid caps member"; + break; + case DDERR_INVALIDPIXELFORMAT: + error = "Invalid pixel format"; + break; +/* case DDERR_OUTOFMEMORY: + error = "Out of memory"; + break;*/ + case DDERR_OUTOFVIDEOMEMORY: + error = "Out of video memory"; + break; + case DDERR_SURFACEBUSY: + error = "Surface busy"; + break; + case DDERR_SURFACELOST: + error = "Surface was lost"; + break; + case DDERR_WASSTILLDRAWING: + error = "DirectDraw is still drawing"; + break; + case DDERR_INVALIDSURFACETYPE: + error = "Invalid surface type"; + break; + case DDERR_NOEXCLUSIVEMODE: + error = "Not in exclusive access mode"; + break; + case DDERR_NOPALETTEATTACHED: + error = "No palette attached"; + break; + case DDERR_NOPALETTEHW: + error = "No palette hardware"; + break; + case DDERR_NOT8BITCOLOR: + error = "Not 8-bit color"; + break; + case DDERR_EXCLUSIVEMODEALREADYSET: + error = "Exclusive mode was already set"; + break; + case DDERR_HWNDALREADYSET: + error = "Window handle already set"; + break; + case DDERR_HWNDSUBCLASSED: + error = "Window handle is subclassed"; + break; + case DDERR_NOBLTHW: + error = "No blit hardware"; + break; + case DDERR_IMPLICITLYCREATED: + error = "Surface was implicitly created"; + break; + case DDERR_INCOMPATIBLEPRIMARY: + error = "Incompatible primary surface"; + break; + case DDERR_NOCOOPERATIVELEVELSET: + error = "No cooperative level set"; + break; + case DDERR_NODIRECTDRAWHW: + error = "No DirectDraw hardware"; + break; + case DDERR_NOEMULATION: + error = "No emulation available"; + break; + case DDERR_NOFLIPHW: + error = "No flip hardware"; + break; + case DDERR_NOTFLIPPABLE: + error = "Surface not flippable"; + break; + case DDERR_PRIMARYSURFACEALREADYEXISTS: + error = "Primary surface already exists"; + break; + case DDERR_UNSUPPORTEDMODE: + error = "Unsupported mode"; + break; + case DDERR_WRONGMODE: + error = "Surface created in different mode"; + break; +/* case DDERR_UNSUPPORTED: + error = "Operation not supported"; + break;*/ + default: + error = "unknown"; + break; + } + return error; +} + + +void gr_update() +{ + DDSURFACEDESC ddsd; + HRESULT ddrval; + int i; + int w, h; + char *j; + char *k; + + ddsd.dwSize=sizeof(ddsd); + ddrval=IDirectDrawSurface_Lock(lpDDSPrimary,NULL,&ddsd,0,NULL); + if (ddrval!=DD_OK) { + printf("lock failed, %s\n", DDerror(ddrval)); + Assert(ddrval==DD_OK); + } + + j=backbuffer; k=ddsd.lpSurface; + h=grd_curscreen->sc_canvas.cv_bitmap.bm_h; + w=grd_curscreen->sc_canvas.cv_bitmap.bm_w; + for (i=0; isc_canvas.cv_bitmap.bm_rowsize; + //j+=ddsd.dwWidth; +#ifdef NONAMELESSUNION + k+=ddsd.u1.lPitch; +#else + k+=ddsd.lPitch; +#endif + } + IDirectDrawSurface_Unlock(lpDDSPrimary,NULL); +/* while (1) + { + ddrval=IDirectDrawSurface_Flip(lpDDSPrimary,NULL,0); + if (ddrval == DD_OK) + { + printf("Flip was successful\n"); + break; + } + if (ddrval == DDERR_SURFACELOST) + { + printf("surface was lost\n"); + ddrval=IDirectDrawSurface_Restore(lpDDSPrimary); + if (ddrval != DD_OK) + { + printf("restore failed\n"); + break; + } + } + if (ddrval == DDERR_WASSTILLDRAWING ) + { + printf("was still drawing\n"); + break; + } + }*/ +} + + + +int gr_set_mode(u_int32_t mode) +{ + DDSURFACEDESC ddsd; +// DDSURFACEDESC DDSDesc; +// DDSCAPS ddcaps; + HRESULT ddrval; + unsigned int w,h; + + if (mode<=0) + return 0; + + w=SM_W(mode); + h=SM_H(mode); + + if(lpDDSPrimary!=NULL) + { + IDirectDrawSurface_Release(lpDDSPrimary); + lpDDSPrimary=NULL; + } + + if (backbuffer) free(backbuffer); + + + //changed 07/11/99 by adb - nonfullscreen mode now option + if (!FindArg("-semiwin")) + { + ddrval=IDirectDraw_SetDisplayMode(lpDD,w,h,8); + + if (ddrval!=DD_OK) + { + fprintf(stderr, "Hmmm... I had a problem changing screen modes... is %ix%ix8 supported? If so, try again... :-( %s\n",w,h, DDerror(ddrval)); + return -3; // This is **not** good... + } + } + //end changes - adb + ddsd.dwSize=sizeof(ddsd); + ddsd.dwFlags=DDSD_CAPS /*| DDSD_BACKBUFFERCOUNT*/; + ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE /*| DDSCAPS_FLIP | DDSCAPS_COMPLEX*/; + //ddsd.dwBackBufferCount=1; + + ddrval=IDirectDraw_CreateSurface(lpDD,&ddsd,&lpDDSPrimary,NULL); + if(ddrval!=DD_OK) + { + return -4; + } + +#if 0 + memset(&ddcaps,0,sizeof(ddcaps)); +// ddcaps.dwSize=sizeof(ddcaps); + ddcaps.dwCaps=DDSCAPS_BACKBUFFER; + + ddrval=IDirectDrawSurface_GetAttachedSurface(lpDDSPrimary,&ddcaps,&lpDDSOne); + Assert(ddrval==DD_OK); + if(lpDDSOne==NULL) + { + return -5; + } +#endif + + ddrval=IDirectDraw_CreatePalette(lpDD,DDPCAPS_8BIT | DDPCAPS_INITIALIZE | DDPCAPS_ALLOW256,pe,&lpDDPal,NULL); + Assert(ddrval==DD_OK); + if(ddrval!=DD_OK) + { + return FALSE; + } + + IDirectDrawSurface_SetPalette(lpDDSPrimary,lpDDPal); +// IDirectDrawSurface_SetPalette(lpDDSOne,lpDDPal); + + gr_palette_clear(); + + memset( grd_curscreen, 0, sizeof(grs_screen)); + grd_curscreen->sc_mode = mode; + grd_curscreen->sc_w = w; + grd_curscreen->sc_h = h; + grd_curscreen->sc_aspect = fixdiv(grd_curscreen->sc_w*3,grd_curscreen->sc_h*4); + grd_curscreen->sc_canvas.cv_bitmap.bm_x = 0; + grd_curscreen->sc_canvas.cv_bitmap.bm_y = 0; + grd_curscreen->sc_canvas.cv_bitmap.bm_w = w; + grd_curscreen->sc_canvas.cv_bitmap.bm_h = h; + grd_curscreen->sc_canvas.cv_bitmap.bm_type = BM_LINEAR; + + backbuffer = malloc(w*h); + memset(backbuffer, 0, w*h); + grd_curscreen->sc_canvas.cv_bitmap.bm_data = (unsigned char *)backbuffer; + + ddsd.dwSize=sizeof(ddsd); + ddrval=IDirectDrawSurface_Lock(lpDDSPrimary,NULL,&ddsd,0,NULL); + if(ddrval!=DD_OK) + { + return -6; + } + + // bm_rowsize is for backbuffer, so always w -- adb + grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize = w; + //grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize = (short)ddsd.lPitch; + + memset(ddsd.lpSurface,0,w*h); // Black the canvas out to stop nasty kludgy display + IDirectDrawSurface_Unlock(lpDDSPrimary,NULL); + + gr_set_current_canvas(NULL); + + gamefont_choose_game_font(w,h); + + printf("Successfully completed set_mode\n"); + return 0; +} + + + +void Win32_DoSetPalette (PALETTEENTRY *rgpe) +{ + IDirectDraw_WaitForVerticalBlank(lpDD,DDWAITVB_BLOCKBEGIN,NULL); + IDirectDrawPalette_SetEntries(lpDDPal,0,0,256,rgpe); +} + +void Win32_DoGetPalette (PALETTEENTRY *rgpe) +{ + IDirectDrawPalette_GetEntries(lpDDPal,0,0,256,rgpe); +} + +//added 07/11/99 by adb for d3d +void Win32_MakePalVisible(void) +{ +} +//end additions - adb + +void gr_close(void); + +int gr_init(int mode) +{ + int retcode; + // Only do this function once! + if (gr_installed==1) + return -1; + MALLOC( grd_curscreen,grs_screen,1 ); + memset( grd_curscreen, 0, sizeof(grs_screen)); + + // Set the mode. + if ((retcode=gr_set_mode(mode))) + { + return retcode; + } + grd_curscreen->sc_canvas.cv_color = 0; + grd_curscreen->sc_canvas.cv_drawmode = 0; + grd_curscreen->sc_canvas.cv_font = NULL; + grd_curscreen->sc_canvas.cv_font_fg_color = 0; + grd_curscreen->sc_canvas.cv_font_bg_color = 0; + gr_set_current_canvas( &grd_curscreen->sc_canvas ); + + gr_installed = 1; + // added on 980913 by adb to add cleanup + atexit(gr_close); + // end changes by adb + + return 0; +} + +void gr_close(void) +{ + if (gr_installed==1) + { + gr_installed = 0; + free(grd_curscreen); + free(backbuffer); + } +} + + diff --git a/arch/win32/hmpfile.c b/arch/win32/hmpfile.c new file mode 100644 index 00000000..4ac701c3 --- /dev/null +++ b/arch/win32/hmpfile.c @@ -0,0 +1,404 @@ +/* This is HMP file playing code by Arne de Bruijn */ +#include +#include +#include +#include "hmpfile.h" + +#if 0 +#define CFILE FILE +#define cfopen fopen +#define cfseek fseek +#define cfread fread +#define cfclose fclose +#else +#include "cfile.h" +#endif + +extern void PumpMessages(void); + +hmp_file *hmp_open(const char *filename) { + int i; + char buf[256]; + long data; + CFILE *fp; + hmp_file *hmp; + int num_tracks; + unsigned char *p; + + if (!(fp = cfopen((char *)filename, "rb"))) + return NULL; + + hmp = malloc(sizeof(hmp_file)); + if (!hmp) { + cfclose(fp); + return NULL; + } + + memset(hmp, 0, sizeof(*hmp)); + + if ((cfread(buf, 1, 8, fp) != 8) || (memcmp(buf, "HMIMIDIP", 8))) + goto err; + + if (cfseek(fp, 0x30, SEEK_SET)) + goto err; + + if (cfread(&num_tracks, 4, 1, fp) != 1) + goto err; + + if ((num_tracks < 1) || (num_tracks > HMP_TRACKS)) + goto err; + + hmp->num_trks = num_tracks; + hmp->tempo = 120; + + if (cfseek(fp, 0x308, SEEK_SET)) + goto err; + + for (i = 0; i < num_tracks; i++) { + if ((cfseek(fp, 4, SEEK_CUR)) || (cfread(&data, 4, 1, fp) != 1)) + goto err; + + data -= 12; + +#if 0 + if (i == 0) /* track 0: reserve length for tempo */ + data += sizeof(hmp_tempo); +#endif + + hmp->trks[i].len = data; + + if (!(p = hmp->trks[i].data = malloc(data))) + goto err; + +#if 0 + if (i == 0) { /* track 0: add tempo */ + memcpy(p, hmp_tempo, sizeof(hmp_tempo)); + p += sizeof(hmp_tempo); + data -= sizeof(hmp_tempo); + } +#endif + /* finally, read track data */ + if ((cfseek(fp, 4, SEEK_CUR)) || (cfread(p, data, 1, fp) != 1)) + goto err; + } + cfclose(fp); + return hmp; + +err: + cfclose(fp); + hmp_close(hmp); + return NULL; +} + +void hmp_stop(hmp_file *hmp) { + MIDIHDR *mhdr; + if (!hmp->stop) { + hmp->stop = 1; + PumpMessages(); + midiStreamStop(hmp->hmidi); + while (hmp->bufs_in_mm) + { + PumpMessages(); + Sleep(0); + } + } + while ((mhdr = hmp->evbuf)) { + midiOutUnprepareHeader((HMIDIOUT)hmp->hmidi, mhdr, sizeof(MIDIHDR)); + hmp->evbuf = mhdr->lpNext; + free(mhdr); + } + + if (hmp->hmidi) { + midiStreamClose(hmp->hmidi); + hmp->hmidi = NULL; + } +} + +void hmp_close(hmp_file *hmp) { + int i; + + hmp_stop(hmp); + for (i = 0; i < hmp->num_trks; i++) + if (hmp->trks[i].data) + free(hmp->trks[i].data); + free(hmp); +} + +/* + * read a HMI type variabele length number + */ +static int get_var_num_hmi(unsigned char *data, int datalen, unsigned long *value) { + unsigned char *p; + unsigned long v = 0; + int shift = 0; + + p = data; + while ((datalen > 0) && !(*p & 0x80)) { + v += *(p++) << shift; + shift += 7; + datalen --; + } + if (!datalen) + return 0; + v += (*(p++) & 0x7f) << shift; + if (value) *value = v; + return p - data; +} + +/* + * read a MIDI type variabele length number + */ +static int get_var_num(unsigned char *data, int datalen, + unsigned long *value) { + unsigned char *orgdata = data; + unsigned long v = 0; + + while ((datalen > 0) && (*data & 0x80)) + v = (v << 7) + (*(data++) & 0x7f); + if (!datalen) + return 0; + v = (v << 7) + *(data++); + if (value) *value = v; + return data - orgdata; +} + +static int get_event(hmp_file *hmp, event *ev) { + static int cmdlen[7]={3,3,3,3,2,2,3}; + unsigned long got; + unsigned long mindelta, delta; + int i, ev_num; + hmp_track *trk, *fndtrk; + + mindelta = INT_MAX; + fndtrk = NULL; + for (trk = hmp->trks, i = hmp->num_trks; (i--) > 0; trk++) { + if (!trk->left) + continue; + if (!(got = get_var_num_hmi(trk->cur, trk->left, &delta))) + return HMP_INVALID_FILE; + if (trk->left > got + 2 && *(trk->cur + got) == 0xff + && *(trk->cur + got + 1) == 0x2f) {/* end of track */ + trk->left = 0; + continue; + } + delta += trk->cur_time - hmp->cur_time; + if (delta < mindelta) { + mindelta = delta; + fndtrk = trk; + } + } + if (!(trk = fndtrk)) + return HMP_EOF; + + got = get_var_num_hmi(trk->cur, trk->left, &delta); + + trk->cur_time += delta; + ev->delta = trk->cur_time - hmp->cur_time; + hmp->cur_time = trk->cur_time; + + if ((trk->left -= got) < 3) + return HMP_INVALID_FILE; + trk->cur += got; + /*memset(ev, 0, sizeof(*ev));*/ev->datalen = 0; + ev->msg[0] = ev_num = *(trk->cur++); + trk->left--; + if (ev_num < 0x80) + return HMP_INVALID_FILE; /* invalid command */ + if (ev_num < 0xf0) { + ev->msg[1] = *(trk->cur++); + trk->left--; + if (cmdlen[((ev_num) >> 4) - 8] == 3) { + ev->msg[2] = *(trk->cur++); + trk->left--; + } + } else if (ev_num == 0xff) { + ev->msg[1] = *(trk->cur++); + trk->left--; + if (!(got = get_var_num(ev->data = trk->cur, + trk->left, (unsigned long *)&ev->datalen))) + return HMP_INVALID_FILE; + trk->cur += ev->datalen; + if (trk->left <= ev->datalen) + return HMP_INVALID_FILE; + trk->left -= ev->datalen; + } else /* sysex -> error */ + return HMP_INVALID_FILE; + return 0; +} + +static int fill_buffer(hmp_file *hmp) { + MIDIHDR *mhdr = hmp->evbuf; + unsigned int *p = (unsigned int *)(mhdr->lpData + mhdr->dwBytesRecorded); + unsigned int *pend = (unsigned int *)(mhdr->lpData + mhdr->dwBufferLength); + unsigned int i; + event ev; + + while (p + 4 <= pend) { + if (hmp->pending_size) { + i = (p - pend) * 4; + if (i > hmp->pending_size) + i = hmp->pending_size; + *(p++) = hmp->pending_event | i; + *(p++) = 0; + memcpy((unsigned char *)p, hmp->pending, i); + hmp->pending_size -= i; + p += (i + 3) / 4; + } else { + if ((i = get_event(hmp, &ev))) { + mhdr->dwBytesRecorded = ((unsigned char *)p) - ((unsigned char *)mhdr->lpData); + return i; + } + if (ev.datalen) { + hmp->pending_size = ev.datalen; + hmp->pending = ev.data; + hmp->pending_event = ev.msg[0] << 24; + } else { + *(p++) = ev.delta; + *(p++) = 0; + *(p++) = (((DWORD)MEVT_SHORTMSG) << 24) | + ((DWORD)ev.msg[0]) | + (((DWORD)ev.msg[1]) << 8) | + (((DWORD)ev.msg[2]) << 16); + } + } + } + mhdr->dwBytesRecorded = ((unsigned char *)p) - ((unsigned char *)mhdr->lpData); + return 0; +} + +static int setup_buffers(hmp_file *hmp) { + int i; + MIDIHDR *buf, *lastbuf; + + lastbuf = NULL; + for (i = 0; i < HMP_BUFFERS; i++) { + if (!(buf = malloc(HMP_BUFSIZE + sizeof(MIDIHDR)))) + return HMP_OUT_OF_MEM; + memset(buf, 0, sizeof(MIDIHDR)); + buf->lpData = (unsigned char *)buf + sizeof(MIDIHDR); + buf->dwBufferLength = HMP_BUFSIZE; + buf->dwUser = (DWORD)hmp; + buf->lpNext = lastbuf; + lastbuf = buf; + } + hmp->evbuf = lastbuf; + return 0; +} + +static void reset_tracks(struct hmp_file *hmp) { + int i; + + for (i = 0; i < hmp->num_trks; i++) { + hmp->trks[i].cur = hmp->trks[i].data; + hmp->trks[i].left = hmp->trks[i].len; + } +} + +static void _stdcall midi_callback(HMIDISTRM hms, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) { + MIDIHDR *mhdr; + hmp_file *hmp; + int rc; + + if (uMsg != MOM_DONE) + return; + + mhdr = ((MIDIHDR *)dw1); + mhdr->dwBytesRecorded = 0; + hmp = (hmp_file *)(mhdr->dwUser); + mhdr->lpNext = hmp->evbuf; + hmp->evbuf = mhdr; + hmp->bufs_in_mm--; + + if (!hmp->stop) { + while (fill_buffer(hmp) == HMP_EOF) + reset_tracks(hmp); + if ((rc = midiStreamOut(hmp->hmidi, hmp->evbuf, + sizeof(MIDIHDR))) != MMSYSERR_NOERROR) { + /* ??? */ + } else { + hmp->evbuf = hmp->evbuf->lpNext; + hmp->bufs_in_mm++; + } + } + +} + +static void setup_tempo(hmp_file *hmp, unsigned long tempo) { + MIDIHDR *mhdr = hmp->evbuf; + unsigned int *p = (unsigned int *)(mhdr->lpData + mhdr->dwBytesRecorded); + *(p++) = 0; + *(p++) = 0; + *(p++) = (((DWORD)MEVT_TEMPO)<<24) | tempo; + mhdr->dwBytesRecorded += 12; +} + +int hmp_play(hmp_file *hmp) { + int rc; + MIDIPROPTIMEDIV mptd; +#if 0 + unsigned int numdevs; + int i=0; + + numdevs=midiOutGetNumDevs(); + hmp->devid=-1; + do + { + MIDIOUTCAPS devcaps; + midiOutGetDevCaps(i,&devcaps,sizeof(MIDIOUTCAPS)); + if ((devcaps.wTechnology==MOD_FMSYNTH) || (devcaps.wTechnology==MOD_SYNTH)) + hmp->devid=i; + i++; + } while ((i<(int)numdevs) && (hmp->devid==-1)); +#else + hmp->devid = MIDI_MAPPER; +#endif + + if ((rc = setup_buffers(hmp))) + return rc; + if ((midiStreamOpen(&hmp->hmidi, &hmp->devid,1,(DWORD)midi_callback, + 0, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR) { + hmp->hmidi = NULL; + return HMP_MM_ERR; + } + mptd.cbStruct = sizeof(mptd); + mptd.dwTimeDiv = hmp->tempo; + if ((midiStreamProperty(hmp->hmidi, + (LPBYTE)&mptd, + MIDIPROP_SET|MIDIPROP_TIMEDIV)) != MMSYSERR_NOERROR) { + /* FIXME: cleanup... */ + return HMP_MM_ERR; + } + + reset_tracks(hmp); + setup_tempo(hmp, 0x0f4240); + + hmp->stop = 0; + while (hmp->evbuf) { + if ((rc = fill_buffer(hmp))) { + if (rc == HMP_EOF) { + reset_tracks(hmp); + continue; + } else + return rc; + } +#if 0 + { FILE *f = fopen("dump","wb"); fwrite(hmp->evbuf->lpData, + hmp->evbuf->dwBytesRecorded,1,f); fclose(f); exit(1);} +#endif + if ((rc = midiOutPrepareHeader((HMIDIOUT)hmp->hmidi, hmp->evbuf, + sizeof(MIDIHDR))) != MMSYSERR_NOERROR) { + /* FIXME: cleanup... */ + return HMP_MM_ERR; + } + if ((rc = midiStreamOut(hmp->hmidi, hmp->evbuf, + sizeof(MIDIHDR))) != MMSYSERR_NOERROR) { + /* FIXME: cleanup... */ + return HMP_MM_ERR; + } + hmp->evbuf = hmp->evbuf->lpNext; + hmp->bufs_in_mm++; + } + midiStreamRestart(hmp->hmidi); + return 0; +} + diff --git a/arch/win32/include/d3dhelp.h b/arch/win32/include/d3dhelp.h new file mode 100644 index 00000000..922c8e6b --- /dev/null +++ b/arch/win32/include/d3dhelp.h @@ -0,0 +1,11 @@ +#ifndef D3DHELP_H_ +#define D3DHELP_H_ + +void Win32_Rect(int left, int top, int right, int bot, int iSurf, int iCol); +#ifndef __cplusplus +void Win32_BlitLinearToDirectX_bm(grs_bitmap *bm, int sx, int sy, + int w, int h, int dx, int dy, int mask); +#endif +void Win32_InvalidatePages(void); + +#endif diff --git a/arch/win32/include/debug.h b/arch/win32/include/debug.h new file mode 100644 index 00000000..9d2dfc81 --- /dev/null +++ b/arch/win32/include/debug.h @@ -0,0 +1,152 @@ +#ifndef DEBUG_H +#define DEBUG_H +/* +**----------------------------------------------------------------------------- +** File: Debug.h +** Purpose: Sample Debug code +** Notes: +** +** Copyright (c) 1995 - 1997 by Microsoft, all rights reserved +**----------------------------------------------------------------------------- +*/ + +/* +**----------------------------------------------------------------------------- +** Include files +**----------------------------------------------------------------------------- +*/ + + + +/* +**----------------------------------------------------------------------------- +** Defines +**----------------------------------------------------------------------------- +*/ + +#ifndef NDEBUG +// Note: Define DEBUG_PROMPTME if you want MessageBox Error prompting +// This can get annoying quickly... +// #define DEBUG_PROMPTME + + // Pre and Post debug string info +// #define START_STR TEXT ("D3DDESCENT: ") + #define START_STR TEXT ("") + #define END_STR TEXT ("\r\n") +#endif // NDEBUG + +// Debug Levels +#define DEBUG_ALWAYS 0L +#define DEBUG_CRITICAL 1L +#define DEBUG_ERROR 2L +#define DEBUG_MINOR 3L +#define DEBUG_WARN 4L +#define DEBUG_DETAILS 5L + + +// Sample Errors +#define APPERR_GENERIC MAKE_DDHRESULT (10001) +#define APPERR_INVALIDPARAMS MAKE_DDHRESULT (10002) +#define APPERR_NOTINITIALIZED MAKE_DDHRESULT (10003) +#define APPERR_OUTOFMEMORY MAKE_DDHRESULT (10004) +#define APPERR_NOTFOUND MAKE_DDHRESULT (10005) + + + +/* +**----------------------------------------------------------------------------- +** Macros +**----------------------------------------------------------------------------- +*/ + +#ifndef NDEBUG + #define DPF dprintf +/* + #define ASSERT(x) \ + if (! (x)) \ + { \ + DPF (DEBUG_ALWAYS, TEXT("Assertion violated: %s, File = %s, Line = #%ld\n"), \ + TEXT(#x), TEXT(__FILE__), (DWORD)__LINE__ ); \ + abort (); \ + } +*/ + + #define REPORTERR(x) \ + ReportDDError ((x), TEXT("%s(%ld)"), \ + TEXT(__FILE__), (DWORD)__LINE__ ); + + #define FATALERR(x) \ + ReportDDError ((x), TEXT("%s(%ld)"), \ + TEXT(__FILE__), (DWORD)__LINE__ ); \ + OnPause (TRUE); \ + DestroyWindow (g_hWnd); +#else + #define REPORTERR(x) + #define DPF 1 ? (void)0 : (void) +/* + #define ASSERT(x) +*/ + #define FATALERR(x) \ + OnPause (TRUE); \ + DestroyWindow (g_hWnd); +#endif // NDEBUG + + + +/* +**----------------------------------------------------------------------------- +** Global Variables +**----------------------------------------------------------------------------- +*/ + +// Debug Variables +#ifndef NDEBUG + extern DWORD g_dwDebugLevel; +#endif + +extern BOOL g_fDebug; + + + +/* +**----------------------------------------------------------------------------- +** Function Prototypes +**----------------------------------------------------------------------------- +*/ + +// Debug Routines +#ifndef NDEBUG + void __cdecl dprintf (DWORD dwDebugLevel, LPCTSTR szFormat, ...); +#endif //NDEBUG + +void _cdecl ReportDDError (HRESULT hResult, LPCTSTR szFormat, ...); + +#ifndef NDEBUG +struct CDebugTracker +{ + CDebugTracker (LPCSTR lpsz); + ~CDebugTracker (); + + void __cdecl Return (LPCSTR szFormat, ...); + +protected: + LPCSTR m_psz; + BOOL m_bReturned; + static ULONG s_cLevels; + static char szsp [80]; +}; + +#define TRACKER_ENTER(str)\ + CDebugTracker __tracker (str); +#else // NDEBUG +#define TRACKER_ENTER(str) while(0); +#endif // NDEBUG + +/* +**----------------------------------------------------------------------------- +** End of File +**----------------------------------------------------------------------------- +*/ +#endif // End DEBUG_H + + diff --git a/arch/win32/include/hmpfile.h b/arch/win32/include/hmpfile.h new file mode 100644 index 00000000..d6e6cab3 --- /dev/null +++ b/arch/win32/include/hmpfile.h @@ -0,0 +1,50 @@ +#ifndef _HMPFILE_H +#define _HMPFILE_H +#include +#include + +#define HMP_TRACKS 32 +#define HMP_BUFFERS 4 +#define HMP_BUFSIZE 1024 + +typedef struct event { + unsigned int delta; + unsigned char msg[3]; + unsigned char *data; + unsigned int datalen; +} event; + +typedef struct hmp_track { + unsigned char *data; + unsigned int len; + unsigned char *cur; + unsigned int left; + unsigned int cur_time; +} hmp_track; + +typedef struct hmp_file { + int num_trks; + hmp_track trks[HMP_TRACKS]; + unsigned int cur_time; + int tempo; + MIDIHDR *evbuf; + HMIDISTRM hmidi; + UINT devid; + unsigned char *pending; + unsigned int pending_size; + unsigned int pending_event; + int stop; /* 1 -> don't send more data */ + int bufs_in_mm; /* number of queued buffers */ +} hmp_file; + + +#define HMP_INVALID_FILE -1 +#define HMP_OUT_OF_MEM -2 +#define HMP_MM_ERR -3 +#define HMP_EOF 1 + +hmp_file *hmp_open(const char *filename); +int hmp_play(hmp_file *hmp); +void hmp_close(hmp_file *hmp); + +#endif diff --git a/arch/win32/include/joy.h b/arch/win32/include/joy.h new file mode 100644 index 00000000..adb7de9c --- /dev/null +++ b/arch/win32/include/joy.h @@ -0,0 +1,121 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifndef _JOY_H +#define _JOY_H + +#include "types.h" +#include "fix.h" + +#define JOY_1_BUTTON_A 1 +#define JOY_1_BUTTON_B 2 +#define JOY_2_BUTTON_A 4 +#define JOY_2_BUTTON_B 8 +#define JOY_ALL_BUTTONS (1+2+4+8) + +#define JOY_1_X_AXIS 1 +#define JOY_1_Y_AXIS 2 +#define JOY_1_R_AXIS 4 +#define JOY_1_Z_AXIS 8 +#define JOY_1_U_AXIS 16 +#define JOY_1_V_AXIS 32 +#define JOY_ALL_AXIS (1+2+4+8+16+32) + +//#if 0 +//#define JOY_2_X_AXIS 4 +//#define JOY_2_Y_AXIS 8 +//#define JOY_ALL_AXIS (1+2+4+8) +//#endif + +#define JOY_POLL_RATE 0 // use minimum FIXME: is this what we want? + +#define JOY_NUM_AXES 6 + +#define MAX_BUTTONS 20 + +//========================================================================== +// This initializes the joy and does a "quick" calibration which +// assumes the stick is centered and sets the minimum value to 0 and +// the maximum value to 2 times the centered reading. Returns 0 if no +// joystick was detected, 1 if everything is ok. +// joy_init() is called. + +extern int joy_init(); +extern void joy_close(); + +extern char joy_installed; +extern char joy_present; + +//========================================================================== +// The following 3 routines can be used to zero in on better joy +// calibration factors. To use them, ask the user to hold the stick +// in either the upper left, lower right, or center and then have them +// press a key or button and then call the appropriate one of these +// routines, and it will read the stick and update the calibration factors. +// Usually, assuming that the stick was centered when joy_init was +// called, you really only need to call joy_set_lr, since the upper +// left position is usually always 0,0 on most joys. But, the safest +// bet is to do all three, or let the user choose which ones to set. + +extern void joy_set_ul(); +extern void joy_set_lr(); +extern void joy_set_cen(); + + +//========================================================================== +// This reads the joystick. X and Y will be between -128 and 127. +// Takes about 1 millisecond in the worst case when the stick +// is in the lower right hand corner. Always returns 0,0 if no stick +// is present. + +extern void joy_get_pos( int *x, int *y ); + +//========================================================================== +// This just reads the buttons and returns their status. When bit 0 +// is 1, button 1 is pressed, when bit 1 is 1, button 2 is pressed. +extern int joy_get_btns(); + +//========================================================================== +// This returns the number of times a button went either down or up since +// the last call to this function. +extern int joy_get_button_up_cnt( int btn ); +extern int joy_get_button_down_cnt( int btn ); + +//========================================================================== +// This returns how long (in approximate milliseconds) that each of the +// buttons has been held down since the last call to this function. +// It is the total time... say you pressed it down for 3 ticks, released +// it, and held it down for 6 more ticks. The time returned would be 9. +extern fix joy_get_button_down_time( int btn ); + +extern ubyte joy_read_raw_buttons(); +extern ubyte joystick_read_raw_axis( ubyte mask, int * axis ); +extern void joy_flush(); +extern ubyte joy_get_present_mask(); +extern void joy_set_timer_rate(int max_value ); +extern int joy_get_timer_rate(); + +extern int joy_get_button_state( int btn ); +extern void joy_set_cen_fake(int channel); +extern ubyte joy_read_stick( ubyte masks, int *axis ); +extern void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max); +extern void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max); +extern void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount ); +extern int joy_get_scaled_reading( int raw, int axn ); +extern void joy_set_slow_reading( int flag ); + + +extern int JOY_PORT; +extern int joy_deadzone; +#endif + diff --git a/arch/win32/include/key.h b/arch/win32/include/key.h new file mode 100644 index 00000000..a7713d78 --- /dev/null +++ b/arch/win32/include/key.h @@ -0,0 +1,271 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/arch/win32/include/key.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:15 $ + * + * Header for keyboard functions + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:01:23 donut + * Import of d1x 1.37 source. + * + * Revision 1.19 1994/10/24 13:58:12 john + * Hacked in support for pause key onto code 0x61. + * + * Revision 1.18 1994/10/21 15:17:10 john + * Added KEY_PRINT_SCREEN + * + * Revision 1.17 1994/08/31 12:22:13 john + * Added KEY_DEBUGGED + * + * Revision 1.16 1994/08/24 18:53:50 john + * Made Cyberman read like normal mouse; added dpmi module; moved + * mouse from assembly to c. Made mouse buttons return time_down. + * + * Revision 1.15 1994/08/18 14:56:16 john + * *** empty log message *** + * + * Revision 1.14 1994/08/08 10:43:24 john + * Recorded when a key was pressed for key_inkey_time. + * + * Revision 1.13 1994/06/17 17:17:28 john + * Added keyd_time_last_key_was_pressed or something like that. + * + * Revision 1.12 1994/04/29 12:14:19 john + * Locked all memory used during interrupts so that program + * won't hang when using virtual memory. + * + * Revision 1.11 1994/02/17 15:57:14 john + * Changed key libary to C. + * + * Revision 1.10 1994/01/31 08:34:09 john + * Fixed reversed lshift/rshift keys. + * + * Revision 1.9 1994/01/18 10:58:17 john + * *** empty log message *** + * + * Revision 1.8 1993/10/16 19:24:43 matt + * Added new function key_clear_times() & key_clear_counts() + * + * Revision 1.7 1993/10/15 10:17:09 john + * added keyd_last_key_pressed and released for use with recorder. + * + * Revision 1.6 1993/10/06 16:20:37 john + * fixed down arrow bug + * + * Revision 1.5 1993/10/04 13:26:42 john + * changed the #defines for scan codes. + * + * Revision 1.4 1993/09/28 11:35:20 john + * added key_peekkey + * + * Revision 1.3 1993/09/20 18:36:43 john + * *** empty log message *** + * + * Revision 1.1 1993/07/10 13:10:39 matt + * Initial revision + * + * + */ + +#ifndef _KEY_H +#define _KEY_H + +#include "fix.h" +#include "types.h" +#include // For 'toupper' + +//========================================================================== +// This installs the int9 vector and initializes the keyboard in buffered +// ASCII mode. key_close simply undoes that. +extern void key_init(); +extern void key_close(); + +//========================================================================== +// These are configuration parameters to setup how the buffer works. +// set keyd_buffer_type to 0 for no key buffering. +// set it to 1 and it will buffer scancodes. +extern unsigned char keyd_buffer_type; +extern unsigned char keyd_repeat; // 1=allow repeating, 0=dont allow repeat + +// keyd_editor_mode... 0=game mode, 1=editor mode. +// Editor mode makes key_down_time always return 0 if modifiers are down. +extern unsigned char keyd_editor_mode; + +// Time in seconds when last key was pressed... +extern volatile int keyd_time_when_last_pressed; + +//========================================================================== +// These are the "buffered" keypress routines. Use them by setting the +// "keyd_buffer_type" variable. + +extern void key_flush(); // Clears the 256 char buffer +extern int key_checkch(); // Returns 1 if a char is waiting +extern int key_getch(); // Gets key if one waiting other waits for one. +extern int key_inkey(); // Gets key if one, other returns 0. +extern int key_inkey_time(fix *time); // Same as inkey, but returns the time the key was pressed down. +extern int key_peekkey(); // Same as inkey, but doesn't remove key from buffer. + +extern unsigned char key_to_ascii(int keycode ); +extern char *key_name(int keycode); // Convert keycode to the name of the key + +extern void key_debug(); // Does an INT3 + +//========================================================================== +// These are the unbuffered routines. Index by the keyboard scancode. + +// Set to 1 if the key is currently down, else 0 +extern volatile unsigned char keyd_pressed[]; +extern volatile unsigned char keyd_last_pressed; +extern volatile unsigned char keyd_last_released; + +// Returns the seconds this key has been down since last call. +extern fix key_down_time(int scancode); + +// Returns number of times key has went from up to down since last call. +extern unsigned int key_down_count(int scancode); + +// Returns number of times key has went from down to up since last call. +extern unsigned int key_up_count(int scancode); + +// Clears the times & counts used by the above functions +// Took out... use key_flush(); +//void key_clear_times(); +//void key_clear_counts(); + +extern char * key_text[256]; + +#define KEY_SHIFTED 0x100 +#define KEY_ALTED 0x200 +#define KEY_CTRLED 0x400 +#define KEY_DEBUGGED 0x800 + +#define KEY_0 11 +#define KEY_1 2 +#define KEY_2 3 +#define KEY_3 4 +#define KEY_4 5 +#define KEY_5 6 +#define KEY_6 7 +#define KEY_7 8 +#define KEY_8 9 +#define KEY_9 10 + +#define KEY_A 30 +#define KEY_B 48 +#define KEY_C 46 +#define KEY_D 32 +#define KEY_E 18 +#define KEY_F 33 +#define KEY_G 34 +#define KEY_H 35 +#define KEY_I 23 +#define KEY_J 36 +#define KEY_K 37 +#define KEY_L 38 +#define KEY_M 50 +#define KEY_N 49 +#define KEY_O 24 +#define KEY_P 25 +#define KEY_Q 16 +#define KEY_R 19 +#define KEY_S 31 +#define KEY_T 20 +#define KEY_U 22 +#define KEY_V 47 +#define KEY_W 17 +#define KEY_X 45 +#define KEY_Y 21 +#define KEY_Z 44 + +#define KEY_MINUS 12 +#define KEY_EQUAL 13 +#define KEY_DIVIDE 43 +#define KEY_SLASH 28 +#define KEY_COMMA 51 +#define KEY_PERIOD 52 +#define KEY_SEMICOL 39 + +#define KEY_LBRACKET 26 +#define KEY_RBRACKET 27 + +#define KEY_RAPOSTRO 40 +#define KEY_LAPOSTRO 41 + +#define KEY_ESC 1 +#define KEY_ENTER 28 +#define KEY_BACKSP 14 +#define KEY_TAB 15 +#define KEY_SPACEBAR 57 + +#define KEY_NUMLOCK 69 +#define KEY_SCROLLOCK 70 +#define KEY_CAPSLOCK 58 + +#define KEY_LSHIFT 42 +#define KEY_RSHIFT 54 + +#define KEY_LALT 56 +#define KEY_RALT 194 + +#define KEY_LCTRL 29 +#define KEY_RCTRL 157 + +#define KEY_F1 59 +#define KEY_F2 60 +#define KEY_F3 61 +#define KEY_F4 62 +#define KEY_F5 63 +#define KEY_F6 64 +#define KEY_F7 65 +#define KEY_F8 66 +#define KEY_F9 67 +#define KEY_F10 68 +#define KEY_F11 87 +#define KEY_F12 88 + +#define KEY_PAD0 82 +#define KEY_PAD1 79 +#define KEY_PAD2 80 +#define KEY_PAD3 81 +#define KEY_PAD4 75 +#define KEY_PAD5 76 +#define KEY_PAD6 77 +#define KEY_PAD7 71 +#define KEY_PAD8 72 +#define KEY_PAD9 73 +#define KEY_PADMINUS 74 +#define KEY_PADPLUS 78 +#define KEY_PADPERIOD 83 +#define KEY_PADDIVIDE 81 +#define KEY_PADMULTIPLY 55 +#define KEY_PADENTER 156 + +#define KEY_INSERT 210 +#define KEY_HOME 209 +#define KEY_PAGEUP 221 +#define KEY_DELETE 211 +#define KEY_END 217 +#define KEY_PAGEDOWN 219 +#define KEY_UP 200 +#define KEY_DOWN 208 +#define KEY_LEFT 203 +#define KEY_RIGHT 205 + +#define KEY_PRINT_SCREEN 165 +#define KEY_PAUSE 143 + +#endif diff --git a/arch/win32/include/mouse.h b/arch/win32/include/mouse.h new file mode 100644 index 00000000..a5a7d3f2 --- /dev/null +++ b/arch/win32/include/mouse.h @@ -0,0 +1,138 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/arch/win32/include/mouse.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:15 $ + * + * Header for mouse functions + * + * $Log: not supported by cvs2svn $ + * Revision 1.2 1999/10/09 05:04:34 donut + * added mouse_init and mouse_close declarations + * + * Revision 1.1.1.1 1999/06/14 22:01:24 donut + * Import of d1x 1.37 source. + * + * Revision 1.10 1995/02/02 10:22:29 john + * Added cyberman init parameter. + * + * Revision 1.9 1994/11/18 23:18:09 john + * Changed some shorts to ints. + * + * Revision 1.8 1994/09/13 12:33:49 john + * Added functions to get down count and state. + * + * Revision 1.7 1994/08/29 20:52:20 john + * Added better cyberman support; also, joystick calibration + * value return funcctiionn, + * + * Revision 1.6 1994/08/24 17:54:35 john + * *** empty log message *** + * + * Revision 1.5 1994/08/24 17:51:43 john + * Added transparent cyberman support + * + * Revision 1.4 1993/07/27 09:32:22 john + * *** empty log message *** + * + * Revision 1.3 1993/07/26 10:46:44 john + * added definition for mouse_set_pos + * + * Revision 1.2 1993/07/22 13:07:59 john + * added header for mousesetlimts + * + * Revision 1.1 1993/07/10 13:10:40 matt + * Initial revision + * + * + */ + +#ifndef MOUSE_H +#define MOUSE_H + +#include "types.h" +#include "fix.h" + +#define MOUSE_MAX_BUTTONS 11 + +#define MB_LEFT 0 + +#ifdef MB_RIGHT +#undef MB_RIGHT +#endif +#define MB_RIGHT 1 +#define MB_MIDDLE 2 +#define MB_Z_UP 3 +#define MB_Z_DOWN 4 +#define MB_PITCH_BACKWARD 5 +#define MB_PITCH_FORWARD 6 +#define MB_BANK_LEFT 7 +#define MB_BANK_RIGHT 8 +#define MB_HEAD_LEFT 9 +#define MB_HEAD_RIGHT 10 + +#define MOUSE_LBTN 1 +#define MOUSE_RBTN 2 +#define MOUSE_MBTN 4 + +#undef NOMOUSE +#ifndef NOMOUSE + +extern int mouse_init(int unused); +extern void mouse_close(void); + + +//======================================================================== +// Check for mouse driver, reset driver if installed. returns number of +// buttons if driver is present. + +extern int mouse_set_limits( int x1, int y1, int x2, int y2 ); +extern void mouse_flush(); // clears all mice events... + +//======================================================================== +extern void mouse_get_pos( int *x, int *y); +extern void mouse_get_delta( int *dx, int *dy ); +extern int mouse_get_btns(); +extern void mouse_set_pos( int x, int y); +extern void mouse_get_cyberman_pos( int *x, int *y ); + +// Returns how long this button has been down since last call. +extern fix mouse_button_down_time(int button); + +// Returns how many times this button has went down since last call. +extern int mouse_button_down_count(int button); + +// Returns 1 if this button is currently down +extern int mouse_button_state(int button); + +#else +// 'Neutered' functions... :-) +#define mouse_init(a) -1 +#define mouse_set_limits(a,b,c,d) -1 +#define mouse_flush() +#define mouse_close() +#define mouse_get_pos(a,b) +#define mouse_get_delta(a,b) +#define mouse_get_btns() 0 +#define mouse_set_pos(a,b) +#define mouse_get_cyberman_pos(a,b) +#define mouse_button_down_time(a) 0 +#define mouse_button_down_count(a) 0 +#define mouse_button_state(a) 0 + +#endif + +#endif + diff --git a/arch/win32/include/pch.h b/arch/win32/include/pch.h new file mode 100644 index 00000000..849fd7d7 --- /dev/null +++ b/arch/win32/include/pch.h @@ -0,0 +1,47 @@ +#define D3D_OVERLOADS +#define WIN32_MEAN_AND_LEAN + +#if 0 +class _Lockit +{ +public: + _Lockit () {} + ~_Lockit () {} +}; +#define _Lockit ___Lockit +#include +#undef _Lockit +#endif + + +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +#include +extern CComModule _Module; +#include + +#include "resource.h" + +#define ASSERT(x) _ASSERTE(x) + +#pragma warning (disable: 4786) diff --git a/arch/win32/include/resource.h b/arch/win32/include/resource.h new file mode 100644 index 00000000..d7008abf --- /dev/null +++ b/arch/win32/include/resource.h @@ -0,0 +1,27 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by d1x.rc +// +#define IDI_MAIN_ICON 101 +#define IDR_MAIN_ACCEL 113 +#define IDD_ABOUT 142 +#define IDR_MENU 143 +#define IDR_POPUP 145 +#define IDM_EXIT 40001 +#define IDM_CHANGEDEVICE 40010 +#define IDM_TOGGLEFULLSCREEN 40011 +#define IDM_HELP 40012 +#define IDM_TOGGLESTART 40013 +#define IDM_SINGLESTEP 40014 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_3D_CONTROLS 1 +#define _APS_NEXT_RESOURCE_VALUE 147 +#define _APS_NEXT_COMMAND_VALUE 40028 +#define _APS_NEXT_CONTROL_VALUE 1009 +#define _APS_NEXT_SYMED_VALUE 102 +#endif +#endif diff --git a/arch/win32/include/scene.h b/arch/win32/include/scene.h new file mode 100644 index 00000000..e1d9e23d --- /dev/null +++ b/arch/win32/include/scene.h @@ -0,0 +1,23 @@ +#ifndef __SCENE_H__ +#define __SCENE_H__ + +extern BOOL g_bAppUseZBuffer; +extern BOOL g_bAppUseBackBuffer; +extern TCHAR* g_strAppTitle; + +HRESULT App_ConfirmDevice( DDCAPS*, D3DDEVICEDESC* ); +HRESULT App_OneTimeSceneInit( HWND ); +VOID App_DeleteDeviceObjects( LPDIRECT3DDEVICE3, LPDIRECT3DVIEWPORT3 ); +HRESULT App_InitDeviceObjects( LPDIRECT3DDEVICE3, LPDIRECT3DVIEWPORT3 ); +HRESULT App_FrameMove( LPDIRECT3DDEVICE3, FLOAT ); +HRESULT App_Render( LPDIRECT3DDEVICE3, LPDIRECT3DVIEWPORT3, D3DRECT* ); +HRESULT App_RestoreSurfaces(); +HRESULT App_FinalCleanup( LPDIRECT3DDEVICE3, LPDIRECT3DVIEWPORT3 ); + + +HRESULT App_StartFrame( LPDIRECT3DDEVICE3, LPDIRECT3DVIEWPORT3, D3DRECT* ); +HRESULT App_EndFrame (); + + + +#endif // __SCENE_H__ diff --git a/arch/win32/include/serial.h b/arch/win32/include/serial.h new file mode 100644 index 00000000..2252ecd0 --- /dev/null +++ b/arch/win32/include/serial.h @@ -0,0 +1,15 @@ +#ifndef _SERIAL_H +#define _SERIAL_H + +extern void com_done(void); +extern int com_init(void); +extern int com_read(char *buffer, int len, int timeout_value); +extern int com_write(char *buffer, int len); +extern void com_port_hangup(); +extern int com_getdcd(); +extern void com_flushbuffers(); +extern void com_setbaudrate(int rate); +extern int com_readline(int timeout_value, char *input_buffer,int len); + +extern int commlib_initialised; +#endif diff --git a/arch/win32/include/texture.h b/arch/win32/include/texture.h new file mode 100644 index 00000000..d2c72eac --- /dev/null +++ b/arch/win32/include/texture.h @@ -0,0 +1,134 @@ +#ifndef __TEXTURE_H__ +#define __TEXTURE_H__ + +struct CPaletteInfo +{ + HRESULT Initialize (); + HRESULT Uninitialize (); + + LONG GetShift (DWORD dwMask) + { + ULONG cshft = 0; + while (dwMask) + { + cshft += 1; + dwMask >>= 1; + } + return cshft; + } + + DWORD ShiftLeft (DWORD dwVal, LONG lShift) + { + if (lShift > 0) + return dwVal << lShift; + else + return dwVal >> (-lShift); + } + + WORD Read16 (BYTE b) + { + DWORD dwPal = *(DWORD*) &m_rgpe [b]; + WORD w; + + w = ShiftLeft (dwPal, m_cshftR - 8) & m_mskR; + w |= ShiftLeft (dwPal, m_cshftG - 16) & m_mskG; + w |= ShiftLeft (dwPal, m_cshftB - 24) & m_mskB; + + return w; + } + + BOOL IsPow2 () const { return m_bPow2; } + BOOL IsSquare () const { return m_bSquare; } + + void GetPixelFormat (DDPIXELFORMAT *pddpf) { *pddpf = m_ddpfPixelFormat; } + BOOL IsIndexed () const { return m_ddpfPixelFormat.dwRGBBitCount == 8; } + void SetPaletteEntries (PALETTEENTRY rgpe [256]); + void GetPaletteEntries (PALETTEENTRY rgpe [256]); + + LPDIRECTDRAWPALETTE GetPalette () { return m_spddpPalette; } + PALETTEENTRY ReadPalette (BYTE b) const { return m_rgpe [b]; } + + DWORD m_mskR, m_mskG, m_mskB; + ULONG m_cshftR, m_cshftG, m_cshftB; + DDPIXELFORMAT m_ddpfPixelFormat; + BOOL m_bPow2, m_bSquare; + PALETTEENTRY m_rgpe [256]; + CComPtr m_spddpPalette; +}; + +struct CTexture +{ + HRESULT Initialize (BYTE *rgbSource, ULONG ulWidth, ULONG ulHeight, ULONG ulPitch); + + HRESULT Allocate (CPaletteInfo *ppi); + HRESULT Free (void); + + HRESULT Lock (void); + HRESULT Unlock (void); + void PlotPixel (ULONG ulX, ULONG ulY, BYTE b); + void SetBitmapData (BYTE *rgb, BOOL bRle); + void CopyFromSource (void); + + void DirtyMemory (void) { m_bDirtyMemory = TRUE; } + BOOL isDirtyMemory (void) const { return m_bDirtyMemory; } + HRESULT CleanMemory (void); + + void SetTransparent (BOOL bTransparent) { m_bTransparent = bTransparent; } + BOOL IsTransparent (void) const { return m_bTransparent; } + + ULONG GetPixelCount () const { return m_ulHeight * m_ulWidth; } + void GetBitmapAdj (D3DVALUE *pflAdjX, D3DVALUE *pflAdjY) + { + *pflAdjX = m_flAdjX; + *pflAdjY = m_flAdjY; + } + + IDirectDrawSurface4 *GetSurface () { return m_spddsMemory; } + IDirect3DTexture2 *GetTexture (); + + ULONG m_ulWidth; + ULONG m_ulHeight; + ULONG m_ulWidthSource; + ULONG m_ulHeightSource; + +protected: + CComPtr m_spddsMemory; + CComQIPtr m_spddtMemory; + ULONG m_ulPitchSource; + ULONG m_ulAge; + BYTE *m_rgbSource; + + BOOL m_bDirtyMemory; + BOOL m_bTransparent; + BOOL m_bRle; + D3DVALUE m_flAdjX, m_flAdjY; + +public: + static CPaletteInfo *m_ppi; + static DDSURFACEDESC2 s_ddsd; + static BOOL s_bLocked; +}; + +struct CTextureSet +{ + HRESULT Initialize (); + HRESULT Uninitialize (); + + CTexture *CreateTexture (BYTE *rgbSource, ULONG dx, ULONG dy, ULONG ulPitch); + void FreeTexture (CTexture *pTexture); + void SetPaletteEntries (PALETTEENTRY rgpe [256]); + void GetPaletteEntries (PALETTEENTRY rgpe [256]); + void DirtyTextures (void); + + PALETTEENTRY ReadPalette (BYTE b) { return m_pi.ReadPalette (b); } + BOOL HasPalette () { return m_pi.IsIndexed (); } + +protected: + typedef std::set TEXTURE_SET; + TEXTURE_SET m_setTextures; + CPaletteInfo m_pi; +}; + + + +#endif // __TEXTURE_H__ diff --git a/arch/win32/include/winmain.h b/arch/win32/include/winmain.h new file mode 100644 index 00000000..ee0f2082 --- /dev/null +++ b/arch/win32/include/winmain.h @@ -0,0 +1,17 @@ +#ifndef __WINMAIN_H__ +#define __WINMAIN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int InitMain (void); +extern void PumpMessages (void); + +extern HWND g_hWnd; + +#ifdef __cplusplus +} +#endif + +#endif // __WINMAIN_H__ diff --git a/arch/win32/include/wsipx.h b/arch/win32/include/wsipx.h new file mode 100644 index 00000000..ede59eba --- /dev/null +++ b/arch/win32/include/wsipx.h @@ -0,0 +1,58 @@ +/* + * wsipx.h + * + * Microsoft Windows + * Copyright (C) Microsoft Corporation, 1992-1996. + * + * Windows Sockets include file for IPX/SPX. This file contains all + * standardized IPX/SPX information. Include this header file after + * winsock.h. + * + * To open an IPX socket, call socket() with an address family of + * AF_IPX, a socket type of SOCK_DGRAM, and protocol NSPROTO_IPX. + * Note that the protocol value must be specified, it cannot be 0. + * All IPX packets are sent with the packet type field of the IPX + * header set to 0. + * + * To open an SPX or SPXII socket, call socket() with an address + * family of AF_IPX, socket type of SOCK_SEQPACKET or SOCK_STREAM, + * and protocol of NSPROTO_SPX or NSPROTO_SPXII. If SOCK_SEQPACKET + * is specified, then the end of message bit is respected, and + * recv() calls are not completed until a packet is received with + * the end of message bit set. If SOCK_STREAM is specified, then + * the end of message bit is not respected, and recv() completes + * as soon as any data is received, regardless of the setting of the + * end of message bit. Send coalescing is never performed, and sends + * smaller than a single packet are always sent with the end of + * message bit set. Sends larger than a single packet are packetized + * with the end of message bit set on only the last packet of the + * send. + * + */ + +#ifndef _WSIPX_ +#define _WSIPX_ + +/* + * This is the structure of the SOCKADDR structure for IPX and SPX. + * + */ + +typedef struct sockaddr_ipx { + short sa_family; + char sa_netnum[4]; + char sa_nodenum[6]; + unsigned short sa_socket; +} SOCKADDR_IPX, *PSOCKADDR_IPX,FAR *LPSOCKADDR_IPX; + +/* + * Protocol families used in the "protocol" parameter of the socket() API. + * + */ + +#define NSPROTO_IPX 1000 +#define NSPROTO_SPX 1256 +#define NSPROTO_SPXII 1257 + +#endif + diff --git a/arch/win32/init.c b/arch/win32/init.c new file mode 100644 index 00000000..25d639f7 --- /dev/null +++ b/arch/win32/init.c @@ -0,0 +1,198 @@ +#include +#include +#include +#include +#include +#include +#include "args.h" + +#ifndef NDEBUG +#ifdef _MSC_VER +#include +#endif +#endif + +extern HINSTANCE hInst; +extern HWND g_hWnd; +extern LPDIRECTDRAW lpDD; +extern LPDIRECTDRAWSURFACE lpDDSPrimary; +extern LPDIRECTDRAWSURFACE lpDDSOne; +extern LPDIRECTDRAWPALETTE lpDDPal; + +extern int Inferno_verbose; + +static int mouse_hidden=0; + +static void finiObjects() +{ + if(lpDD!=NULL) + { + if(lpDDSPrimary!=NULL) + { + IDirectDrawSurface_Release(lpDDSPrimary); + lpDDSPrimary=NULL; + } + if(lpDDSOne!=NULL) + { + IDirectDrawSurface_Unlock(lpDDSOne,NULL); + IDirectDrawSurface_Release(lpDDSOne); + lpDDSOne=NULL; + } + if(lpDDPal!=NULL) + { + IDirectDrawSurface_Release(lpDDPal); + lpDDPal=NULL; + } + IDirectDrawSurface_Release(lpDD); + lpDD=NULL; + } + if(mouse_hidden) + ShowCursor(TRUE); +} + +//extern unsigned int key_wparam, key_lparam, key_msg; +void keyboard_handler(); +extern int WMKey_Handler_Ready; + +void PumpMessages(void) +{ + MSG msg; + + while (PeekMessage(&msg,NULL,0,0,PM_REMOVE|PM_NOYIELD)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +long PASCAL DescentWndProc(HWND hWnd,UINT message, + WPARAM wParam,LPARAM lParam ) +{ + switch(message) + { + + case WM_KEYDOWN: + case WM_KEYUP: + if (WMKey_Handler_Ready) { +// key_wparam=wParam; key_lparam=lParam; key_msg=message; + keyboard_handler(); + } + break; + case WM_MOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_NCMOUSEMOVE: + case WM_NCLBUTTONDOWN: + case WM_NCLBUTTONUP: + case WM_NCRBUTTONDOWN: + case WM_NCRBUTTONUP: + break; + case WM_PALETTECHANGED: + case WM_PALETTEISCHANGING: + return 0; + case WM_ACTIVATEAPP: +// Win32_Key_Hook(wParam); +// DPH: This doesn't work... no idea why not... + break; + case WM_DESTROY: + finiObjects(); + PostQuitMessage(0); + break; + } + return DefWindowProc(hWnd,message,wParam,lParam); +} + +void arch_init_start() +{ + WNDCLASS wcDescentClass; + + #ifndef NDEBUG + #ifdef _MSC_VER + if (FindArg("-memdbg")) + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | /* _CRTDBG_CHECK_ALWAYS_DF | */ + /*_CRTDBG_CHECK_CRT_DF |*/ + _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF); + #endif + #endif + + wcDescentClass.lpszClassName = "WinD1X"; + wcDescentClass.hInstance = hInst; + wcDescentClass.lpfnWndProc = DescentWndProc; + wcDescentClass.hCursor = LoadCursor(NULL, IDC_ARROW); + wcDescentClass.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wcDescentClass.lpszMenuName = NULL; + wcDescentClass.hbrBackground = NULL; + wcDescentClass.style = CS_HREDRAW | CS_VREDRAW; + wcDescentClass.cbClsExtra = 0; + wcDescentClass.cbWndExtra = 0; + + // Register the class + RegisterClass(&wcDescentClass); + g_hWnd = CreateWindowEx(0, + "WinD1X", + "Descent", + WS_OVERLAPPED | WS_BORDER, + 0, 0, + GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN), + NULL, + NULL, + hInst, + NULL + ); + + if (!g_hWnd) return; // CRAP! + ShowWindow(g_hWnd,SW_SHOWNORMAL); + UpdateWindow(g_hWnd); +} + +extern void key_init(void); +extern void mouse_init(void); +//added/changed 3/7/99 Owen Evans (next line) +extern void joy_init(int joyid); + +void arch_init() +{ + HRESULT ddrval; + + + ddrval=DirectDrawCreate(NULL,&lpDD,NULL); + + if(ddrval!=DD_OK) + { + fprintf(stderr,"DirectDrawCreate() failed!\n"); + abort(); + } + + if (FindArg("-semiwin")) + ddrval=IDirectDraw_SetCooperativeLevel(lpDD,g_hWnd,DDSCL_NORMAL); + else + { + #ifndef NDEBUG + ddrval=IDirectDraw_SetCooperativeLevel(lpDD,g_hWnd, + DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN|DDSCL_ALLOWREBOOT); +#else + ddrval=IDirectDraw_SetCooperativeLevel(lpDD,g_hWnd, + DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN|DDSCL_ALLOWREBOOT); +#endif + } + + if (ddrval!=DD_OK) + { + fprintf(stderr,"SetCooperativeLevel() failed\n"); + abort(); + } + + ShowCursor(FALSE); + mouse_hidden = 1; + + SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS); + + key_init(); + mouse_init(); +//added/changed 3/7/99 Owen Evans (next line) + joy_init(JOYSTICKID1); + printf("arch_init successfully completed\n"); +} diff --git a/arch/win32/ipx_drv.h b/arch/win32/ipx_drv.h new file mode 100644 index 00000000..a042239f --- /dev/null +++ b/arch/win32/ipx_drv.h @@ -0,0 +1,68 @@ +/* + * IPX driver interface + * + * parts from: + * ipx.h header file for IPX for the DOS emulator + * Tim Bird, tbird@novell.com + */ +#ifndef _IPX_DRV_H +#define _IPX_DRV_H +#define IPX_MANUAL_ADDRESS + +#include "types.h" + +#define MAX_PACKET_DATA 1500 + +#ifdef _MSC_VER +#pragma pack (push, 1) +#endif + +typedef struct IPXAddressStruct { + u_char Network[4] __pack__; + u_char Node[6] __pack__; + u_char Socket[2] __pack__; +} IPXAddress_t; + +typedef struct IPXPacketStructure { + u_short Checksum __pack__; + u_short Length __pack__; + u_char TransportControl __pack__; + u_char PacketType __pack__; + IPXAddress_t Destination __pack__; + IPXAddress_t Source __pack__; +} IPXPacket_t; + +#ifdef _MSC_VER +#pragma pack (pop) +#endif + +typedef struct ipx_socket_struct { + u_short socket; + int fd; +} ipx_socket_t; + +struct ipx_recv_data { + /* all network order */ + u_char src_network[4]; + u_char src_node[6]; + u_short src_socket; + u_short dst_socket; + int pkt_type; +}; + +struct ipx_driver { + int (*GetMyAddress)(void); + int (*OpenSocket)(ipx_socket_t *sk, int port); + void (*CloseSocket)(ipx_socket_t *mysock); + int (*SendPacket)(ipx_socket_t *mysock, IPXPacket_t *IPXHeader, + u_char *data, int dataLen); + int (*ReceivePacket)(ipx_socket_t *s, char *buffer, int bufsize, + struct ipx_recv_data *rec); + int (*PacketReady)(ipx_socket_t *s); +}; + +int ipx_general_PacketReady(ipx_socket_t *s); + +extern unsigned char ipx_MyAddress[10]; + +#endif /* _IPX_DRV_H */ diff --git a/arch/win32/ipx_win.c b/arch/win32/ipx_win.c new file mode 100644 index 00000000..ed44b6f0 --- /dev/null +++ b/arch/win32/ipx_win.c @@ -0,0 +1,195 @@ +/* IPX driver using BSD style sockets */ +/* Mostly taken from dosemu */ +#include +#include +#include +#include +#include + +#include "ipx_drv.h" + +#include "mono.h" + +//#define n_printf(format, args...) mprintf((1, format, ## args)) + +static int ipx_win_GetMyAddress( void ) +{ +#if 0 + int sock; + struct sockaddr_ipx ipxs; + struct sockaddr_ipx ipxs2; + int len; + int i; + +// sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX); + sock=socket(AF_IPX,SOCK_DGRAM,0); + + if(sock==-1) + { + mprintf((1,"IPX: could not open socket in GetMyAddress\n")); + return(-1); + } + + /* bind this socket to network 0 */ + ipxs.sa_family=AF_IPX; +#ifdef IPX_MANUAL_ADDRESS + memcpy(ipxs.sa_netnum, ipx_MyAddress, 4); +#else + memset(ipxs.sa_netnum, 0, 4); +#endif + ipxs.sa_socket=0; + + if(bind(sock,(struct sockaddr *)&ipxs,sizeof(ipxs))==-1) + { + mprintf((1,"IPX: could bind to network 0 in GetMyAddress\n")); + closesocket( sock ); + return(-1); + } + + len = sizeof(ipxs2); + if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) { + mprintf((1,"IPX: could not get socket name in GetMyAddress\n")); + closesocket( sock ); + return(-1); + } + + memcpy(ipx_MyAddress, ipxs2.sa_netnum, 4); + for (i = 0; i < 6; i++) { + ipx_MyAddress[4+i] = ipxs2.sa_nodenum[i]; + } +/* printf("My address is 0x%.4X:%.2X.%.2X.%.2X.%.2X.%.2X.%.2X\n", *((int *)ipxs2.sa_netnum), ipxs2.sa_nodenum[0], + ipxs2.sa_nodenum[1], ipxs2.sa_nodenum[2], ipxs2.sa_nodenum[3], ipxs2.sa_nodenum[4], ipxs2.sa_nodenum[5]);*/ + + closesocket( sock ); + +#endif + return(0); +} + +static int ipx_win_OpenSocket(ipx_socket_t *sk, int port) +{ + int sock; /* sock here means Linux socket handle */ + int opt; + struct sockaddr_ipx ipxs; + int len; + struct sockaddr_ipx ipxs2; + + /* DANG_FIXTHIS - kludge to support broken linux IPX stack */ + /* need to convert dynamic socket open into a real socket number */ +/* if (port == 0) { + mprintf((1,"IPX: using socket %x\n", nextDynamicSocket)); + port = nextDynamicSocket++; + } +*/ + /* do a socket call, then bind to this port */ +// sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX); + sock = socket(AF_IPX, SOCK_DGRAM, 0); + if (sock == -1) { + mprintf((1,"IPX: could not open IPX socket.\n")); + return -1; + } + + + opt = 1; + /* Permit broadcast output */ + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, + (const char *)&opt, sizeof(opt)) == -1) { + mprintf((1,"IPX: could not set socket option for broadcast.\n")); + return -1; + } + ipxs.sa_family = AF_IPX; + memcpy(ipxs.sa_netnum, ipx_MyAddress, 4); +// *((unsigned int *)&ipxs.sa_netnum[0]) = *((unsigned int *)&ipx_MyAddress[0]); +/* ipxs.sa_netnum = htonl(MyNetwork); */ + memset(ipxs.sa_nodenum, 0, 6); +// bzero(ipxs.sa_nodenum, 6); /* Please fill in my node name */ + ipxs.sa_socket = htons((short)port); + + /* now bind to this port */ + if (bind(sock, (struct sockaddr *) &ipxs, sizeof(ipxs)) == -1) { + mprintf((1,"IPX: could not bind socket to address\n")); + closesocket( sock ); + return -1; + } + +// if( port==0 ) { +// len = sizeof(ipxs2); +// if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) { +// //n_printf("IPX: could not get socket name in IPXOpenSocket\n"); +// closesocket( sock ); +// return -1; +// } else { +// port = htons(ipxs2.sa_socket); +// //n_printf("IPX: opened dynamic socket %04x\n", port); +// } + len = sizeof(ipxs2); + if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) { + mprintf((1,"IPX: could not get socket name in IPXOpenSocket\n")); + closesocket( sock ); + return -1; + } + if (port == 0) { + port = htons(ipxs2.sa_socket); + mprintf((1,"IPX: opened dynamic socket %04x\n", port)); + } + + memcpy(ipx_MyAddress, ipxs2.sa_netnum, 4); + memcpy(ipx_MyAddress + 4, ipxs2.sa_nodenum, 6); + + sk->fd = sock; + sk->socket = port; + return 0; +} + +static void ipx_win_CloseSocket(ipx_socket_t *mysock) { + /* now close the file descriptor for the socket, and free it */ + mprintf((1,"IPX: closing file descriptor on socket %x\n", mysock->socket)); + closesocket(mysock->fd); +} + +static int ipx_win_SendPacket(ipx_socket_t *mysock, IPXPacket_t *IPXHeader, + u_char *data, int dataLen) { + struct sockaddr_ipx ipxs; + + ipxs.sa_family = AF_IPX; + /* get destination address from IPX packet header */ + memcpy(&ipxs.sa_netnum, IPXHeader->Destination.Network, 4); + /* if destination address is 0, then send to my net */ + if ((*(unsigned int *)&ipxs.sa_netnum) == 0) { + (*(unsigned int *)&ipxs.sa_netnum)= *((unsigned int *)&ipx_MyAddress[0]); +/* ipxs.sa_netnum = htonl(MyNetwork); */ + } + memcpy(&ipxs.sa_nodenum, IPXHeader->Destination.Node, 6); + memcpy(&ipxs.sa_socket, IPXHeader->Destination.Socket, 2); +// ipxs.sa_type = IPXHeader->PacketType; + /* ipxs.sipx_port=htons(0x452); */ + return sendto(mysock->fd, data, dataLen, 0, + (struct sockaddr *) &ipxs, sizeof(ipxs)); +} + +static int ipx_win_ReceivePacket(ipx_socket_t *s, char *buffer, int bufsize, + struct ipx_recv_data *rd) { + int sz, size; + struct sockaddr_ipx ipxs; + + sz = sizeof(ipxs); + if ((size = recvfrom(s->fd, buffer, bufsize, 0, + (struct sockaddr *) &ipxs, &sz)) <= 0) + return size; + memcpy(rd->src_network, ipxs.sa_netnum, 4); + memcpy(rd->src_node, ipxs.sa_nodenum, 6); + rd->src_socket = ipxs.sa_socket; + rd->dst_socket = s->socket; +// rd->pkt_type = ipxs.sipx_type; + + return size; +} + +struct ipx_driver ipx_win = { + ipx_win_GetMyAddress, + ipx_win_OpenSocket, + ipx_win_CloseSocket, + ipx_win_SendPacket, + ipx_win_ReceivePacket, + ipx_general_PacketReady +}; diff --git a/arch/win32/joydefs.c b/arch/win32/joydefs.c new file mode 100644 index 00000000..eece039c --- /dev/null +++ b/arch/win32/joydefs.c @@ -0,0 +1,145 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#include +#include +#include + +#include "mono.h" +#include "key.h" +#include "joy.h" +#include "timer.h" +#include "error.h" + +#include "inferno.h" +#include "game.h" +#include "object.h" +#include "player.h" + +#include "controls.h" +#include "joydefs.h" +#include "render.h" +#include "palette.h" +#include "newmenu.h" +#include "args.h" +#include "text.h" +#include "kconfig.h" +#include "digi.h" +#include "playsave.h" + +int joydefs_calibrate_flag=0; + +int Joy_is_Sidewinder=0; //not needed, but lots of main/* stuff use it + +void joy_delay() +{ + +} + +int joycal_message( char * title, char * text ) +{ + int i; + newmenu_item m[2]; + m[0].type = NM_TYPE_TEXT; m[0].text = text; + m[1].type = NM_TYPE_MENU; m[1].text = TXT_OK; + i = newmenu_do( title, NULL, 2, m, NULL ); + if ( i < 0 ) + return 1; + return 0; +} + +void joydefs_calibrate() +{ + joycal_message("No Calibration", "calibration should be performed\nthrough windows"); + return; +} + +void joydef_menuset_1(int nitems, newmenu_item * items, int *last_key, int citem ) +{ + int i; + int oc_type = Config_control_type; + + nitems = nitems; + last_key = last_key; + citem = citem; + + for (i=0; i<3; i++ ) + if (items[i].value) Config_control_type = i; + + if (Config_control_type == 2) Config_control_type = CONTROL_MOUSE; + + if ( (oc_type != Config_control_type) && (Config_control_type == CONTROL_THRUSTMASTER_FCS ) ) { + nm_messagebox( TXT_IMPORTANT_NOTE, 1, TXT_OK, TXT_FCS ); + } + + if (oc_type != Config_control_type) { + switch (Config_control_type) { + // case CONTROL_NONE: + case CONTROL_JOYSTICK: + case CONTROL_FLIGHTSTICK_PRO: + case CONTROL_THRUSTMASTER_FCS: + case CONTROL_GRAVIS_GAMEPAD: + // case CONTROL_MOUSE: + // case CONTROL_CYBERMAN: + joydefs_calibrate_flag = 1; + } + kc_set_controls(); + } + +} + +extern ubyte kc_use_external_control; +extern ubyte kc_enable_external_control; +extern ubyte *kc_external_name; + +void joydefs_config() +{ + newmenu_item m[13]; + int i, j, i1=0, nitems=7; + + m[0].type = NM_TYPE_RADIO; m[0].text = "KEYBOARD"; m[0].value = 0; m[0].group = 0; + m[1].type = NM_TYPE_RADIO; m[1].text = "JOYSTICK"; m[1].value = 0; m[1].group = 0; + m[2].type = NM_TYPE_RADIO; m[2].text = "MOUSE"; m[2].value = 0; m[2].group = 0; + m[3].type = NM_TYPE_TEXT; m[3].text=""; + m[4].type = NM_TYPE_MENU; m[4].text="CUSTOMIZE ABOVE"; + m[5].type = NM_TYPE_MENU; m[5].text="CUSTOMIZE KEYBOARD"; + m[6].type = NM_TYPE_MENU; m[6].text="CUSTOMIZE D1X KEYS"; + + do { + i = Config_control_type; + if(i==CONTROL_MOUSE) i = 2; + m[i].value=1; + i1 = newmenu_do1( NULL, TXT_CONTROLS, nitems, m, joydef_menuset_1, i1 ); + +//added 6-15-99 Owen Evans + for (j = 0; j <= 2; j++) + if (m[j].value) + Config_control_type = j; + i = Config_control_type; + if (Config_control_type == 2) + Config_control_type = CONTROL_MOUSE; +//end added - OE + + switch(i1) { + case 4: + kconfig (i, m[i].text); + break; + case 5: + kconfig(0, "KEYBOARD"); + break; + case 6: + kconfig(3, "D1X KEYS"); + break; + } + } while(i1>-1); +} diff --git a/arch/win32/joyhh.c b/arch/win32/joyhh.c new file mode 100644 index 00000000..3e78598d --- /dev/null +++ b/arch/win32/joyhh.c @@ -0,0 +1,640 @@ +//JOYC.C for D1_3Dfx and D1OpenGL +//D1_3Dfx is a Win32 executable using Glide and DirectX 3 +//D1OpenGL is a Win32 executable using OpenGL and DirectX 3 +//This joystick code should run on DirectInput 2 and higher +//We are not using DirectX 5 for now, since we want to stay compatible to the HH-loved Windows NT :). +//So ForceFeedback is not supported + +//Notes: +// 1) Windows DirectX supports up to 7 axes, D1/DOS only 4, so we needed to increase the number to 7 at several points +// Also JOY_ALL_AXIS must be (1+2+4+8+16+32+64) in JOY.H file +// 2) Windows DirectX supports up to 32 buttons. So far we however only support 4. Adding support for more should be however easily possible. +// 3) _enable and _disable are not needed +// 4) joy_bogus_reading is not needed, so all calls are just removed +// 5) The joystick query goes over the DirectInputs function +// MMRESULT joyGetPosEx(UINT uJoyID, LPJOYINFOEX pji); +// All functions reading over BIOS, including the ASM code are removed + + + +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +/* +Modifications by Heiko Herrmann +Later modified by Owen Evans to work with D1X (3/7/99) +*/ + + +#define _WIN32_OS //HH + +#include //HH +#include //HH +#include +#include + +#include "types.h" +#include "joy.h" +#include "timer.h" + +#define my_hwnd g_hWnd // D1X compatibility +extern HWND g_hWnd; + +char joy_installed = 0; +char joy_present = 0; + +typedef struct Button_info { + ubyte ignore; + ubyte state; + ubyte last_state; + int timedown; + ubyte downcount; + ubyte upcount; +} Button_info; + +typedef struct Joy_info { + int joyid; + ubyte present_mask; + ubyte slow_read; + int max_timer; + int read_count; + ubyte last_value; + Button_info buttons[MAX_BUTTONS]; + int axis_min[JOY_NUM_AXES]; //changed + int axis_center[JOY_NUM_AXES]; //changed --orulz + int axis_max[JOY_NUM_AXES]; //changed +} Joy_info; + +Joy_info joystick; + + +int joy_deadzone = 0; + +void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max) +{ + int i; + + for (i=0; iignore) { + if ( i < (MAX_BUTTONS-4) ) + state = (value >> i) & 1; + else + state = 0; + + if ( button->last_state == state ) { + if (state) { + button->timedown += time_diff; //ticks_this_time; + } + } else { + if (state) { + button->downcount += state; + button->state = 1; + } else { + button->upcount += button->state; + button->state = 0; + } + button->last_state = state; + } + } + } + + time_last = time_now; + return 0; +} + + +//Begin section modified 3/7/99 - Owen Evans + +ubyte joy_read_raw_buttons() +{ + JOYINFOEX joy; + int i; + + if (!joy_present) + return 0; + + memset(&joy, 0, sizeof(joy)); + joy.dwSize = sizeof(joy); + joy.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOVCTS | JOY_USEDEADZONE; + + if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR) + return 0; + + for (i = 0; i < MAX_BUTTONS; i++) { + joystick.buttons[i].last_state = joystick.buttons[i].state; + joystick.buttons[i].state = (joy.dwButtons >> i) & 0x1; + if (!joystick.buttons[i].last_state && joystick.buttons[i].state) { + joystick.buttons[i].timedown = timer_get_fixed_seconds(); + joystick.buttons[i].downcount++; + } + } + + /* Hat stuff */ + + if (joy.dwPOV != JOY_POVCENTERED) + { + joystick.buttons[19].state = (joy.dwPOV < JOY_POVRIGHT || joy.dwPOV > JOY_POVLEFT); + joystick.buttons[15].state = (joy.dwPOV < JOY_POVBACKWARD && joy.dwPOV > JOY_POVFORWARD); + joystick.buttons[11].state = (joy.dwPOV < JOY_POVLEFT && joy.dwPOV > JOY_POVRIGHT); + joystick.buttons[7].state = (joy.dwPOV > JOY_POVBACKWARD); + } + + return (ubyte)joy.dwButtons; +} + +//end changed section - OE + + +ubyte joystick_read_raw_axis( ubyte mask, int * axis ) +{ + JOYINFOEX joy; + ubyte read_masks = 0; + + axis[0] = 0; axis[1] = 0; //orulz: 1=x 2=y 3=r 4=z 5=u 6=v + axis[2] = 0; axis[3] = 0; + axis[4] = 0; axis[5] = 0; //HH: Added support for axes R and U + + if (!joy_installed) { + return 0; + } + + memset(&joy, 0, sizeof(joy)); + joy.dwSize = sizeof(joy); + joy.dwFlags = JOY_RETURNALL | JOY_USEDEADZONE; + if (joyGetPosEx(joystick.joyid, &joy)!=JOYERR_NOERROR) { + return 0; + } + + mask &= joystick.present_mask; // Don't read non-present channels + if ( mask==0 ) { + return 0; // Don't read if no stick connected. + } + + if (mask & JOY_1_X_AXIS) { axis[0] = joy.dwXpos; read_masks |= JOY_1_X_AXIS; } + if (mask & JOY_1_Y_AXIS) { axis[1] = joy.dwYpos; read_masks |= JOY_1_Y_AXIS; } +//orulz: +// if (mask & JOY_1_Z_AXIS) { axis[2] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; } +// if (mask & JOY_1_POV) { axis[3] = joy.dwPOV; read_masks |= JOY_1_POV; } +// if (mask & JOY_1_R_AXIS) { axis[4] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; } +// if (mask & JOY_1_U_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_U_AXIS; } +// if (mask & JOY_1_V_AXIS) { axis[6] = joy.dwVpos; read_masks |= JOY_1_V_AXIS; } + if (mask & JOY_1_R_AXIS) { axis[2] = joy.dwRpos; read_masks |= JOY_1_R_AXIS; } + if (mask & JOY_1_Z_AXIS) { axis[3] = joy.dwZpos; read_masks |= JOY_1_Z_AXIS; } + if (mask & JOY_1_U_AXIS) { axis[4] = joy.dwZpos; read_masks |= JOY_1_U_AXIS; } + if (mask & JOY_1_V_AXIS) { axis[5] = joy.dwUpos; read_masks |= JOY_1_V_AXIS; } + + return read_masks; +} + +int hh_average(int val1, int val2) +{ + return abs(val1-val2)/2; +} + +int joy_init(int joyid) //HH: added joyid parameter +{ + int i; + int temp_axis[JOY_NUM_AXES]; //changed - orulz + JOYCAPS pjc; + + atexit(joy_close); //HH: we are a bit lazy :). Errors are ignored, so we are even double-lazy :) + + joy_flush(); + memset(&joystick, 0, sizeof(joystick)); + + for (i=0; i 127 ) x = 127; + +//added on 4/13/99 by Victor Rachels to add deadzone control + d = (joy_deadzone) * 6; + if ((x > (-1*d)) && (x < d)) + x = 0; +//end this section addition -VR + + return x; +} + +void joy_get_pos( int *x, int *y ) +{ + ubyte flags; + int axis[JOY_NUM_AXES]; + + if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; } + + flags=joystick_read_raw_axis( JOY_1_X_AXIS+JOY_1_Y_AXIS, axis ); + + if ( flags & JOY_1_X_AXIS ) + *x = joy_get_scaled_reading( axis[0], 0 ); + else + *x = 0; + + if ( flags & JOY_1_Y_AXIS ) + *y = joy_get_scaled_reading( axis[1], 1 ); + else + *y = 0; +} + +ubyte joy_read_stick( ubyte masks, int *axis ) +{ + ubyte flags; + int raw_axis[JOY_NUM_AXES]; + + if ((!joy_installed)||(!joy_present)) { + axis[0] = 0; axis[1] = 0; + axis[2] = 0; axis[3] = 0; + axis[4] = 0; axis[5] = 0; + return 0; + } + + flags=joystick_read_raw_axis( masks, raw_axis ); + + if ( flags & JOY_1_X_AXIS ) + axis[0] = joy_get_scaled_reading( raw_axis[0], 0 ); + else + axis[0] = 0; + + if ( flags & JOY_1_Y_AXIS ) + axis[1] = joy_get_scaled_reading( raw_axis[1], 1 ); + else + axis[1] = 0; + + if ( flags & JOY_1_R_AXIS ) + axis[2] = joy_get_scaled_reading( raw_axis[2], 2 ); + else + axis[2] = 0; + + if ( flags & JOY_1_Z_AXIS ) + axis[3] = joy_get_scaled_reading( raw_axis[3], 3 ); + else + axis[3] = 0; + + if ( flags & JOY_1_U_AXIS ) + axis[4] = joy_get_scaled_reading( raw_axis[4], 4); + else + axis[4] = 0; + + if ( flags & JOY_1_V_AXIS ) + axis[5] = joy_get_scaled_reading( raw_axis[5], 5 ); + else + axis[5] = 0; + + + return flags; +} + +int joy_get_btns() +{ + if ((!joy_installed)||(!joy_present)) return 0; + + return joy_read_raw_buttons(); +} + + +//Begin section modified 3/7/99 - Owen Evans + +void joy_get_btn_down_cnt( int *btn0, int *btn1 ) +{ + if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; } + + joy_get_btns(); + + *btn0 = joystick.buttons[0].downcount; + joystick.buttons[0].downcount = 0; + *btn1 = joystick.buttons[1].downcount; + joystick.buttons[1].downcount = 0; +} + +int joy_get_button_state( int btn ) +{ + if ((!joy_installed)||(!joy_present)) return 0; + if ( btn >= MAX_BUTTONS ) return 0; + + joy_get_btns(); + + return joystick.buttons[btn].state; +} + +int joy_get_button_up_cnt( int btn ) +{ + int count; + + if ((!joy_installed)||(!joy_present)) return 0; + + if ( btn >= MAX_BUTTONS ) return 0; + + count = joystick.buttons[btn].upcount; + joystick.buttons[btn].upcount = 0; + + return count; +} + +int joy_get_button_down_cnt( int btn ) +{ + int count; + + if ((!joy_installed)||(!joy_present)) return 0; + if ( btn >= MAX_BUTTONS ) return 0; + + joy_get_btns(); + + count = joystick.buttons[btn].downcount; + joystick.buttons[btn].downcount = 0; + + return count; +} + +fix joy_get_button_down_time( int btn ) +{ + fix count; + + if ((!joy_installed)||(!joy_present)) return 0; + if ( btn >= MAX_BUTTONS ) return 0; + + joy_get_btns(); + + if (joystick.buttons[btn].state) { + count = timer_get_fixed_seconds() - joystick.buttons[btn].timedown; + joystick.buttons[btn].timedown = 0; + } else count = 0; + + return count; +} + +//end changed section - OE + + +void joy_get_btn_up_cnt( int *btn0, int *btn1 ) +{ + if ((!joy_installed)||(!joy_present)) { *btn0=*btn1=0; return; } + + *btn0 = joystick.buttons[0].upcount; + joystick.buttons[0].upcount = 0; + *btn1 = joystick.buttons[1].upcount; + joystick.buttons[1].upcount = 0; +} + +void joy_set_btn_values( int btn, int state, fix timedown, int downcount, int upcount ) +{ + joystick.buttons[btn].ignore = 1; + joystick.buttons[btn].state = state; + joystick.buttons[btn].timedown = fixmuldiv( timedown, 1193180, 65536 ); + joystick.buttons[btn].downcount = downcount; + joystick.buttons[btn].upcount = upcount; +} + +void joy_poll() +{ +} + diff --git a/arch/win32/key.c b/arch/win32/key.c new file mode 100644 index 00000000..3ac64376 --- /dev/null +++ b/arch/win32/key.c @@ -0,0 +1,481 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +//#include "inferno.h" +#include "fix.h" +#include "timer.h" +#include "key.h" + +extern void PumpMessages(void); + +// These are to kludge up a bit my slightly broken GCC directx port. +#ifndef E_FAIL +#define E_FAIL (HRESULT)0x80004005L +#endif +#ifndef SUCCEEDED +#define SUCCEEDED(a) ((HRESULT)(a) >= 0) +#endif +#ifndef S_OK +#define S_OK 0 +#define S_FALSE 1 +#endif + +extern void PumpMessages(void); + +volatile int keyd_time_when_last_pressed; +volatile unsigned char keyd_last_pressed; +volatile unsigned char keyd_last_released; +volatile unsigned char keyd_pressed [256]; +unsigned char keyd_repeat; +unsigned char WMKey_Handler_Ready=0; + + +fix g_rgtimeDown [256]; +fix g_rgtimeElapsed [256]; +ULONG g_rgcDowns [256]; +ULONG g_rgcUps [256]; + +char ascii_table[256]; +char shifted_ascii_table[256]; + +LPDIRECTINPUT g_lpdi; +LPDIRECTINPUTDEVICE g_lpdidKeybd; +extern HWND g_hWnd; + +typedef int KEYCODE; + +#define KEY_BUFFER_SIZE 16 + +ULONG g_rgbKeyQueue [KEY_BUFFER_SIZE]; +fix g_rgtimeQueue [KEY_BUFFER_SIZE]; +ULONG g_rgbPressedQueue [KEY_BUFFER_SIZE]; + +ULONG iQueueStart = 0; +ULONG iQueueEnd = 0; + +KEYCODE ShiftKeyCode (KEYCODE kcKey) +{ + KEYCODE kcShifted; + + if (keyd_pressed [kcKey]) + { + kcShifted = kcKey; + + // the key is down + if (keyd_pressed [KEY_LSHIFT] || keyd_pressed [KEY_RSHIFT]) + { + kcShifted |= KEY_SHIFTED; + } + if (keyd_pressed [KEY_LCTRL] || keyd_pressed [KEY_RCTRL]) + { + kcShifted |= KEY_CTRLED; + } + if (keyd_pressed [KEY_LALT] || keyd_pressed [KEY_RALT]) + { + kcShifted |= KEY_ALTED; + } + } + else + { + // the key is UP! + kcShifted = 0; + } + return kcShifted; +} + +BOOL SpaceInBuffer () +{ + if (iQueueStart == 0) + { + return iQueueEnd != KEY_BUFFER_SIZE - 1; + } + else + { + return iQueueEnd != iQueueStart - 1; + } +} + +void FlushQueue (void) +{ + iQueueStart = iQueueEnd = 0; +} + +void PushKey (ULONG kcKey, fix timeDown) +{ + if (SpaceInBuffer ()) + { + g_rgbKeyQueue [iQueueEnd] = ShiftKeyCode(kcKey); + g_rgtimeQueue [iQueueEnd] = timeDown; + + if (iQueueEnd ++ == KEY_BUFFER_SIZE) + { + iQueueEnd = 0; + } + } +} + +BOOL PopKey (KEYCODE *piKey, fix *ptimeDown) +{ + if (iQueueEnd != iQueueStart) + { + // there are items in the queue + + if (piKey != NULL) + { + *piKey = g_rgbKeyQueue [iQueueStart]; + } + if (ptimeDown != NULL) + { + *ptimeDown = g_rgbPressedQueue [iQueueStart]; + } + + if (iQueueStart ++ == KEY_BUFFER_SIZE) + { + iQueueStart = 0; + } + + return TRUE; + } + else + { + return FALSE; + } +} + +static BOOL EnsureInit (void) +{ + if (g_lpdidKeybd == NULL) + { + key_init (); + } + + return g_lpdidKeybd != NULL; +} + +void key_close(void); + +void key_init() +{ + HRESULT hr; + // my kingdom, my kingdom for C++... + if (SUCCEEDED (hr = DirectInputCreate (GetModuleHandle (NULL), DIRECTINPUT_VERSION, &g_lpdi, NULL))) + { + if (SUCCEEDED (hr = IDirectInput_CreateDevice (g_lpdi, (void *)&GUID_SysKeyboard, &g_lpdidKeybd, NULL))) + { + DIPROPDWORD dipdw; + + dipdw.diph.dwSize = sizeof (DIPROPDWORD); + dipdw.diph.dwHeaderSize = sizeof (DIPROPHEADER); + dipdw.diph.dwObj = 0; + dipdw.diph.dwHow = DIPH_DEVICE; + dipdw.dwData = 40; + + if (SUCCEEDED (hr = IDirectInputDevice_SetDataFormat (g_lpdidKeybd, &c_dfDIKeyboard)) && + SUCCEEDED (hr = IDirectInputDevice_SetCooperativeLevel (g_lpdidKeybd, g_hWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND)) && + SUCCEEDED (hr = IDirectInputDevice_SetProperty (g_lpdidKeybd, DIPROP_BUFFERSIZE, &dipdw.diph)) && + SUCCEEDED (hr = IDirectInputDevice_Acquire (g_lpdidKeybd))) + { + // fine + WMKey_Handler_Ready = 1; + + // Clear the keyboard array + key_flush(); + + atexit(key_close); + } + else + { + IDirectInputDevice_Release (g_lpdidKeybd); + g_lpdidKeybd = NULL; + } + } + } +} + +void key_close(void) +{ + WMKey_Handler_Ready = 0; + if (g_lpdidKeybd != NULL) + { + IDirectInputDevice_Unacquire (g_lpdidKeybd); + IDirectInputDevice_Release (g_lpdidKeybd); + g_lpdidKeybd = NULL; + } + if (g_lpdi != NULL) + { + IDirectInput_Release (g_lpdi); + g_lpdi = NULL; + } +} + +HRESULT ReadKey (DIDEVICEOBJECTDATA *pdidod) +{ + ULONG cElements = 1; + HRESULT hr; + if (g_lpdidKeybd == NULL) + return E_FAIL; + hr = IDirectInputDevice_Acquire (g_lpdidKeybd); + if (SUCCEEDED (hr)) + { + hr = IDirectInputDevice_GetDeviceData ( + g_lpdidKeybd, + sizeof (*pdidod), + pdidod, + (int *) &cElements, + 0); + if (SUCCEEDED (hr) && cElements != 1) + hr = E_FAIL; + } + + return hr; +} + +void UpdateState (DIDEVICEOBJECTDATA *pdidod) +{ + KEYCODE kcKey = pdidod->dwOfs; + + fix timeNow = timer_get_fixed_seconds (); + + if (pdidod->dwData & 0x80) + { + keyd_pressed [kcKey] = 1; + keyd_last_pressed = kcKey; + g_rgtimeDown [kcKey] = keyd_time_when_last_pressed = timeNow; + g_rgcDowns [kcKey] ++; + PushKey (kcKey, keyd_time_when_last_pressed); + } + else + { + keyd_pressed [kcKey] = 0; + keyd_last_released = kcKey; + g_rgcUps [kcKey] ++; + g_rgtimeElapsed [kcKey] = timeNow - g_rgtimeDown [kcKey]; + } +} + +void keyboard_handler() +{ +// static int peekmsgcount = 0; + DIDEVICEOBJECTDATA didod; + while (SUCCEEDED (ReadKey (&didod))) + { + UpdateState (&didod); + + //added 02/20/99 by adb to prevent message overflow + //(this should probably go somewhere else...) +// if (++peekmsgcount == 64) // 64 = wild guess... +// { +// peekmsgcount = 0; +// } + //end additions + } + PumpMessages(); +} + + + +void key_flush() +{ + if (EnsureInit ()) + { + ULONG cElements = INFINITE; + ULONG kcKey; +// HRESULT hr = + IDirectInputDevice_GetDeviceData ( + g_lpdidKeybd, + sizeof (DIDEVICEOBJECTDATA), + NULL, + (int *) &cElements, + 0); + + for (kcKey = 0; kcKey < 256; kcKey ++) + { + g_rgtimeElapsed [kcKey] = 0; + g_rgcDowns [kcKey] = 0; + g_rgcUps [kcKey] = 0; + keyd_pressed [kcKey] = 0; + } + + FlushQueue (); + } +} + +int key_getch() +{ + KEYCODE kcKey; + keyboard_handler(); + while (!PopKey (&kcKey, NULL)) + { + keyboard_handler (); + } + + return kcKey; +} + +KEYCODE key_inkey_time(fix * pTime) +{ + KEYCODE kcKey = 0; + + keyboard_handler (); + + PopKey (&kcKey, pTime); + + return kcKey; +} + +KEYCODE key_inkey () +{ + return key_inkey_time (NULL); +} + +KEYCODE key_peekkey () +{ + keyboard_handler(); + return 0; +} + +int key_checkch() +{ + return 1; // FIXME +} + +unsigned char key_to_ascii(KEYCODE kcKey ) +{ + BOOL bShifted = kcKey & KEY_SHIFTED; + unsigned char ch; + + kcKey &= ~KEY_SHIFTED; + + if (kcKey <= 127) + { + if (bShifted) + { + ch = shifted_ascii_table [kcKey & 0xff]; + } + else + { + ch = ascii_table [kcKey & 0xff]; + } + } + else + { + ch = 255; + } + + return ch; +} + +// Returns the number of seconds this key has been down since last call. +fix key_down_time(KEYCODE kcKey) +{ + ULONG timeElapsed; + keyboard_handler(); + if ((kcKey<0) || (kcKey>127)) return 0; + + if (keyd_pressed [kcKey]) + { + fix timeNow = timer_get_fixed_seconds (); + timeElapsed = timeNow - g_rgtimeDown [kcKey]; + g_rgtimeDown [kcKey] = timeNow; + } + else + { + timeElapsed = g_rgtimeElapsed [kcKey]; + g_rgtimeElapsed [kcKey] = 0; + } + + return timeElapsed;; +} + + +unsigned int key_down_count(KEYCODE kcKey) +{ + int n; + keyboard_handler(); + if ((kcKey < 0) || (kcKey > 127)) + { + n = 0; + } + else + { + n = g_rgcDowns [kcKey]; + g_rgcDowns [kcKey] = 0; + } + + return n; +} + +unsigned int key_up_count(KEYCODE kcKey) +{ + int n; + + keyboard_handler(); + if ((kcKey < 0) || (kcKey > 127)) + { + n = 0; + } + else + { + n = g_rgcUps [kcKey]; + g_rgcUps [kcKey] = 0; + } + + return n; +} + + +#define ___ ((char) 255) +char ascii_table[256] = +{ +___, ___, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', ___, ___, +'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', ___, ___, 'a', 's', +'d', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`', ___,'\\', 'z', 'x', 'c', 'v', +'b', 'n', 'm', ',', '.', '/', ___, '*', ___, ___, ___, ___, ___, ___, ___, ___, +___, ___, ___, ___, ___, ___, ___, '7', '8', '9', '-', '4', '5', '6', '+', '1', +'2', '3', '0', '.', ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, +___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, +___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, +}; + +char shifted_ascii_table[256] = +{ +___, ___, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', ___, ___, +'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', ___, ___, 'A', 'S', +'D', 'F', 'G', 'H', 'J', 'K', 'L', ':','\"', '~', ___, '|', 'Z', 'X', 'C', 'V', +'B', 'N', 'M', '<', '>', '?', ___, '*', ___, ___, ___, ___, ___, ___, ___, ___, +___, ___, ___, ___, ___, ___, ___, '&', '*', '(', '_', '$', '%', '^', '=', '!', +'@', '#', ')', '>', ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, +___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, +___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, +}; +#undef ___ + +char * key_text[256] = { +"","ESC","1","2","3","4","5","6","7","8","9","0","-", +"=","BSPC","TAB","Q","W","E","R","T","Y","U","I","O", +"P","[","]","ƒ","LCTRL","A","S","D","F", +"G","H","J","K","L",";","'","`", +"LSHFT","\\","Z","X","C","V","B","N","M",",", +".","/","RSHFT","PAD*","LALT","SPC", +"CPSLK","F1","F2","F3","F4","F5","F6","F7","F8","F9", +"F10","NMLCK","SCLK","PAD7","PAD8","PAD9","PAD-", +"PAD4","PAD5","PAD6","PAD+","PAD1","PAD2","PAD3","PAD0", +"PAD.","","","","F11","F12","","","","","","","","","", +"","","","","","","","","","","","","","","","","","","","", +"","","","","","","","","","","","","","","","","","","","", +"","","","","","","","","","","","","","","","","","", +"PADƒ","RCTRL","","","","","","","","","","","","","", +"","","","","","","","","","","PAD/","","","RALT","", +"","","","","","","","","","","","","","HOME","‚","PGUP", +"","","","","","END","€","PGDN","INS", +"DEL","","","","","","","","","","","","","","","","","", +"","","","","","","","","","","","","","","","","","","","", +"","","","","","","" }; +#if 0 // what was this? -- adb +"","","","HOME","UP","PGUP","","LEFT","","RGHT","","END","DOWN","PGDN","INS","DEL", +"","","","","","","?","","", +"","","","","","","","","","","","","","","","","","", +"","","","","","","","","","","","","","","","","","","","", +"","","","","","","" }; +#endif diff --git a/arch/win32/mono.c b/arch/win32/mono.c new file mode 100644 index 00000000..8b35eddf --- /dev/null +++ b/arch/win32/mono.c @@ -0,0 +1,13 @@ +#include +#include +void mopen() {} +void mclose() {} +void _mprintf(short n, char * format, ...) { +#ifndef NMONO + va_list args; + va_start(args, format ); + vprintf(format, args); + va_end(args); +#endif +} + diff --git a/arch/win32/mouse.c b/arch/win32/mouse.c new file mode 100644 index 00000000..de216aec --- /dev/null +++ b/arch/win32/mouse.c @@ -0,0 +1,620 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* +* $Source: /cvs/cvsroot/d2x/arch/win32/mouse.c,v $ +* $Revision: 1.1.1.1 $ +* $Author: bradleyb $ +* $Date: 2001-01-19 03:30:15 $ +* +* Functions to access Mouse and Cyberman... +* +* $Log: not supported by cvs2svn $ +* Revision 1.5 1999/10/15 05:27:48 donut +* include to fix undef'd err +* +* Revision 1.4 1999/10/14 03:08:10 donut +* changed exit to mprintf on unknown mouse event +* +* Revision 1.3 1999/10/09 05:03:57 donut +* fixed win32 exit on mouse move +* +* Revision 1.2 1999/09/05 04:19:19 sekmu +* made mouse exclusive for windows +* +* Revision 1.1.1.1 1999/06/14 22:00:37 donut +* Import of d1x 1.37 source. +* +* Revision 1.8 1996/02/21 13:57:36 allender +* cursor device manager stuff added here so as not to +* rely on InterfaceLib anymore +* +* Revision 1.7 1995/10/17 15:42:21 allender +* new mouse function to determine single button press +* +* Revision 1.6 1995/10/03 11:27:31 allender +* fixed up hotspot problems with the mouse on multiple monitors +* +* Revision 1.5 1995/07/13 11:27:08 allender +* trap button checks at MAX_MOUSE_BUTTONS +* +* Revision 1.4 1995/06/25 21:56:53 allender +* added events include +* +* Revision 1.3 1995/05/11 17:06:38 allender +* fixed up mouse routines +* +* Revision 1.2 1995/05/11 13:05:53 allender +* of mouse handler code +* +* Revision 1.1 1995/05/05 09:54:45 allender +* Initial revision +* +* Revision 1.9 1995/01/14 19:19:52 john +* Fixed signed short error cmp with -1 that caused mouse +* to break under Watcom 10.0 +* +* Revision 1.8 1994/12/27 12:38:23 john +* Made mouse use temporary dos buffer instead of +* +* allocating its own. +* +* +* Revision 1.7 1994/12/05 23:54:53 john +* Fixed bug with mouse_get_delta only returning positive numbers.. +* +* Revision 1.6 1994/11/18 23:18:18 john +* Changed some shorts to ints. +* +* Revision 1.5 1994/09/13 12:34:02 john +* Added functions to get down count and state. +* +* Revision 1.4 1994/08/29 20:52:19 john +* Added better cyberman support; also, joystick calibration +* value return funcctiionn, +* +* Revision 1.3 1994/08/24 18:54:32 john +* *** empty log message *** +* +* Revision 1.2 1994/08/24 18:53:46 john +* Made Cyberman read like normal mouse; added dpmi module; moved +* mouse from assembly to c. Made mouse buttons return time_down. +* +* Revision 1.1 1994/08/24 13:56:37 john +* Initial revision +* +* +*/ + +#define WIN32_LEAN_AND_MEAN +#include + + +#include +#include +#include + +#include "error.h" +#include "fix.h" +#include "mouse.h" +#include "mono.h" +#include "timer.h" + +// These are to kludge up a bit my slightly broken GCC directx port. +#ifndef E_FAIL +#define E_FAIL (HRESULT)0x80004005L +#endif +#ifndef SUCCEEDED +#define SUCCEEDED(a) ((HRESULT)(a) >= 0) +#endif +#ifndef S_OK +#define S_OK 0 +#define S_FALSE 1 +#endif +#ifndef SEVERITY_SUCCESS +#define SEVERITY_SUCCESS 0 +#define SEVERITY_ERROR 1 +#endif +#ifndef FACILITY_WIN32 +#define FACILITY_WIN32 7 +#endif +#ifndef FIELD_OFFSET +#define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field)) +#endif + +#define ME_CURSOR_MOVED (1<<0) +#define ME_LB_P (1<<1) +#define ME_LB_R (1<<2) +#define ME_RB_P (1<<3) +#define ME_RB_R (1<<4) +#define ME_MB_P (1<<5) +#define ME_MB_R (1<<6) +#define ME_OB_P (1<<7) +#define ME_OB_R (1<<8) +#define ME_X_C (1<<9) +#define ME_Y_C (1<<10) +#define ME_Z_C (1<<11) +#define ME_P_C (1<<12) +#define ME_B_C (1<<13) +#define ME_H_C (1<<14) +#define ME_O_C (1<<15) + +typedef struct event_info { + short x; + short y; + short z; + short pitch; + short bank; + short heading; + ushort button_status; + ushort device_dependant; +} event_info; + +typedef struct mouse_info { + fix ctime; + ubyte cyberman; + int num_buttons; + ubyte pressed[MOUSE_MAX_BUTTONS]; + fix time_went_down[MOUSE_MAX_BUTTONS]; + fix time_held_down[MOUSE_MAX_BUTTONS]; + uint num_downs[MOUSE_MAX_BUTTONS]; + uint num_ups[MOUSE_MAX_BUTTONS]; + // ubyte went_down; /* Not in PC version, not needed with 'num_downs' etc */ + event_info *x_info; + ushort button_status; +} mouse_info; + +typedef struct cyberman_info { + ubyte device_type; + ubyte major_version; + ubyte minor_version; + ubyte x_descriptor; + ubyte y_descriptor; + ubyte z_descriptor; + ubyte pitch_descriptor; + ubyte roll_descriptor; + ubyte yaw_descriptor; + ubyte reserved; +} cyberman_info; + +static mouse_info Mouse; + +static int Mouse_installed = 0; + +int WMMouse_Handler_Ready = 0; +int mouse_wparam, mouse_lparam, mouse_msg; + + +//GGI data: +//extern ggi_visual_t visual; +//extern ggi_directbuffer_t dbuf; // GGI direct acces to screen memory +//extern ggi_pixellinearbuffer *plb; + +//Mouse globals +static double mouse_x, mouse_y; +static double mouse_saved_x, mouse_saved_y; //used when hiding/unhiding to reset the real (displayed) postion +double mouse_accel=1.0; + +void DrawMouse(void); +void EraseMouse(void); +void MoveMouse(/*int button,*/ int x, int y); + +#define WIN_WIDTH 640 +#define WIN_HEIGHT 480 +#define SCR_WIDTH 640 +#define SCR_HEIGHT 480 + +LPDIRECTINPUT g_lpdi; +LPDIRECTINPUTDEVICE g_lpdidMouse; +extern HWND g_hWnd; + + +HRESULT ReadMouse (DIDEVICEOBJECTDATA *pdidod) +{ + ULONG cElements = 1; + HRESULT hr; + + if (g_lpdidMouse == NULL) + return E_FAIL; + + hr = IDirectInputDevice_GetDeviceData ( + g_lpdidMouse, + sizeof (*pdidod), + pdidod, + (int *) &cElements, + 0); + + if (hr == DIERR_INPUTLOST) + { + hr = IDirectInputDevice_Acquire (g_lpdidMouse); + if (SUCCEEDED (hr)) + { + hr = IDirectInputDevice_GetDeviceData ( + g_lpdidMouse, + sizeof (*pdidod), + pdidod, + (int *) &cElements, + 0); + } + } + + if (SUCCEEDED (hr) && cElements != 1) + hr = E_FAIL; + + return hr; +} + + +void UpdateMouseState (DIDEVICEOBJECTDATA *pdidod) +{ +// fix timeNow = timer_get_fixed_seconds (); + + ULONG iEvt = pdidod->dwOfs; + switch (iEvt) + { + case DIMOFS_BUTTON0: + case DIMOFS_BUTTON1: + case DIMOFS_BUTTON2: + case DIMOFS_BUTTON3: + { + BOOL bPressed = pdidod->dwData & 0x80; + ULONG iButton = (iEvt - DIMOFS_BUTTON0) + MB_LEFT; + if (bPressed) + { + if (!Mouse.pressed [iButton]) + { + Mouse.pressed [iButton] = 1; + Mouse.time_went_down [iButton] = Mouse.ctime; + Mouse.num_downs [iButton]++; + // Mouse.went_down = 1; + } + Mouse.num_downs [iButton] ++; + } + else + { + if (Mouse.pressed [iButton]) + { + Mouse.pressed [iButton] = 0; + Mouse.time_held_down [iButton] += Mouse.ctime - Mouse.time_went_down [iButton]; + Mouse.num_ups [iButton]++; + // Mouse.went_down = 0; + } + } + break; + } + case DIMOFS_X: + mouse_x += (double) ((LONG) pdidod->dwData); + break; + + case DIMOFS_Y: + mouse_y += (double) ((LONG) pdidod->dwData); + break; + case DIMOFS_Z: + break;//hm, handle this? + default: + mprintf((0,"unknown mouse event %i\n",iEvt)); +// exit (iEvt);//not happy. + break; + } +} + +void mouse_handler() +{ + DIDEVICEOBJECTDATA didod; + + Mouse.ctime = timer_get_fixed_seconds(); + + while (SUCCEEDED (ReadMouse (&didod))) + { + UpdateMouseState (&didod); + } +} + +void mouse_flush() +{ + int i; + fix CurTime; + + if (!Mouse_installed) + return; + + mouse_handler(); + // _disable(); + CurTime = timer_get_fixed_seconds(); + for (i = 0; i < MOUSE_MAX_BUTTONS; i++) { + Mouse.pressed[i] = 0; + Mouse.time_went_down[i] = CurTime; + Mouse.time_held_down[i] = 0; + Mouse.num_downs[i] = 0; + Mouse.num_ups[i] = 0; + } + // Mouse.went_down = 0; /* mac only */ + // _enable(); + + { + ULONG cElements = INFINITE; +// HRESULT hr = + IDirectInputDevice_GetDeviceData ( + g_lpdidMouse, + sizeof (DIDEVICEOBJECTDATA), + NULL, + (int *) &cElements, + 0); + } +} + + +void mouse_close(void) +{ + // if (Mouse_installed) // DPH: Unnecessary... + WMMouse_Handler_Ready=Mouse_installed = 0; + + if (g_lpdidMouse != NULL) + { + IDirectInputDevice_Unacquire (g_lpdidMouse); + IDirectInputDevice_Release (g_lpdidMouse); + g_lpdidMouse = NULL; + } + if (g_lpdi != NULL) + { + IDirectInput_Release (g_lpdi); + g_lpdi = NULL; + } +} + + + +int mouse_init(int unused) +{ + if (Mouse_installed) + return Mouse.num_buttons; + + { + HRESULT hr; + + if (SUCCEEDED (hr = DirectInputCreate (GetModuleHandle (NULL), DIRECTINPUT_VERSION, &g_lpdi, NULL))) + { + if (SUCCEEDED (hr = IDirectInput_CreateDevice (g_lpdi,(void *) &GUID_SysMouse, &g_lpdidMouse, NULL))) + { + DIPROPDWORD dipdw; + dipdw.diph.dwSize = sizeof (DIPROPDWORD); + dipdw.diph.dwHeaderSize = sizeof (DIPROPHEADER); + dipdw.diph.dwObj = 0; + dipdw.diph.dwHow = DIPH_DEVICE; + dipdw.dwData = 40; + + if (SUCCEEDED (hr = IDirectInputDevice_SetDataFormat (g_lpdidMouse, &c_dfDIMouse)) && + //changed on 9/4/99 by Victor Rachels NONEX -> Exclusive + SUCCEEDED (hr = IDirectInputDevice_SetCooperativeLevel (g_lpdidMouse, g_hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND)) && + //end this section edit -VR + SUCCEEDED (hr = IDirectInputDevice_SetProperty (g_lpdidMouse, DIPROP_BUFFERSIZE, &dipdw.diph)) && + SUCCEEDED (hr = IDirectInputDevice_Acquire (g_lpdidMouse))) + { + } + else + { + IDirectInputDevice_Release (g_lpdidMouse); + g_lpdidMouse = NULL; + return 0; + } + } + } + } + Mouse.num_buttons = 3; + + WMMouse_Handler_Ready=Mouse_installed = 1; + atexit(mouse_close); + mouse_flush(); + // mouse_set_center(); + + return Mouse.num_buttons; +} + +//WHS: added this +void mouse_center() { + mouse_x=mouse_saved_x=WIN_WIDTH/2; + mouse_y=mouse_saved_y=WIN_HEIGHT/2; +} + +void mouse_get_pos( int *x, int *y) +{ + mouse_handler(); //temp + + *x=(int) mouse_x; + *y=(int) mouse_y; +} + +void mouse_get_delta( int *dx, int *dy ) +{ + if (!Mouse_installed) { + *dx = *dy = 0; + return; + } + mouse_handler(); //temp + + *dx = (int) mouse_x - WIN_WIDTH/2; + *dy = (int) mouse_y - WIN_HEIGHT/2; + + //Now reset the mouse position to the center of the screen + mouse_x = (double) WIN_WIDTH/2; + mouse_y = (double) WIN_HEIGHT/2; +} + +void mouse_get_delta_no_reset( int *dx, int *dy ) +{ + if (!Mouse_installed) { + *dx = *dy = 0; + return; + } + mouse_handler(); //temp + + *dx = (int) mouse_x - WIN_WIDTH/2; + *dy = (int) mouse_y - WIN_HEIGHT/2; +} + +int mouse_get_btns() +{ + int i; + uint flag=1; + int status = 0; + + if (!Mouse_installed) + return 0; + + mouse_handler(); //temp + + for (i = 0; i < MOUSE_MAX_BUTTONS; i++) { + if (Mouse.pressed[i]) + status |= flag; + flag <<= 1; + } + return status; +} + +/* This should be replaced with mouse_button_down_count(int button) */ +int mouse_went_down(int button) +{ + int count; + + if (!Mouse_installed) + return 0; + + mouse_handler(); //temp + + if ((button < 0) || (button >= MOUSE_MAX_BUTTONS)) + return 0; + + // _disable(); + count = Mouse.num_downs[button]; + Mouse.num_downs[button] = 0; + + // _enable(); + return count; +} + +// Returns how many times this button has went down since last call. +int mouse_button_down_count(int button) +{ + int count; + + if (!Mouse_installed) + return 0; + + mouse_handler(); //temp + + if ((button < 0) || (button >= MOUSE_MAX_BUTTONS)) + return 0; + + // _disable(); + count = Mouse.num_downs[button]; + Mouse.num_downs[button] = 0; + // _enable(); + return count; +} + +// Returns 1 if this button is currently down +int mouse_button_state(int button) +{ + int state; + + if (!Mouse_installed) + return 0; + + mouse_handler(); //temp + + if ((button < 0) || (button >= MOUSE_MAX_BUTTONS)) + return 0; + + // _disable(); + state = Mouse.pressed[button]; + // _enable(); + return state; +} + +// Returns how long this button has been down since last call. +fix mouse_button_down_time(int button) +{ + fix time_down, time; + + if (!Mouse_installed) + return 0; + + mouse_handler(); //temp + + if ((button < 0) || (button >= MOUSE_MAX_BUTTONS)) + return 0; + + // _disable(); + if (!Mouse.pressed[button]) { + time_down = Mouse.time_held_down[button]; + Mouse.time_held_down[button] = 0; + } else { + time = timer_get_fixed_seconds(); + time_down = time - Mouse.time_held_down[button]; + Mouse.time_held_down[button] = 0; + } + // _enable(); + + return time_down; +} + +void mouse_get_cyberman_pos( int *x, int *y ) +{ +} + + + +//WHS: I made this :) +void hide_cursor() +{ + ShowCursor(FALSE); +} + +void show_cursor() +{ + ShowCursor(TRUE); +} + + +/* New mouse pointer stuff for GGI/DGA */ +//#include "cursor.h" /* cursor and mask */ + +typedef struct Sprite { + ushort width; + ushort height; + byte *pixels; + byte *mask; +} Sprite; + +//Sprite mouse_sprite = { cursor_width, cursor_height, cursor_bits, cursor_mask_bits}; + +//byte *behind_mouse; +//byte behind_mouse[cursor_width*cursor_height]; + + +void DrawMouse(void) +{ +} + + +void EraseMouse(void) +{ +} + +//Should add a mode, relative, absolute +#define MOVE_REL 0 +#define MOVE_ABS 1 +//void MoveMouse(int mode, int x, int y) { + +void MoveMouse(int x, int y) +{ +} diff --git a/arch/win32/palw32.c b/arch/win32/palw32.c new file mode 100644 index 00000000..319b5f1e --- /dev/null +++ b/arch/win32/palw32.c @@ -0,0 +1,225 @@ +#include "gr.h" +#include "grdef.h" +#include "palette.h" + +#include + + +//added on 7/11/99 by adb to fix palette problem +#undef min +static __inline int min(int x, int y) { return x < y ? x : y; } +//end additions - adb + +static int last_r=0, last_g=0, last_b=0; + +extern void Win32_DoSetPalette(PALETTEENTRY *rgpe); +extern void Win32_DoGetPalette(PALETTEENTRY *rgpe); +extern void Win32_MakePalVisible(void); + +void gr_palette_step_up( int r, int g, int b ) +{ + int i; + ubyte *p; + int temp; + + PALETTEENTRY pe[256]; + + if (gr_palette_faded_out) return; + + if ( (r==last_r) && (g==last_g) && (b==last_b) ) return; + + last_r = r; + last_g = g; + last_b = b; + + p=gr_palette; + for (i=0; i<256; i++) + { + temp = (int)(*p++) + r; + if (temp<0) temp=0; + else if (temp>63) temp=63; + pe[i].peRed = min(temp + gr_palette_gamma, 63) * 4; + temp = (int)(*p++) + g; + if (temp<0) temp=0; + else if (temp>63) temp=63; + pe[i].peGreen = min(temp + gr_palette_gamma, 63) * 4 ; + temp = (int)(*p++) + b; + if (temp<0) temp=0; + else if (temp>63) temp=63; + pe[i].peBlue = min(temp + gr_palette_gamma, 63) * 4; + pe[i].peFlags = 0; + } + Win32_DoSetPalette (pe); +} + +void gr_palette_clear() +{ + int i; + + PALETTEENTRY pe[256]; + for (i=0;i<256;i++) + { + pe[i].peRed=pe[i].peGreen=pe[i].peBlue=pe[i].peFlags=0; + } + + Win32_DoSetPalette (pe); + + gr_palette_faded_out = 1; +} + +void gr_palette_load( ubyte *pal ) +{ + int i, j; + PALETTEENTRY pe[256]; + + for (i=0; i<768; i++ ) { + //gr_current_pal[i] = pal[i] + gr_palette_gamma; + //if (gr_current_pal[i] > 63) gr_current_pal[i] = 63; + gr_current_pal[i] = pal[i]; + } + for (i=0,j=0;j<256;j++) + { + pe[j].peRed = min(gr_current_pal[i++] + gr_palette_gamma, 63) * 4; + pe[j].peGreen= min(gr_current_pal[i++] + gr_palette_gamma, 63) * 4; + pe[j].peBlue = min(gr_current_pal[i++] + gr_palette_gamma, 63) * 4; + pe[j].peFlags = 0; + } + Win32_DoSetPalette (pe); + + gr_palette_faded_out = 0; + init_computed_colors(); +} + +int gr_palette_fade_out(ubyte *pal, int nsteps, int allow_keys ) +{ + int i,j,k; + fix fade_palette[768]; + fix fade_palette_delta[768]; + PALETTEENTRY pe[256]; + + allow_keys = allow_keys; + + if (gr_palette_faded_out) return 0; + + if (pal==NULL) pal=gr_current_pal; + + for (i=0; i<768; i++ ) + { + gr_current_pal[i] = pal[i]; + fade_palette[i] = i2f(pal[i]); + fade_palette_delta[i] = fade_palette[i] / nsteps; + } + + for (j=0; j i2f(pal[i] + gr_palette_gamma) ) + fade_palette[i] = i2f(pal[i] + gr_palette_gamma); + + pe[k].peRed = min(f2i(fade_palette[i]), 63) * 4; + i++; + fade_palette[i] -= fade_palette_delta[i]; + if (fade_palette[i] < 0 ) + fade_palette[i] = 0; + if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma) ) + fade_palette[i] = i2f(pal[i] + gr_palette_gamma); + + pe[k].peGreen = min(f2i(fade_palette[i]), 63) * 4; + i++; + fade_palette[i] -= fade_palette_delta[i]; + if (fade_palette[i] < 0 ) + fade_palette[i] = 0; + if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma) ) + fade_palette[i] = i2f(pal[i] + gr_palette_gamma); + + pe[k].peBlue = min(f2i(fade_palette[i]), 63) * 4; + pe[k].peFlags = 0; + i++; + } + + Win32_DoSetPalette (pe); + Win32_MakePalVisible (); + } + + gr_palette_faded_out = 1; + return 0; +} + +int gr_palette_fade_in(ubyte *pal, int nsteps, int allow_keys) +{ + int i,j, k; +// ubyte c; + fix fade_palette[768]; + fix fade_palette_delta[768]; + + PALETTEENTRY pe[256]; + + allow_keys = allow_keys; + + if (!gr_palette_faded_out) return 0; + + if (pal==NULL) pal=gr_current_pal; + + + for (i=0; i<768; i++ ) { + gr_current_pal[i] = pal[i]; + fade_palette[i] = 0; + fade_palette_delta[i] = i2f(pal[i]) / nsteps; + } + + for (j=0; j i2f(pal[i] + gr_palette_gamma) ) + fade_palette[i] = i2f(pal[i] + gr_palette_gamma); + + pe[k].peRed = min(f2i(fade_palette[i]), 63) * 4; + i++; + fade_palette[i] += fade_palette_delta[i]; + if (fade_palette[i] < 0 ) + fade_palette[i] = 0; + if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma) ) + fade_palette[i] = i2f(pal[i] + gr_palette_gamma); + + pe[k].peGreen = min(f2i(fade_palette[i]), 63) * 4; + i++; + fade_palette[i] += fade_palette_delta[i]; + if (fade_palette[i] < 0 ) + fade_palette[i] = 0; + if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma) ) + fade_palette[i] = i2f(pal[i] + gr_palette_gamma); + + pe[k].peBlue = min(f2i(fade_palette[i]), 63) * 4; + pe[k].peFlags = 0; + i++; + } + + Win32_DoSetPalette (pe); + //added on 7/11/99 by adb to allow fade in on non-palette displays + Win32_MakePalVisible (); + //end additions - adb + } + + gr_palette_faded_out = 0; + return 0; +} + +void gr_palette_read(ubyte * pal) +{ + int i; +// char c; + PALETTEENTRY rgpe [256]; + Win32_DoGetPalette (rgpe); + for (i = 0; i < 256; i++) + { + *pal++ = (rgpe[i].peRed) / 4; + *pal++ = (rgpe[i].peGreen) / 4; + *pal++ = (rgpe[i].peBlue) / 4; + } +} diff --git a/arch/win32/pch.cpp b/arch/win32/pch.cpp new file mode 100644 index 00000000..22810d40 --- /dev/null +++ b/arch/win32/pch.cpp @@ -0,0 +1,4 @@ +#include "pch.h" + +#include +CComModule _Module; diff --git a/arch/win32/scene.cpp b/arch/win32/scene.cpp new file mode 100644 index 00000000..8070f2e4 --- /dev/null +++ b/arch/win32/scene.cpp @@ -0,0 +1,810 @@ +//----------------------------------------------------------------------------- +// File: VBuffer.cpp +// +// Desc: Example code showing how to use DirectX 6 vertex buffers. +// +// Note: This code uses the D3D Framework helper library. +// +// +// Copyright (c) 1997-1998 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- + +#include "pch.h" +#include "scene.h" +#include + +#include "D3DTextr.h" +#include "D3DUtil.h" +#include "D3DMath.h" +#include "D3DFrame.h" + +#include "texture.h" + +extern CD3DFramework* g_pFramework; +extern BOOL g_bWindowed; + +extern "C" { +#include "d3dhelp.h" +} + +//----------------------------------------------------------------------------- +// Declare the application globals for use in WinMain.cpp +//----------------------------------------------------------------------------- +void Win32_SetupColor(void); +BOOL g_TrueColor; +int g_RShift, g_GShift, g_BShift; +int g_RBits6, g_GBits6, g_BBits6; + +TCHAR* g_strAppTitle = TEXT( "Direct3D Descent" ); +BOOL g_bAppUseZBuffer = FALSE; +BOOL g_bAppUseBackBuffer = TRUE; + +LPDIRECT3DTEXTURE2 g_pd3dtLast; +BOOL g_bTransparentLast; + +std::stack g_stkWorlds; + +float g_fPSURed = 0.0f; +float g_fPSUGreen = 0.0f; +float g_fPSUBlue = 0.0f; + +D3DLVERTEX g_rgVerts [16]; + +CTextureSet g_setTextures; + +//----------------------------------------------------------------------------- +// Defines, constants, and global variables +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Function prototypes and global (or static) variables +//----------------------------------------------------------------------------- +HRESULT App_InitDeviceObjects( LPDIRECT3DDEVICE3, LPDIRECT3DVIEWPORT3 ); +VOID App_DeleteDeviceObjects( LPDIRECT3DDEVICE3, LPDIRECT3DVIEWPORT3 ); + + + + +//----------------------------------------------------------------------------- +// Name: App_OneTimeSceneInit() +// Desc: Called during initial app startup, this function performs all the +// permanent initialization. +//----------------------------------------------------------------------------- +HRESULT App_OneTimeSceneInit( HWND hWnd ) +{ + // Create some textures + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: App_InitDeviceObjects() +// Desc: Initialize scene objects. +//----------------------------------------------------------------------------- +HRESULT App_InitDeviceObjects( LPDIRECT3DDEVICE3 pd3dDevice, + LPDIRECT3DVIEWPORT3 pvViewport ) +{ + // Check parameters + if( NULL==pd3dDevice || NULL==pvViewport ) + return E_INVALIDARG; + + + D3DVIEWPORT2 vdData; + ZeroMemory( &vdData, sizeof(D3DVIEWPORT2) ); + vdData.dwSize = sizeof(vdData); + vdData.dwX = 0; + vdData.dwY = 0; + vdData.dwWidth = g_pFramework->m_dwRenderWidth; + vdData.dwHeight = 147 * g_pFramework->m_dwRenderHeight / 200; + vdData.dvMaxZ = 1.0f; + + vdData.dvClipX = -1.0f; + vdData.dvClipY = (FLOAT) g_pFramework->m_dwRenderHeight / (FLOAT) g_pFramework->m_dwRenderWidth; + vdData.dvClipWidth = 2.0f; + vdData.dvClipHeight = 2.0f * vdData.dvClipY; + vdData.dvMinZ = 0.0f; + vdData.dvMaxZ = 1.0f; + + // Set the parameters to the new viewport + if (FAILED (pvViewport->SetViewport2 (&vdData))) + { + DEBUG_MSG( TEXT("Error: Couldn't set the viewport data") ); + return D3DFWERR_NOVIEWPORT; + } + + + // Get a ptr to the ID3D object to create VB's, materials and/or lights. + // Note: the Release() call just serves to decrease the ref count. + LPDIRECT3D3 pD3D; + if( FAILED( pd3dDevice->GetDirect3D( &pD3D ) ) ) + return E_FAIL; + pD3D->Release(); + + // Get the device's caps bits + D3DDEVICEDESC ddHwDesc, ddSwDesc; + D3DUtil_InitDeviceDesc( ddHwDesc ); + D3DUtil_InitDeviceDesc( ddSwDesc ); + if( FAILED( pd3dDevice->GetCaps( &ddHwDesc, &ddSwDesc ) ) ) + return E_FAIL; + + D3DMATRIX matProj; + float fAspect = 1.0f; + D3DUtil_SetProjectionMatrix( matProj, g_PI/3, fAspect, 0.01f, 1000.0f ); + pd3dDevice->SetTransform( D3DTRANSFORMSTATE_PROJECTION, &matProj ); + + pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); + //pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTFN_LINEAR ); + //pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTFG_LINEAR ); + + pd3dDevice->SetRenderState (D3DRENDERSTATE_SPECULARENABLE, FALSE); + pd3dDevice->SetRenderState (D3DRENDERSTATE_DITHERENABLE, TRUE); + pd3dDevice->SetRenderState (D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE); + pd3dDevice->SetRenderState (D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID); + pd3dDevice->SetRenderState (D3DRENDERSTATE_ZENABLE, 0); + pd3dDevice->SetRenderState (D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); + pd3dDevice->SetRenderState (D3DRENDERSTATE_COLORKEYENABLE, FALSE); + + D3DMATRIX matID; + D3DUtil_SetIdentityMatrix (matID); + + while (!g_stkWorlds.empty ()) + g_stkWorlds.pop (); + + g_stkWorlds.push (matID); + pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matID ); + + g_setTextures.Initialize (); + + g_bTransparentLast = FALSE; + g_pd3dtLast = NULL; + + Win32_SetupColor(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: App_FinalCleanup() +// Desc: Called before the app exits, this function gives the app the chance +// to cleanup after itself. +//----------------------------------------------------------------------------- +HRESULT App_FinalCleanup( LPDIRECT3DDEVICE3 pd3dDevice, + LPDIRECT3DVIEWPORT3 pvViewport) +{ + App_DeleteDeviceObjects( pd3dDevice, pvViewport ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: App_DeleteDeviceObjects() +// Desc: Called when the app is exitting, or the device is being changed, +// this function deletes any device dependant objects. +//----------------------------------------------------------------------------- +VOID App_DeleteDeviceObjects( LPDIRECT3DDEVICE3 pd3dDevice, + LPDIRECT3DVIEWPORT3 pvViewport) +{ + D3DTextr_InvalidateAllTextures(); + + g_setTextures.Uninitialize (); + + Win32_InvalidatePages(); + + Win32_SetupColor(); +} + + + + +//---------------------------------------------------------------------------- +// Name: App_RestoreSurfaces +// Desc: Restores any previously lost surfaces. Must do this for all surfaces +// (including textures) that the app created. +//---------------------------------------------------------------------------- +HRESULT App_RestoreSurfaces() +{ + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: App_ConfirmDevice() +// Desc: Called during device intialization, this code checks the device +// for some minimum set of capabilities +//----------------------------------------------------------------------------- +HRESULT App_ConfirmDevice( DDCAPS* pddDriverCaps, + D3DDEVICEDESC* pd3dDeviceDesc ) +{ + // Don't allow 3d Devices that don't support textures(Matrox Millenium) + if (!pd3dDeviceDesc->dwMaxTextureWidth) + return DDERR_INVALIDOBJECT; + + return S_OK; + +} + + + + +#define byte __BOGUS1 +#define bool __BOGUS2 + +extern "C" +{ +#include "types.h" +#include "grdef.h" +#include "..\main\segment.h" +#include "..\main\segpoint.h" +#include "..\main\object.h" +#include "..\3d\globvars.h" +#include "3d.h" +#include "palette.h" +} + +#undef __BOGUS1 +#undef __BOGUS2 + +LPDIRECT3DDEVICE3 g_pd3dDevice; + +HRESULT App_StartFrame( LPDIRECT3DDEVICE3 pd3dDevice, LPDIRECT3DVIEWPORT3 pvViewport, D3DRECT* prcViewRect ) +{ + g_pd3dDevice = pd3dDevice; + + HRESULT hResult; + + hResult = pvViewport->Clear2 (1UL, prcViewRect, D3DCLEAR_TARGET, 0, 1.0f, 0); + + // Begin the scene + hResult = pd3dDevice->BeginScene(); + + ASSERT (g_stkWorlds.size () == 1); + + return hResult; +} + +HRESULT App_EndFrame (void) +{ + HRESULT hResult; + + hResult = g_pd3dDevice->EndScene (); + + ASSERT (g_stkWorlds.size () == 1); + + return hResult; +} + +extern "C" RGBQUAD w32lastrgb[256]; + +extern "C" void Win32_DoSetPalette (PALETTEENTRY *rgpe) +{ + g_setTextures.SetPaletteEntries (rgpe); + for (int i = 0; i < 256; i++) { + w32lastrgb[i].rgbBlue = rgpe[i].peBlue; + w32lastrgb[i].rgbGreen = rgpe[i].peGreen; + w32lastrgb[i].rgbRed = rgpe[i].peRed; + } +} + +extern "C" void Win32_DoGetPalette (PALETTEENTRY *rgpe) +{ + g_setTextures.GetPaletteEntries (rgpe); +} + +extern "C" int Win32_PaletteStepUp (int r, int g, int b) +{ + if (g_setTextures.HasPalette ()) + { + g_fPSURed = g_fPSUGreen = g_fPSUBlue = 0.0f; + return FALSE; + } + else + { + g_fPSURed = (float) r / 32.0f; + g_fPSUGreen = (float) g / 32.0f; + g_fPSUBlue = (float) b / 32.0f; + return TRUE; + } +} + +D3DVECTOR g_vecRight, g_vecUp; + +extern "C" void Win32_set_view_matrix () +{ + vms_vector *pPos = &View_position; + vms_matrix *pOrient = &View_matrix; + + D3DVECTOR vecView; + vecView.x = (D3DVALUE) f2fl (pPos->x) / 10; + vecView.y = (D3DVALUE) f2fl (pPos->y) / 10; + vecView.z = (D3DVALUE) f2fl (pPos->z) / 10; + + D3DMATRIX matView; + D3DVECTOR vecDir; + matView(0, 0) = g_vecRight.x = (D3DVALUE) f2fl (pOrient->rvec.x) / 10; + matView(1, 0) = g_vecRight.y = (D3DVALUE) f2fl (pOrient->rvec.y) / 10; + matView(2, 0) = g_vecRight.z = (D3DVALUE) f2fl (pOrient->rvec.z) / 10; + + matView(0, 1) = g_vecUp.x = (D3DVALUE) f2fl (pOrient->uvec.x) / 10; + matView(1, 1) = g_vecUp.y = (D3DVALUE) f2fl (pOrient->uvec.y) / 10; + matView(2, 1) = g_vecUp.z = (D3DVALUE) f2fl (pOrient->uvec.z) / 10; + + matView(0, 2) = vecDir.x = (D3DVALUE) f2fl (pOrient->fvec.x) / 10; + matView(1, 2) = vecDir.y = (D3DVALUE) f2fl (pOrient->fvec.y) / 10; + matView(2, 2) = vecDir.z = (D3DVALUE) f2fl (pOrient->fvec.z) / 10; + + matView(3, 0) = -DotProduct (g_vecRight, vecView); + matView(3, 1) = -DotProduct (g_vecUp, vecView); + matView(3, 2) = -DotProduct (vecDir, vecView); + + matView(0, 3) = matView(1, 3) = matView(2, 3) = 0.0f; + matView(3, 3) = 1.0f; + + g_pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &matView ); +} + +HRESULT SetTexture (CTexture *pTexture) +{ + HRESULT hResult = S_OK; + LPDIRECT3DTEXTURE2 pd3dt; + BOOL bTransparent; + + if (pTexture != NULL) + { + pd3dt = pTexture->GetTexture (); + bTransparent = pTexture->IsTransparent (); + } + else + { + pd3dt = NULL; + bTransparent = FALSE; + } + + if (pd3dt != g_pd3dtLast) + { + g_pd3dtLast = pd3dt; + + hResult = g_pd3dDevice->SetTexture (0, pd3dt); + ASSERT (SUCCEEDED (hResult)); + } + + if (bTransparent != g_bTransparentLast) + { + g_bTransparentLast = bTransparent; + + hResult = g_pd3dDevice->SetRenderState (D3DRENDERSTATE_COLORKEYENABLE, bTransparent); + ASSERT (SUCCEEDED (hResult)); + } + return hResult; +} + +extern "C" bool g3_draw_tmap (int cPoints, g3s_point **rgpPoints, g3s_uvl *rgpUvls, grs_bitmap *pbm) +{ + ASSERT (cPoints <= sizeof (g_rgVerts) / sizeof (g_rgVerts[0])); + + for (ULONG iPoint = 0; iPoint < cPoints; iPoint ++) + { + D3DLVERTEX *pvert = &g_rgVerts [iPoint]; + const g3s_point *pPoint = rgpPoints [iPoint]; + const g3s_uvl *pUvl = &rgpUvls [iPoint]; + double dCol = f2fl (pUvl->l); + double dColR = min (1, max (0, dCol + g_fPSURed)); + double dColG = min (1, max (0, dCol + g_fPSUGreen)); + double dColB = min (1, max (0, dCol + g_fPSUBlue)); + + pvert->x = (D3DVALUE) f2fl (pPoint->p3_orig.x) / 10; + pvert->y = (D3DVALUE) f2fl (pPoint->p3_orig.y) / 10; + pvert->z = (D3DVALUE) f2fl (pPoint->p3_orig.z) / 10; + pvert->tu = (D3DVALUE) f2fl (pUvl->u); + pvert->tv = (D3DVALUE) f2fl (pUvl->v); + pvert->color = D3DRGBA (dColR, dColG, dColB, 0); + pvert->specular = 0; + } + + HRESULT hResult; + hResult = SetTexture ((CTexture *) pbm->pvSurface); + ASSERT (SUCCEEDED (hResult)); + + hResult = g_pd3dDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, D3DFVF_LVERTEX, g_rgVerts, cPoints, D3DDP_WAIT); + ASSERT (SUCCEEDED (hResult)); + + return hResult == S_OK; +} + +extern "C" bool g3_draw_poly (int cPoints, g3s_point **rgpPoints) +{ + ASSERT (cPoints <= sizeof (g_rgVerts) / sizeof (g_rgVerts[0])); + PALETTEENTRY pe = g_setTextures.ReadPalette (grd_curcanv->cv_color); + BYTE bR = pe.peRed; + BYTE bG = pe.peGreen; + BYTE bB = pe.peBlue; + double dColR = min (1, max (0, (float) bR / 256 + g_fPSURed)); + double dColG = min (1, max (0, (float) bG / 256 + g_fPSUGreen)); + double dColB = min (1, max (0, (float) bB / 256 + g_fPSUBlue)); + + for (ULONG iPoint = 0; iPoint < cPoints; iPoint ++) + { + D3DLVERTEX *pvert = &g_rgVerts [iPoint]; + const g3s_point *pPoint = rgpPoints [iPoint]; + + pvert->x = (D3DVALUE) f2fl (pPoint->p3_orig.x) / 10; + pvert->y = (D3DVALUE) f2fl (pPoint->p3_orig.y) / 10; + pvert->z = (D3DVALUE) f2fl (pPoint->p3_orig.z) / 10; + pvert->tu = 0; + pvert->tv = 0; + pvert->color = D3DRGBA (dColR, dColG, dColB, 0); + pvert->specular = 0; + } + + HRESULT hResult; + hResult = SetTexture (NULL); + ASSERT (SUCCEEDED (hResult)); + + hResult = g_pd3dDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, D3DFVF_LVERTEX, g_rgVerts, cPoints, D3DDP_WAIT); + ASSERT (SUCCEEDED (hResult)); + + return S_OK; +} + + + +extern "C" bool g3_draw_bitmap (vms_vector *pos, fix width, fix height,grs_bitmap *pbm) +{ + ULONG cPoints = 4; + + D3DVECTOR vecRight = g_vecRight * f2fl (width); + D3DVECTOR vecUp = g_vecUp * f2fl (height); + D3DVECTOR vecPos ( + (D3DVALUE) f2fl (pos->x) / 10, + (D3DVALUE) f2fl (pos->y) / 10, + (D3DVALUE) f2fl (pos->z) / 10); + + double dCol = 0.5; + double dColR = min (1, max (0, dCol + g_fPSURed)); + double dColG = min (1, max (0, dCol + g_fPSUGreen)); + double dColB = min (1, max (0, dCol + g_fPSUBlue)); + D3DCOLOR col = D3DRGBA (dColR, dColG, dColB, 0); + + D3DVALUE flAdjX, flAdjY; + CTexture *pTexture = (CTexture *) pbm->pvSurface; + pTexture->GetBitmapAdj (&flAdjX, &flAdjY); + + D3DLVERTEX rgVerts [4] = + { + D3DLVERTEX (vecPos - vecRight - vecUp, col, 0, 0, flAdjY), + D3DLVERTEX (vecPos - vecRight + vecUp, col, 0, 0, 0), + D3DLVERTEX (vecPos + vecRight + vecUp, col, 0, flAdjX, 0), + D3DLVERTEX (vecPos + vecRight - vecUp, col, 0, flAdjX, flAdjY), + }; + + HRESULT hResult; + hResult = SetTexture (pTexture); + ASSERT (SUCCEEDED (hResult)); + + hResult = g_pd3dDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, D3DFVF_LVERTEX, rgVerts, cPoints, D3DDP_WAIT); + ASSERT (SUCCEEDED (hResult)); + + return S_OK; +} + +extern "C" void BlitToPrimary(HDC hSrcDC) +{ + RECT rectDest; + rectDest.left = 0; + rectDest.top = 0; + rectDest.right = g_pFramework->m_dwRenderWidth; + rectDest.bottom = g_pFramework->m_dwRenderHeight; + + if (g_bWindowed) + { + rectDest.left += g_pFramework->m_rcScreenRect.left; + rectDest.right += g_pFramework->m_rcScreenRect.left; + rectDest.top += g_pFramework->m_rcScreenRect.top; + rectDest.bottom += g_pFramework->m_rcScreenRect.top; + } + + HDC hDstDC; + if (g_pFramework->GetFrontBuffer()->GetDC(&hDstDC) == DD_OK) + { + StretchBlt(hDstDC, rectDest.left, rectDest.top, + rectDest.right - rectDest.left, rectDest.bottom - rectDest.top, + hSrcDC, 0, 0, 320, 200, SRCCOPY); + g_pFramework->GetFrontBuffer()->ReleaseDC(hDstDC); + } + return; +} + +extern "C" void BlitToPrimaryRect(HDC hSrcDC, int x, int y, int w, int h, + unsigned char *dst) +{ + RECT rectDest; + int destWidth = g_pFramework->m_dwRenderWidth; + int destHeight = g_pFramework->m_dwRenderHeight; + + rectDest.left = (x * destWidth) / 320; + rectDest.top = (y * destHeight) / 200; + rectDest.right = ((x + w) * destWidth) / 320; + rectDest.bottom = ((y + h) * destHeight) / 200; + + if (g_bWindowed && (int)dst == BM_D3D_DISPLAY) + { + rectDest.left += g_pFramework->m_rcScreenRect.left; + rectDest.right += g_pFramework->m_rcScreenRect.left; + rectDest.top += g_pFramework->m_rcScreenRect.top; + rectDest.bottom += g_pFramework->m_rcScreenRect.top; + } + + HDC hDstDC; + IDirectDrawSurface4 *pddsDest = ((int)dst == BM_D3D_DISPLAY) ? + g_pFramework->GetFrontBuffer() : + g_pFramework->GetRenderSurface(); + if (pddsDest->GetDC(&hDstDC) == DD_OK) + { + StretchBlt(hDstDC, rectDest.left, rectDest.top, + rectDest.right - rectDest.left, rectDest.bottom - rectDest.top, + hSrcDC, x, y, w, h, SRCCOPY); + pddsDest->ReleaseDC(hDstDC); + } + return; +} + +HRESULT Blit ( + RECT &rectDest, + LPDIRECTDRAWSURFACE4 pddsSrc, + RECT &rectSrc, + DWORD dwFlags, + DDBLTFX *pddbltfx, + BOOL bPrimary) +{ + rectDest.left = rectDest.left * g_pFramework->m_dwRenderWidth / 320; + rectDest.top = rectDest.top * g_pFramework->m_dwRenderHeight / 200; + rectDest.right = (rectDest.right + 1) * g_pFramework->m_dwRenderWidth / 320; + rectDest.bottom = (rectDest.bottom + 1) * g_pFramework->m_dwRenderHeight / 200; + + if (g_bWindowed && bPrimary) + { + rectDest.left += g_pFramework->m_rcScreenRect.left; + rectDest.right += g_pFramework->m_rcScreenRect.left; + rectDest.top += g_pFramework->m_rcScreenRect.top; + rectDest.bottom += g_pFramework->m_rcScreenRect.top; + } + + IDirectDrawSurface4 *pddsDest; + if (bPrimary) + { + pddsDest = g_pFramework->GetFrontBuffer (); + } + else + { + pddsDest = g_pFramework->GetRenderSurface(); + } + + return pddsDest->Blt ( + &rectDest, + pddsSrc, + &rectSrc, + dwFlags, + pddbltfx); +} + +static void findmask6(int in_mask, int *shift, int *bits6) +{ + int i; + + if (!in_mask) { + *shift = 0; + *bits6 = 6; + return; + } + i = 0; + while (!(in_mask & 1)) + { + in_mask >>= 1; + i++; + } + *shift = i; + i = 0; + while (in_mask & 1) + { + in_mask >>= 1; + i++; + } + *bits6 = 6 - i; +} + +void Win32_SetupColor(void) +{ + DDPIXELFORMAT pf; + pf.dwSize = sizeof(pf); + g_pFramework->GetFrontBuffer ()->GetPixelFormat(&pf); + g_TrueColor = pf.dwRGBBitCount == 24 || pf.dwRGBBitCount == 32; + if (!g_TrueColor) + { + findmask6(pf.dwRBitMask, &g_RShift, &g_RBits6); + findmask6(pf.dwGBitMask, &g_GShift, &g_GBits6); + findmask6(pf.dwBBitMask, &g_BShift, &g_BBits6); + } +} + +extern "C" void Win32_Rect ( + int left, int top, int right, int bot, + int iSurf, + int iCol) +{ + RECT rectDest = {left, top, right, bot}; + + DDBLTFX ddbltfx; + ddbltfx.dwSize = sizeof (ddbltfx); + + #if 0 + if (g_setTextures.HasPalette ()) + { + ddbltfx.dwFillColor = iCol; + } + else + { + PALETTEENTRY pe = g_setTextures.ReadPalette (iCol); + ddbltfx.dwFillColor = *(DWORD*) &pe; + } + #else + unsigned char *p = gr_current_pal + iCol * 3; + if (g_TrueColor) + ddbltfx.dwFillColor = (255 << 24) | (p[0] << 18) | + (p[1] << 10) | (p[2] << 2); + else + ddbltfx.dwFillColor = (p[0] >> g_RBits6) << g_RShift | + (p[1] >> g_GBits6) << g_GShift | + (p[2] >> g_BBits6) << g_BShift; + #endif + + HRESULT hr = Blit ( + rectDest, + NULL, + rectDest, + DDBLT_WAIT | DDBLT_COLORFILL, + &ddbltfx, + iSurf == BM_D3D_DISPLAY); +} + + +extern "C" void Win32_BlitLinearToDirectX ( + int w, int h, + int dx, int dy, + int sx, int sy, + void *pvSurface, + int iSurf, + BOOL bTransparent) +{ + CTexture *pTexture = (CTexture *) pvSurface; + + if (pTexture == NULL) + { + return; + } + + if (!(w <= pTexture->m_ulWidthSource && h <= pTexture->m_ulHeightSource)) + { + ASSERT (FALSE); + } + + if (pTexture->isDirtyMemory ()) + { + pTexture->CleanMemory (); + } + + RECT rectDest = {dx, dy, dx + w, dy + h}; + RECT rectSrc = {0, 0, w, h}; + + HRESULT hr = Blit ( + rectDest, + pTexture->GetSurface (), + rectSrc, + DDBLT_WAIT, + NULL, + iSurf == BM_D3D_DISPLAY); +} + +extern "C" void Win32_start_instance_matrix (vms_vector *pPos, vms_matrix *pOrient) +{ + D3DMATRIX matOrientInv; + if (pOrient != NULL) + { + D3DMATRIX matOrient; + + matOrient(0, 0) = (D3DVALUE) f2fl (pOrient->rvec.x); + matOrient(1, 0) = (D3DVALUE) f2fl (pOrient->rvec.y); + matOrient(2, 0) = (D3DVALUE) f2fl (pOrient->rvec.z); + matOrient(3, 0) = 0; + matOrient(0, 1) = (D3DVALUE) f2fl (pOrient->uvec.x); + matOrient(1, 1) = (D3DVALUE) f2fl (pOrient->uvec.y); + matOrient(2, 1) = (D3DVALUE) f2fl (pOrient->uvec.z); + matOrient(3, 1) = 0; + matOrient(0, 2) = (D3DVALUE) f2fl (pOrient->fvec.x); + matOrient(1, 2) = (D3DVALUE) f2fl (pOrient->fvec.y); + matOrient(2, 2) = (D3DVALUE) f2fl (pOrient->fvec.z); + matOrient(3, 2) = 0; + matOrient(0, 3) = 0; + matOrient(1, 3) = 0; + matOrient(2, 3) = 0; + matOrient(3, 3) = 1; + + D3DMath_MatrixInvert (matOrientInv, matOrient); + } + else + { + D3DUtil_SetIdentityMatrix (matOrientInv); + } + + D3DMATRIX matTranslate; + D3DUtil_SetTranslateMatrix ( + matTranslate, + (D3DVALUE) f2fl (pPos->x) / 10, + (D3DVALUE) f2fl (pPos->y) / 10, + (D3DVALUE) f2fl (pPos->z) / 10); + + D3DMATRIX matTmp; + D3DMath_MatrixMultiply (matTmp, g_stkWorlds.top (), matTranslate); + D3DMATRIX matWorld; + D3DMath_MatrixMultiply (matWorld, matTmp, matOrientInv); + + g_stkWorlds.push (matWorld); + + g_pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matWorld ); +} + +extern "C" void Win32_done_instance (void) +{ + g_stkWorlds.pop (); + + D3DMATRIX matWorld = g_stkWorlds.top (); + g_pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matWorld ); +} + + +extern "C" void Win32_SetTextureBits (grs_bitmap *bm, unsigned char *data, int bRle) +{ + CTexture *pTexture = (CTexture *) bm->pvSurface; + if (pTexture != NULL) + { + pTexture->SetBitmapData (data, bRle); + pTexture->SetTransparent (bm->bm_flags & BM_FLAG_TRANSPARENT); + } +} + +extern "C" void Win32_CreateTexture (grs_bitmap *bm) +{ + bm->pvSurface = (void *) g_setTextures.CreateTexture ( + bm->bm_data, + bm->bm_w, + bm->bm_h, + bm->bm_rowsize); +} + +extern "C" void Win32_FreeTexture (grs_bitmap *bm) +{ + CTexture *pTexture = (CTexture *) bm->pvSurface; + if (pTexture != NULL) + { + g_setTextures.FreeTexture (pTexture); + bm->pvSurface = NULL; + } +} + +extern "C" void Win32_SetTransparent (void *pvTexture, BOOL bTransparent) +{ + CTexture *pTexture = (CTexture *) pvTexture; + if (pTexture != NULL) + { + pTexture->SetTransparent (bTransparent); + } +} + diff --git a/arch/win32/serial.c b/arch/win32/serial.c new file mode 100644 index 00000000..7b235c30 --- /dev/null +++ b/arch/win32/serial.c @@ -0,0 +1,41 @@ +void com_done(void) +{ +} + +int com_init(void) +{ + return 0; +} + +int com_read(char *buffer, int len, int timeout_value) +{ + return -1; +} + +int com_write(char *buffer, int len) +{ + return -1; +} + +void com_port_hangup() +{ +} + +int com_getdcd() +{ + return -1; +} + +void com_flushbuffers() +{ +} + +void com_setbaudrate(int rate) +{ +} + +int com_readline(int timeout_value, char *input_buffer,int len) +{ + return 0; +} + diff --git a/arch/win32/texture.cpp b/arch/win32/texture.cpp new file mode 100644 index 00000000..d94bd014 --- /dev/null +++ b/arch/win32/texture.cpp @@ -0,0 +1,533 @@ +#include "pch.h" +#include "texture.h" + +#include "d3dframe.h" +extern CD3DFramework* g_pFramework; + +//////////////////////////////////////////////////////////////////////////// + +BOOL CTexture::s_bLocked = FALSE; +DDSURFACEDESC2 CTexture::s_ddsd; + + +HRESULT CTexture::Initialize (BYTE *rgbSource, ULONG ulWidth, ULONG ulHeight, ULONG ulPitch) +{ + m_rgbSource = rgbSource; + m_ulWidthSource = ulWidth; + m_ulHeightSource = ulHeight; + m_ulPitchSource = ulPitch; + + return S_OK; +} + +HRESULT CTexture::Allocate (CPaletteInfo *ppi) +{ + HRESULT hr; + + ASSERT (m_spddsMemory == NULL); + + if (ppi->IsPow2 ()) + { + m_ulWidth = 1; + while (m_ulWidth < m_ulWidthSource) + m_ulWidth *= 2; + + m_ulHeight = 1; + while (m_ulHeight < m_ulHeightSource) + m_ulHeight *= 2; + } + else + { + m_ulWidth = m_ulWidthSource; + m_ulHeight = m_ulHeightSource; + } + + if (ppi->IsSquare ()) + { + if (m_ulHeight > m_ulWidth) + { + m_ulWidth = m_ulHeight; + } + else + { + m_ulHeight = m_ulWidth; + } + } + + m_flAdjX = (D3DVALUE) m_ulWidthSource / (D3DVALUE) m_ulWidth; + m_flAdjY = (D3DVALUE) m_ulHeightSource / (D3DVALUE) m_ulHeight; + + DDSURFACEDESC2 ddsd; + ZeroMemory (&ddsd, sizeof (ddsd)); + ddsd.dwSize = sizeof (ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; + ddsd.dwWidth = m_ulWidth; + ddsd.dwHeight = m_ulHeight; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; + ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE; + ppi->GetPixelFormat (&ddsd.ddpfPixelFormat); + + hr = g_pFramework->GetDirectDraw ()->CreateSurface(&ddsd, &m_spddsMemory, NULL); + ASSERT (SUCCEEDED (hr)); + if (FAILED (hr)) + return hr; + + ASSERT (m_spddsMemory != NULL); + + m_spddtMemory = m_spddsMemory; + + DirtyMemory (); + + DDCOLORKEY ddck; + if (ppi->IsIndexed ()) + { + ddck.dwColorSpaceLowValue = 255; + ddck.dwColorSpaceHighValue = 255; + } + else + { + ddck.dwColorSpaceLowValue = 0; + ddck.dwColorSpaceHighValue = 0; + } + hr = m_spddsMemory->SetColorKey (DDCKEY_SRCBLT, &ddck); + ASSERT (SUCCEEDED (hr)); + + if (ppi->GetPalette () != NULL) + { + hr = m_spddsMemory->SetPalette (ppi->GetPalette ()); + ASSERT (SUCCEEDED (hr)); + } + + return hr; +} + +HRESULT CTexture::Free (void) +{ + HRESULT hr = S_OK; + + m_spddtMemory = m_spddsMemory = NULL; + + m_ulWidth = 0; + m_ulHeight = 0; + + return hr; +} + +HRESULT CTexture::Lock (void) +{ + HRESULT hr; + if (!s_bLocked) + { + s_bLocked = TRUE; + + s_ddsd.dwSize = sizeof (s_ddsd); + hr = m_spddsMemory->Lock ( + NULL, + &s_ddsd, +#ifndef NDEBUG + DDLOCK_NOSYSLOCK | +#endif + DDLOCK_WAIT, + NULL); + ASSERT (SUCCEEDED (hr)); + } + else + { + // already locked + hr = E_FAIL; + ASSERT (FALSE); + } + return hr; +} + +HRESULT CTexture::Unlock (void) +{ + HRESULT hr; + if (s_bLocked) + { + hr = m_spddsMemory->Unlock (NULL); + ASSERT (SUCCEEDED (hr)); + + s_bLocked = FALSE; + } + else + { + // not locked + hr = E_FAIL; + ASSERT (FALSE); + } + return hr; +} + +void CTexture::PlotPixel (ULONG ulX, ULONG ulY, BYTE b) +{ + ASSERT (ulX <= m_ulWidth); + ASSERT (ulY <= m_ulHeight); + + ASSERT (s_bLocked); + ASSERT (s_ddsd.lpSurface != NULL); + + switch (s_ddsd.ddpfPixelFormat.dwRGBBitCount) + { + case 8: + { + * (((LPBYTE) s_ddsd.lpSurface) + ulX + ulY * s_ddsd.lPitch) = b; + + break; + } + case 16: + { + WORD w; + if (!(m_bTransparent && b == 255)) + { + w = m_ppi->Read16 (b); + } + else + { + w = 0; + } + * (WORD *) (((LPBYTE) s_ddsd.lpSurface) + ulX * 2 + ulY * s_ddsd.lPitch) = w; + break; + } + + default: + { + ASSERT (FALSE); + break; + } + } +} + +void CTexture::SetBitmapData (BYTE *rgb, BOOL bRle) +{ + m_rgbSource = rgb; + m_bRle = bRle; + DirtyMemory (); +} + +void CTexture::CopyFromSource (void) +{ + if (SUCCEEDED (Lock ())) + { + if (m_bRle) + { + PBYTE pbLine = m_rgbSource + m_ulHeightSource + 4;; + for (ULONG y = 0; y < m_ulHeightSource; y ++) + { + ULONG x = 0; + PBYTE pbSrc = pbLine; + + while (1) + { + const BYTE RLE_CODE = 0xE0; + BYTE b = *pbSrc++; + if ((b & RLE_CODE) != RLE_CODE) + { + PlotPixel (x++, y, b); + } + else + { + BYTE cb = b & (~RLE_CODE); + if (cb == 0) + break; + + b = *pbSrc++; + while (cb--) + PlotPixel (x++, y, b); + } + } + ASSERT (x <= m_ulWidthSource); + + pbLine += m_rgbSource [y + 4]; + } + } + else + { + LPBYTE lpbDest = (LPBYTE) s_ddsd.lpSurface; + LPBYTE lpbSrc = m_rgbSource; + + switch (s_ddsd.ddpfPixelFormat.dwRGBBitCount) + { + case 8: + { + for (ULONG y = m_ulHeightSource; y != 0; y--) + { + memcpy (lpbDest, lpbSrc, m_ulPitchSource); + lpbDest += s_ddsd.lPitch; + lpbSrc += m_ulPitchSource; + } + break; + } + case 16: + { + for (ULONG y = m_ulHeightSource; y != 0; y--) + { + LPBYTE lpbLineSrc = lpbSrc; + LPWORD lpwLineDest = (LPWORD) lpbDest; + + if (m_bTransparent) + { + for (ULONG x = m_ulWidthSource; x != 0; x--) + { + BYTE b = *lpbLineSrc++; + *lpwLineDest++ = (b == 255) ? 0 : m_ppi->Read16 (b); + } + } + else + { + for (ULONG x = m_ulWidthSource; x != 0; x--) + { + *lpwLineDest++ = m_ppi->Read16 (*lpbLineSrc++); + } + } + lpbDest += s_ddsd.lPitch; + lpbSrc += m_ulPitchSource; + } + break; + } + + default: + { + ASSERT (FALSE); + break; + } + } + } + Unlock (); + } + else + { + ASSERT (FALSE); + } +} + +HRESULT CTexture::CleanMemory (void) +{ + CopyFromSource (); + m_bDirtyMemory = FALSE; + return S_OK; +} + +IDirect3DTexture2 *CTexture::GetTexture () +{ + if (m_bDirtyMemory) + { + CleanMemory (); + } + + return m_spddtMemory; +} + +//////////////////////////////////////////////////////////////////////////// + +struct FindTextureData +{ + DWORD bpp; // we want a texture format of this bpp + DDPIXELFORMAT ddpf; // place the format here +}; + + +HRESULT CALLBACK FindTextureCallback(LPDDPIXELFORMAT pddpf, LPVOID lParam) +{ + FindTextureData * FindData = (FindTextureData *)lParam; + + // + // we use GetDC/BitBlt to init textures so we only + // want to use formats that GetDC will support. + // + if (pddpf->dwFlags & (DDPF_ALPHA|DDPF_ALPHAPIXELS)) + return DDENUMRET_OK; + +/* + if (pddpf->dwRGBBitCount == 16) + { + FindData->ddpf = ddpf; + } + + return DDENUMRET_OK; +*/ + + +// if (!(pddpf->dwFlags & DDPF_ALPHAPIXELS)) +// return DDENUMRET_OK; + + if (pddpf->dwRGBBitCount < 8) + return DDENUMRET_OK; + + if (pddpf->dwRGBBitCount == 8 && !(pddpf->dwFlags & DDPF_PALETTEINDEXED8)) + return DDENUMRET_OK; + + if (pddpf->dwRGBBitCount > 8 && !(pddpf->dwFlags & DDPF_RGB)) + return DDENUMRET_OK; + + // + // keep the texture format that is nearest to the bitmap we have + // + if (FindData->ddpf.dwRGBBitCount == 0 || + (pddpf->dwRGBBitCount >= FindData->bpp && pddpf->dwRGBBitCount <= FindData->ddpf.dwRGBBitCount) //&& + //(pddpf->dwAlphaBitDepth != 0 && pddpf->dwAlphaBitDepth > FindData->ddpf.dwAlphaBitDepth) // ALPHA BIT DEPTHS ARE REVERSED!!!! + ) + { + FindData->ddpf = *pddpf; + } + + return DDENUMRET_OK; +} + +void ChooseTextureFormat(LPDIRECT3DDEVICE3 Device, DWORD bpp, DDPIXELFORMAT *pddpf) +{ + HRESULT hr; + FindTextureData FindData; + ZeroMemory(&FindData, sizeof(FindData)); + FindData.bpp = bpp; + hr = Device->EnumTextureFormats(FindTextureCallback, (LPVOID)&FindData); + ASSERT(hr == S_OK); + *pddpf = FindData.ddpf; +} + +HRESULT CPaletteInfo::Initialize () +{ + m_spddpPalette = NULL; + + // + // find the best texture format to use. + // + ChooseTextureFormat (g_pFramework->GetD3DDevice (), 8, &m_ddpfPixelFormat); + + m_cshftR = GetShift (m_mskR = m_ddpfPixelFormat.dwRBitMask); + m_cshftG = GetShift (m_mskG = m_ddpfPixelFormat.dwGBitMask); + m_cshftB = GetShift (m_mskB = m_ddpfPixelFormat.dwBBitMask); + + HRESULT hr; + + D3DDEVICEDESC descHAL, descHEL; + descHAL.dwSize = descHEL.dwSize = sizeof (descHAL); + hr = g_pFramework->GetD3DDevice ()->GetCaps (&descHAL, &descHEL); + ASSERT (SUCCEEDED (hr)); + + if (!descHAL.dwFlags) { + m_bPow2 = (descHEL.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) != 0; + m_bSquare = (descHEL.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) != 0; + } else { + m_bPow2 = (descHAL.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) != 0; + m_bSquare = (descHAL.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) != 0; + } + + if (IsIndexed ()) + { + hr = g_pFramework->GetDirectDraw ()->CreatePalette (DDPCAPS_8BIT | DDPCAPS_ALLOW256, m_rgpe, &m_spddpPalette, NULL); + ASSERT (SUCCEEDED (hr)); + } + + return S_OK; +} + +HRESULT CPaletteInfo::Uninitialize () +{ + m_spddpPalette = NULL; // smart pointer release + + return S_OK; +} + +void CPaletteInfo::SetPaletteEntries (PALETTEENTRY rgpe [256]) +{ + // okay, we don't really need to cache the palette values + // we could implement ReadPalette by individual Getentries calls... + memcpy (m_rgpe, rgpe, sizeof (m_rgpe)); + + if (m_spddpPalette != NULL) + { + HRESULT hr = m_spddpPalette->SetEntries (0, 0, 256, m_rgpe); + ASSERT (SUCCEEDED (hr)); + } +} + +void CPaletteInfo::GetPaletteEntries (PALETTEENTRY rgpe [256]) +{ + if (m_spddpPalette != NULL) + { + HRESULT hr = m_spddpPalette->GetEntries (0, 0, 256, m_rgpe); + ASSERT (SUCCEEDED (hr)); + } +} + +//////////////////////////////////////////////////////////////// +CPaletteInfo *CTexture::m_ppi; + +HRESULT CTextureSet::Initialize () +{ + HRESULT hr; + + hr = m_pi.Initialize (); + ASSERT (SUCCEEDED (hr)); + + CTexture::m_ppi = &m_pi; + + for (TEXTURE_SET::iterator iter = m_setTextures.begin (); + iter != m_setTextures.end (); + iter ++) + { + (*iter)->Allocate (&m_pi); + } + + return hr; +} + +HRESULT CTextureSet::Uninitialize () +{ + for (TEXTURE_SET::iterator iter = m_setTextures.begin (); + iter != m_setTextures.end (); + iter ++) + { + (*iter)->Free (); + } + + m_pi.Uninitialize (); + + return S_OK; +} + +CTexture *CTextureSet::CreateTexture (BYTE *rgbSource, ULONG dx, ULONG dy, ULONG ulPitch) +{ + CTexture *pTexture = new CTexture; + + pTexture->Initialize (rgbSource, dx, dy, ulPitch); + pTexture->Allocate (&m_pi); + + m_setTextures.insert (pTexture); + + return pTexture; +} + +void CTextureSet::FreeTexture (CTexture *pTexture) +{ + m_setTextures.erase (pTexture); + + delete pTexture; +} + +void CTextureSet::DirtyTextures (void) +{ + for (TEXTURE_SET::iterator iter = m_setTextures.begin (); + iter != m_setTextures.end (); + iter ++) + { + (*iter)->DirtyMemory (); + } +} + + +void CTextureSet::SetPaletteEntries (PALETTEENTRY rgpe [256]) +{ + m_pi.SetPaletteEntries (rgpe); + + if (!m_pi.IsIndexed ()) + { + DirtyTextures (); + } +} + +void CTextureSet::GetPaletteEntries (PALETTEENTRY rgpe [256]) +{ + m_pi.GetPaletteEntries (rgpe); +} diff --git a/arch/win32/timer.c b/arch/win32/timer.c new file mode 100644 index 00000000..4b59a88d --- /dev/null +++ b/arch/win32/timer.c @@ -0,0 +1,71 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +// File nearly completely rewritten by dph-man + +#include +#include // DPH: We use timeGetTime from here... + +#include "types.h" +#include "maths.h" +#include "timer.h" + +static int Installed = 0; + +static unsigned long old_tv; + +fix timer_get_fixed_seconds() +{ + fix x; + + //Ye good olde unix: + //Ye bad olde Windows DPH:-) +/* DPH: Using timeGetTime will fail approximately 47 days after Windows was + started as the timer wraps around to 0. Ever had Windows not crash for 47 + consecutive days? Thought not. */ + + unsigned long tv_now=timeGetTime()-old_tv; + x=i2f(tv_now/1000) | fixdiv(i2f(tv_now % 1000),i2f(1000)); + return x; +} + +void delay(int d_time) +{ + fix t, total; + + total = (F1_0 * d_time) / 1000; + t = timer_get_fixed_seconds(); + while (timer_get_fixed_seconds() - t < total) ; +} + +void timer_close() +{ + Installed = 0; +} + +void timer_init() +{ + + if (Installed) + return; + Installed = 1; + +/* DPH: Using timeGetTime will fail approximately 47 days after Windows was + started as the timer wraps around to 0. Ever had Windows not crash for 47 + consecutive days? Thought not. */ + old_tv=timeGetTime(); + +} + +// NOTE: This C file has been "neutered" by dph-man. If someone wants to work +// on this, feel free. I don't use joystick :-) diff --git a/arch/win32/win32.c b/arch/win32/win32.c new file mode 100644 index 00000000..60e5075f --- /dev/null +++ b/arch/win32/win32.c @@ -0,0 +1,335 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include "gr.h" +#include "grdef.h" +#include "u_mem.h" +#include "timer.h" +#include "error.h" + +#include "gr.h" +#include "grdef.h" +#include "palette.h" +#include "rle.h" +#include "d3dhelp.h" +#include "game.h" +#include "gauges.h" +#include "args.h" + +#include "gamefont.h" + +#ifndef NDEBUG +#ifdef _MSC_VER +#include +#endif +#endif + +void gr_linear_rep_movsdm(ubyte *src, ubyte *dest, int num_pixels); +void InitMain(); +void show_dd_error(HRESULT hr, char *loc); +void GetDDErrorString(HRESULT hr, char *buf, int size); + +void BlitToPrimary(HDC hSrcDC); +void BlitToPrimaryRect(HDC hSrcDC, int x, int y, int w, int h, + unsigned char *dst); +extern HWND g_hWnd; + +void key_init(void); +void mouse_init(void); + + +unsigned char *createdib(void); + +static unsigned char *backbuffer, *screenbuffer; +static int screensize; +static HBITMAP screen_bitmap; + +void arch_init_start() +{ + #ifndef NDEBUG + #ifdef _MSC_VER + if (FindArg("-memdbg")) + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | + /* _CRTDBG_CHECK_CRT_DF | */ + _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF); + #endif + #endif + + InitMain (); +} + +void arch_init() +{ + //SetPriorityClass (GetCurrentProcess(),HIGH_PRIORITY_CLASS); + + timer_init (); + key_init(); + mouse_init(); + + printf("arch_init successfully completed\n"); +} + + + + +int gr_installed = 0; + +int gr_check_mode(int mode) +{ + if (mode == SM_320x200C) + return 0; + + return 11; +} + +int gr_set_mode(int mode) +{ + unsigned int w,h,t,r; + + if (mode == SM_ORIGINAL) + return 0; + + switch (mode) + { + case SM(320,200): + w = 320; r = 320; h = 200; t=BM_LINEAR;//BM_DIRECTX;; + break; + default: + return 1; + } + + gr_palette_clear(); + + memset( grd_curscreen, 0, sizeof(grs_screen)); + grd_curscreen->sc_mode = mode; + grd_curscreen->sc_w = w; + grd_curscreen->sc_h = h; + grd_curscreen->sc_aspect = fixdiv(grd_curscreen->sc_w*3,grd_curscreen->sc_h*4); + gr_init_canvas(&grd_curscreen->sc_canvas, (unsigned char *)BM_D3D_DISPLAY, t, w, h); + gr_set_current_canvas(NULL); + + + if (!(backbuffer = createdib())) + return 1; + + grd_curscreen->sc_canvas.cv_bitmap.bm_data = backbuffer; + grd_curscreen->sc_canvas.cv_bitmap.bm_type = BM_LINEAR; + grd_curscreen->sc_canvas.cv_bitmap.bm_x = 0; + grd_curscreen->sc_canvas.cv_bitmap.bm_y = 0; + grd_curscreen->sc_canvas.cv_bitmap.bm_w = w; + grd_curscreen->sc_canvas.cv_bitmap.bm_h = h; + grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize = w; + + gamefont_choose_game_font(w,h); + + return 0; +} + +int gr_init(int mode) +{ + //int org_gamma; + int retcode; + //HRESULT hr; + + // Only do this function once! + if (gr_installed==1) + return -1; + + MALLOC( grd_curscreen,grs_screen,1 ); + memset( grd_curscreen, 0, sizeof(grs_screen)); + + // Set the mode. + if ((retcode=gr_set_mode(mode))) + { + return retcode; + } + + // Set all the screen, canvas, and bitmap variables that + // aren't set by the gr_set_mode call: + grd_curscreen->sc_canvas.cv_color = 0; + grd_curscreen->sc_canvas.cv_drawmode = 0; + grd_curscreen->sc_canvas.cv_font = NULL; + grd_curscreen->sc_canvas.cv_font_fg_color = 0; + grd_curscreen->sc_canvas.cv_font_bg_color = 0; + gr_set_current_canvas( &grd_curscreen->sc_canvas ); + + // Set flags indicating that this is installed. + gr_installed = 1; + + return 0; +} + +void gr_upixel( int x, int y ) +{ + gr_bm_upixel(&grd_curcanv->cv_bitmap, x, y, (unsigned char)COLOR); +#if 0 + grs_bitmap * bm = &grd_curcanv->cv_bitmap; + Win32_Rect ( + //x + bm->bm_x, y + bm->bm_y, + //x + bm->bm_x, y + bm->bm_y, + x, y, x, y, + bm->bm_data, COLOR); +#endif +} + +void gr_bm_upixel( grs_bitmap * bm, int x, int y, unsigned char color ) +{ + switch (bm->bm_type) + { + case BM_LINEAR: + bm->bm_data[ bm->bm_rowsize*y+x ] = color; + break; + + case BM_DIRECTX: + { + unsigned char *p = gr_current_pal + color * 3; + Win32_Rect ( + x, y, x, y, + //x + bm->bm_x, y + bm->bm_y, + //x + bm->bm_x, y + bm->bm_y, + (int)bm->bm_data, color); + } + break; + + default: + Assert (FALSE); + break; + } +} + +RGBQUAD w32lastrgb[256]; + +void gr_update () +{ + HDC hdc; + unsigned char *p; + int i; + + p = gr_current_pal; + for (i = 0; i < 256; i++) { + w32lastrgb[i].rgbRed = *p++ * 4; + w32lastrgb[i].rgbGreen = *p++ * 4; + w32lastrgb[i].rgbBlue = *p++ * 4; + } + hdc = CreateCompatibleDC(NULL); + SelectObject(hdc, screen_bitmap); + SetDIBColorTable(hdc, 0, 256, w32lastrgb); + + BlitToPrimary(hdc); + DeleteDC(hdc); +} + +void show_dd_error(HRESULT hr, char *loc) +{ + char buf[512], len; + + strcpy(buf, loc); + len = strlen(buf); + #ifdef NDEBUG + sprintf(buf + len, "%x", hr); + #else + GetDDErrorString(hr, buf + len, sizeof(buf) - len); + #endif + Error(buf); +} + +unsigned char *createdib(void) +{ + BITMAPINFO *bmHdr; + HDC hdc; + int i; + unsigned char *p; + unsigned char *buffer; + + if (!(bmHdr = malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)))) + return NULL; + + memset(bmHdr, 0, sizeof(*bmHdr)); + bmHdr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmHdr->bmiHeader.biWidth = grd_curscreen->sc_canvas.cv_bitmap.bm_w; + bmHdr->bmiHeader.biHeight = -grd_curscreen->sc_canvas.cv_bitmap.bm_h; + bmHdr->bmiHeader.biPlanes = 1; + bmHdr->bmiHeader.biBitCount = 8; + bmHdr->bmiHeader.biCompression = BI_RGB; + + p = gr_current_pal; + for (i = 0; i < 256; i++) { + #if 0 + ((short *)bmHdr->bmiColors)[i] = i; + #else + bmHdr->bmiColors[i].rgbRed = (*p++) << 2; + bmHdr->bmiColors[i].rgbGreen = (*p++) << 2; + bmHdr->bmiColors[i].rgbBlue = (*p++) << 2; + bmHdr->bmiColors[i].rgbReserved = 0; + #endif + } + hdc = CreateCompatibleDC(NULL); + if (!(screen_bitmap = CreateDIBSection(hdc, bmHdr, DIB_RGB_COLORS, + &buffer, NULL, 0))) { + int err = GetLastError(); + char buf[256]; + sprintf(buf, "CreateDISection():%d", err); + MessageBox(g_hWnd, buf, NULL, MB_OK); + } + DeleteDC(hdc); + free(bmHdr); + return buffer; +} + +void Win32_BlitLinearToDirectX_bm(grs_bitmap *bm, int sx, int sy, + int w, int h, int dx, int dy, int masked) { + HDC hdc; + unsigned char *src, *dest, *rle_w; + int i; + + dest = backbuffer + dy * 320 + dx; + + if (bm->bm_flags & BM_FLAG_RLE) { + src = bm->bm_data + 4 + bm->bm_h; + rle_w = bm->bm_data + 4; + while (sy--) + src += (int)*rle_w++; + if (masked) { + for (i = h; i--; ) { + gr_rle_expand_scanline_masked(dest, src, sx, sx + w - 1); + src += (int)*rle_w++; + dest += 320; + } + } else { + for (i = h; i--; ) { + gr_rle_expand_scanline(dest, src, sx, sx + w - 1); + src += (int)*rle_w++; + dest += 320; + } + } + } else { + src = bm->bm_data + sy * bm->bm_rowsize + sx; + if (masked) { + for (i = h; i--; ) { + gr_linear_rep_movsdm(src, dest, w); + src += bm->bm_rowsize; + dest += 320; + } + } else { + for (i = h; i--; ) { + gr_linear_movsd(src, dest, w); + src += bm->bm_rowsize; + dest += 320; + } + } + } + hdc = CreateCompatibleDC(NULL); + SelectObject(hdc, screen_bitmap); + SetDIBColorTable(hdc, 0, 256, w32lastrgb); + BlitToPrimaryRect(hdc, dx, dy, w, h, grd_curcanv->cv_bitmap.bm_data); + DeleteDC(hdc); +} + +void Win32_MakePalVisible(void) { + gr_update(); +} + +void Win32_InvalidatePages(void) { + reset_cockpit(); + init_gauges(); +} diff --git a/arch/win32/winmain.cpp b/arch/win32/winmain.cpp new file mode 100644 index 00000000..46d4600f --- /dev/null +++ b/arch/win32/winmain.cpp @@ -0,0 +1,690 @@ +//----------------------------------------------------------------------------- +// File: WinMain.cpp +// +// Desc: Windows code for Direct3D samples +// +// This code uses the Direct3D sample framework. +// +// +// Copyright (c) 1996-1998 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- + +#include "pch.h" +#include "WinMain.h" +#include "D3DFrame.h" +#include "D3DEnum.h" +#include "D3DUtil.h" +#include "resource.h" + +#include "scene.h" + + +//----------------------------------------------------------------------------- +// Global variables for using the D3D sample framework class +//----------------------------------------------------------------------------- +CD3DFramework* g_pFramework = NULL; +BOOL g_bActive = FALSE; +BOOL g_bReady = FALSE; +BOOL g_bFrameMoving = TRUE; +BOOL g_bSingleStep = FALSE; +BOOL g_bWindowed = TRUE; +BOOL g_bShowStats = TRUE; +RECT g_rcWindow; +HACCEL g_hAccel; +HWND g_hWnd; + +enum APPMSGTYPE { MSG_NONE, MSGERR_APPMUSTEXIT, MSGWARN_SWITCHTOSOFTWARE }; + + + + +//----------------------------------------------------------------------------- +// Local function-prototypes +//----------------------------------------------------------------------------- +INT CALLBACK AboutProc( HWND, UINT, WPARAM, LPARAM ); +LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); +HRESULT Initialize3DEnvironment( HWND ); +HRESULT Change3DEnvironment( HWND ); +HRESULT Render3DEnvironment(); +VOID Cleanup3DEnvironment(); +VOID DisplayFrameworkError( HRESULT, APPMSGTYPE ); +VOID AppShowStats(); +VOID AppOutputText( LPDIRECT3DDEVICE3, DWORD, DWORD, CHAR* ); +VOID AppPause( BOOL ); + + + + +//----------------------------------------------------------------------------- +// Name: WinMain() +// Desc: Entry point to the program. Initializes everything, and goes into a +// message-processing loop. Idle time is used to render the scene. +//----------------------------------------------------------------------------- +//INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) +extern "C" INT InitMain () +{ + HINSTANCE hInst = GetModuleHandle (NULL); + + // Register the window class + WNDCLASS wndClass = { CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInst, + LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN_ICON)), + LoadCursor(NULL, IDC_ARROW), + (HBRUSH)GetStockObject(WHITE_BRUSH), + MAKEINTRESOURCE(IDR_MENU), + TEXT("Render Window") }; + RegisterClass( &wndClass ); + + // Create our main window + g_hWnd = CreateWindow( TEXT("Render Window"), g_strAppTitle, + WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, + CW_USEDEFAULT, 300, 300, 0L, 0L, hInst, 0L ); + + RECT rect; + if (GetClientRect (g_hWnd, &rect)) + { + int cx = 320 + (300 - rect.right); + int cy = 200 + (300 - rect.bottom); + + SetWindowPos (g_hWnd, NULL, 0, 0, cx, cy, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOZORDER); + } + + ShowWindow( g_hWnd, SW_SHOWNORMAL ); + UpdateWindow( g_hWnd ); + + // Save the window size/pos for switching modes + GetWindowRect( g_hWnd, &g_rcWindow ); + + // Load keyboard accelerators + g_hAccel = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_MAIN_ACCEL) ); + + // Enumerate available D3D devices, passing a callback that allows devices + // to be accepted/rejected based on what capabilities the app requires. + HRESULT hr; + if( FAILED( hr = D3DEnum_EnumerateDevices( App_ConfirmDevice ) ) ) + { + DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT ); + return 0; + } + + // Check if we could not get a device that renders into a window, which + // means the display must be 16- or 256-color mode. If so, let's bail. + D3DEnum_DriverInfo* pDriverInfo; + D3DEnum_DeviceInfo* pDeviceInfo; + D3DEnum_GetSelectedDriver( &pDriverInfo, &pDeviceInfo ); + if( FALSE == pDeviceInfo->bWindowed ) + { + Cleanup3DEnvironment(); + DisplayFrameworkError( D3DFWERR_INVALIDMODE, MSGERR_APPMUSTEXIT ); + return 0; + } + + // Initialize the 3D environment for the app + if( FAILED( hr = Initialize3DEnvironment( g_hWnd ) ) ) + { + Cleanup3DEnvironment(); + DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT ); + return 0; + } + + g_bReady = TRUE; + + return 1; +} + +void PumpMessages (void) +{ + MSG msg; + while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) + { + // Exit App ?!? + if (msg.message == WM_QUIT) + { + return; + } + + if (!TranslateAccelerator (g_hWnd, g_hAccel, &msg)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + } +} + + + + +//----------------------------------------------------------------------------- +// Name: WndProc() +// Desc: This is the basic Windows-programming function that processes +// Windows messages. We need to handle window movement, painting, +// and destruction. +//----------------------------------------------------------------------------- +LRESULT CALLBACK WndProc( HWND g_hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + switch( uMsg ) + { + case WM_PAINT: + if( g_pFramework ) + { + // If we are paused, and in fullscreen mode, give the dialogs + // a GDI surface to draw on. + if( !g_bReady && !g_bWindowed) + g_pFramework->FlipToGDISurface( TRUE ); + else // Simply repaint the frame's contents + g_pFramework->ShowFrame(); + } + break; + + case WM_MOVE: + if( g_bActive && g_bReady && g_bWindowed ) + { + GetWindowRect( g_hWnd, &g_rcWindow ); + g_pFramework->Move( (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam) ); + } + break; + + case WM_SIZE: + // Check to see if we are losing our window... + if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam ) + g_bActive = FALSE; + else g_bActive = TRUE; + + // A new window size will require a new viewport and backbuffer + // size, so the 3D structures must be changed accordingly. + if( g_bActive && g_bReady && g_bWindowed ) + { + g_bReady = FALSE; + GetWindowRect( g_hWnd, &g_rcWindow ); + Change3DEnvironment( g_hWnd ); + g_bReady = TRUE; + } + break; + + case WM_GETMINMAXINFO: + ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100; + ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100; + break; + + case WM_SETCURSOR: + if( g_bActive && g_bReady && (!g_bWindowed) ) + { + SetCursor(NULL); + return TRUE; + } + break; + + case WM_CLOSE: + DestroyWindow( g_hWnd ); + return 0; + + case WM_DESTROY: + Cleanup3DEnvironment(); + PostQuitMessage(0); + return 0L; + + case WM_ENTERMENULOOP: + AppPause(TRUE); + break; + + case WM_EXITMENULOOP: + AppPause(FALSE); + break; + + case WM_CONTEXTMENU: + { + HMENU hMenu = LoadMenu( 0, MAKEINTRESOURCE(IDR_POPUP) ); + TrackPopupMenuEx( GetSubMenu( hMenu, 0 ), + TPM_VERTICAL, LOWORD(lParam), + HIWORD(lParam), g_hWnd, NULL ); + } + break; + + case WM_COMMAND: + switch( LOWORD(wParam) ) + { + case SC_MONITORPOWER: + // Prevent potential crashes when the monitor powers down + return 1; + + case IDM_TOGGLESTART: + g_bFrameMoving = !g_bFrameMoving; + break; + + case IDM_SINGLESTEP: + g_bSingleStep = TRUE; + break; + + case IDM_CHANGEDEVICE: + // Display the driver-selection dialog box. + if( g_bActive && g_bReady ) + { + AppPause(TRUE); + if( g_bWindowed ) + GetWindowRect( g_hWnd, &g_rcWindow ); + + HWND hWnd = g_hWnd; + if( IDOK == D3DEnum_UserDlgSelectDriver( hWnd, g_bWindowed ) ) + { + D3DEnum_DriverInfo* pDriverInfo; + D3DEnum_DeviceInfo* pDeviceInfo; + D3DEnum_GetSelectedDriver( &pDriverInfo, &pDeviceInfo ); + g_bWindowed = pDeviceInfo->bWindowed; + + Change3DEnvironment( g_hWnd ); + } + AppPause(FALSE); + } + return 0; + + case IDM_TOGGLEFULLSCREEN: + // Toggle the fullscreen/window mode + if( g_bActive && g_bReady ) + { + g_bReady = FALSE; + if( g_bWindowed ) + GetWindowRect( g_hWnd, &g_rcWindow ); + g_bWindowed = !g_bWindowed; + Change3DEnvironment( g_hWnd ); + g_bReady = TRUE; + } + return 0; + + case IDM_HELP: + AppPause(TRUE); + DialogBox( (HINSTANCE)GetWindowLong( g_hWnd, GWL_HINSTANCE ), + MAKEINTRESOURCE(IDD_ABOUT), g_hWnd, (DLGPROC)AboutProc ); + AppPause(FALSE); + return 0; + + case IDM_EXIT: + // Recieved key/menu command to exit app + SendMessage( g_hWnd, WM_CLOSE, 0, 0 ); + return 0; + } + break; + } + + return DefWindowProc( g_hWnd, uMsg, wParam, lParam ); +} + + + + +//----------------------------------------------------------------------------- +// Name: AboutProc() +// Desc: Minimal message proc function for the about box +//----------------------------------------------------------------------------- +BOOL CALLBACK AboutProc( HWND g_hWnd, UINT uMsg, WPARAM wParam, LPARAM ) +{ + if( WM_COMMAND == uMsg ) + if( IDOK == LOWORD(wParam) || IDCANCEL == LOWORD(wParam) ) + EndDialog (g_hWnd, TRUE); + + return ( WM_INITDIALOG == uMsg ) ? TRUE : FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Note: From this point on, the code is DirectX specific support for the app. +//----------------------------------------------------------------------------- + + + + +//----------------------------------------------------------------------------- +// Name: AppInitialize() +// Desc: Initializes the sample framework, then calls the app-specific function +// to initialize device specific objects. This code is structured to +// handled any errors that may occur duing initialization +//----------------------------------------------------------------------------- +HRESULT AppInitialize( HWND g_hWnd ) +{ + D3DEnum_DriverInfo* pDriverInfo; + D3DEnum_DeviceInfo* pDeviceInfo; + DWORD dwFrameworkFlags = 0L; + HRESULT hr; + + D3DEnum_GetSelectedDriver( &pDriverInfo, &pDeviceInfo ); + + dwFrameworkFlags |= (!g_bWindowed ? D3DFW_FULLSCREEN : 0L ); + dwFrameworkFlags |= ( g_bAppUseZBuffer ? D3DFW_ZBUFFER : 0L ); + dwFrameworkFlags |= ( g_bAppUseBackBuffer ? D3DFW_BACKBUFFER : 0L ); + + // Initialize the D3D framework + if( SUCCEEDED( hr = g_pFramework->Initialize( g_hWnd, &pDriverInfo->guid, + &pDeviceInfo->guid, &pDeviceInfo->pCurrentMode->ddsd, + dwFrameworkFlags ) ) ) + { + // Let the app run its startup code which creates the 3d scene. + if( SUCCEEDED( hr = App_InitDeviceObjects( g_pFramework->GetD3DDevice(), + g_pFramework->GetViewport() ) ) ) + return S_OK; + else + { + App_DeleteDeviceObjects( g_pFramework->GetD3DDevice(), + g_pFramework->GetViewport() ); + g_pFramework->DestroyObjects(); + } + } + + // If we get here, the first initialization passed failed. If that was with a + // hardware device, try again using a software rasterizer instead. + if( pDeviceInfo->bIsHardware ) + { + // Try again with a software rasterizer + DisplayFrameworkError( hr, MSGWARN_SWITCHTOSOFTWARE ); + D3DEnum_SelectDefaultDriver( D3DENUM_SOFTWAREONLY ); + return AppInitialize( g_hWnd ); + } + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: Initialize3DEnvironment() +// Desc: Called when the app window is initially created, this triggers +// creation of the remaining portion (the 3D stuff) of the app. +//----------------------------------------------------------------------------- +HRESULT Initialize3DEnvironment( HWND g_hWnd ) +{ + HRESULT hr; + + // Initialize the app + if( FAILED( hr = App_OneTimeSceneInit( g_hWnd ) ) ) + return E_FAIL; + + // Create a new CD3DFramework class. This class does all of our D3D + // initialization and manages the common D3D objects. + if( NULL == ( g_pFramework = new CD3DFramework() ) ) + return E_OUTOFMEMORY; + + // Finally, initialize the framework and scene. + return AppInitialize( g_hWnd ); +} + + + + +//----------------------------------------------------------------------------- +// Name: Change3DEnvironment() +// Desc: Handles driver, device, and/or mode changes for the app. +//----------------------------------------------------------------------------- +HRESULT Change3DEnvironment( HWND g_hWnd ) +{ + HRESULT hr; + + // Release all objects that need to be re-created for the new device + App_DeleteDeviceObjects( g_pFramework->GetD3DDevice(), + g_pFramework->GetViewport() ); + + // Release the current framework objects (they will be recreated later on) + if( FAILED( hr = g_pFramework->DestroyObjects() ) ) + { + DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT ); + DestroyWindow( g_hWnd ); + return hr; + } + + // In case we're coming from a fullscreen mode, restore the window size + if( g_bWindowed ) + { + SetWindowPos( g_hWnd, HWND_NOTOPMOST, g_rcWindow.left, g_rcWindow.top, + ( g_rcWindow.right - g_rcWindow.left ), + ( g_rcWindow.bottom - g_rcWindow.top ), SWP_SHOWWINDOW ); + } + + // Inform the framework class of the driver change. It will internally + // re-create valid surfaces, a d3ddevice, and a viewport. + if( FAILED( hr = AppInitialize( g_hWnd ) ) ) + { + DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT ); + DestroyWindow( g_hWnd ); + return hr; + } + + // Trigger the rendering of a frame and return + g_bSingleStep = TRUE; + return S_OK; +} + +FLOAT g_fTime; + +extern "C" HRESULT Win32_start_frame () +{ + // Check the cooperative level before rendering + if( FAILED( g_pFramework->GetDirectDraw()->TestCooperativeLevel() ) ) + return S_OK; + + // Get the current time + g_fTime = GetTickCount() * 0.001f; + + return App_StartFrame( g_pFramework->GetD3DDevice(), + g_pFramework->GetViewport(), + (D3DRECT*)g_pFramework->GetViewportRect() ); +} + +extern "C" HRESULT Win32_end_frame () +{ + // Show the frame rate, etc. + if( g_bShowStats ) + AppShowStats(); + + return App_EndFrame (); +} + +extern "C" HRESULT Win32_flip_screens () +{ + // Show the frame on the primary surface. + if( DDERR_SURFACELOST == g_pFramework->ShowFrame() ) + { + g_pFramework->RestoreSurfaces(); + App_RestoreSurfaces(); + } + return S_OK; +} + + + +//----------------------------------------------------------------------------- +// Name: Cleanup3DEnvironment() +// Desc: Cleanup scene objects +//----------------------------------------------------------------------------- +VOID Cleanup3DEnvironment() +{ + if( g_pFramework ) + { + App_FinalCleanup( g_pFramework->GetD3DDevice(), + g_pFramework->GetViewport() ); + + SAFE_DELETE( g_pFramework ); + } + g_bActive = FALSE; + g_bReady = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: AppPause() +// Desc: Called in to toggle the pause state of the app. This function +// brings the GDI surface to the front of the display, so drawing +// output like message boxes and menus may be displayed. +//----------------------------------------------------------------------------- +VOID AppPause( BOOL bPause ) +{ + static DWORD dwAppPausedCount = 0L; + + if( bPause && 0 == dwAppPausedCount ) + if( g_pFramework ) + g_pFramework->FlipToGDISurface( TRUE ); + + dwAppPausedCount += ( bPause ? +1 : -1 ); + + g_bReady = (0==dwAppPausedCount); +} + + + + +//----------------------------------------------------------------------------- +// Name: AppShowStats() +// Desc: Shows frame rate and dimensions of the rendering device. Note: a +// "real" app wouldn't query the surface dimensions each frame. +//----------------------------------------------------------------------------- +VOID AppShowStats() +{ + static FLOAT fFPS = 0.0f; + static FLOAT fLastTime = 0.0f; + static DWORD dwFrames = 0L; + + // Keep track of the time lapse and frame count + FLOAT fTime = GetTickCount() * 0.001f; // Get current time in seconds + ++dwFrames; + + // Update the frame rate once per second + if( fTime - fLastTime > 1.0f ) + { + fFPS = dwFrames / (fTime - fLastTime); + fLastTime = fTime; + dwFrames = 0L; + } + + // Get dimensions of the render surface + DDSURFACEDESC2 ddsd; + ddsd.dwSize = sizeof(DDSURFACEDESC2); + g_pFramework->GetRenderSurface()->GetSurfaceDesc(&ddsd); + + // Setup the text buffer to write out + CHAR buffer[80]; + sprintf( buffer, "%7.02f fps (%dx%dx%d)", fFPS, ddsd.dwWidth, + ddsd.dwHeight, ddsd.ddpfPixelFormat.dwRGBBitCount ); + AppOutputText( g_pFramework->GetD3DDevice(), 0, 0, buffer ); +} + + + + +//----------------------------------------------------------------------------- +// Name: AppOutputText() +// Desc: Draws text on the window. +//----------------------------------------------------------------------------- +VOID AppOutputText( LPDIRECT3DDEVICE3 pd3dDevice, DWORD x, DWORD y, CHAR* str ) +{ + LPDIRECTDRAWSURFACE4 pddsRenderSurface; + if( FAILED( pd3dDevice->GetRenderTarget( &pddsRenderSurface ) ) ) + return; + + // Get a DC for the surface. Then, write out the buffer + HDC hDC; + if( SUCCEEDED( pddsRenderSurface->GetDC(&hDC) ) ) + { + SetTextColor( hDC, RGB(255,255,0) ); + SetBkMode( hDC, TRANSPARENT ); + ExtTextOut( hDC, x, y, 0, NULL, str, strlen(str), NULL ); + + pddsRenderSurface->ReleaseDC(hDC); + } + pddsRenderSurface->Release(); +} + + + + +//----------------------------------------------------------------------------- +// Name: DisplayFrameworkError() +// Desc: Displays error messages in a message box +//----------------------------------------------------------------------------- +VOID DisplayFrameworkError( HRESULT hr, APPMSGTYPE errType ) +{ + CHAR strMsg[512]; + + switch( hr ) + { + case D3DENUMERR_NOCOMPATIBLEDEVICES: + strcpy( strMsg, TEXT("Could not find any compatible Direct3D\n" + "devices.") ); + break; + case D3DENUMERR_SUGGESTREFRAST: + strcpy( strMsg, TEXT("Could not find any compatible devices.\n\n" + "Try enabling the reference rasterizer using\n" + "EnableRefRast.reg.") ); + break; + case D3DENUMERR_ENUMERATIONFAILED: + strcpy( strMsg, TEXT("Enumeration failed. Your system may be in an\n" + "unstable state and need to be rebooted") ); + break; + case D3DFWERR_INITIALIZATIONFAILED: + strcpy( strMsg, TEXT("Generic initialization error.\n\nEnable " + "debug output for detailed information.") ); + break; + case D3DFWERR_NODIRECTDRAW: + strcpy( strMsg, TEXT("No DirectDraw") ); + break; + case D3DFWERR_NODIRECT3D: + strcpy( strMsg, TEXT("No Direct3D") ); + break; + case D3DFWERR_INVALIDMODE: + strcpy( strMsg, TEXT("This sample requires a 16-bit (or higher) " + "display mode\nto run in a window.\n\nPlease switch " + "your desktop settings accordingly.") ); + break; + case D3DFWERR_COULDNTSETCOOPLEVEL: + strcpy( strMsg, TEXT("Could not set Cooperative Level") ); + break; + case D3DFWERR_NO3DDEVICE: + strcpy( strMsg, TEXT("No 3D Device") ); + break; + case D3DFWERR_NOZBUFFER: + strcpy( strMsg, TEXT("No ZBuffer") ); + break; + case D3DFWERR_NOVIEWPORT: + strcpy( strMsg, TEXT("No Viewport") ); + break; + case D3DFWERR_NOPRIMARY: + strcpy( strMsg, TEXT("No primary") ); + break; + case D3DFWERR_NOCLIPPER: + strcpy( strMsg, TEXT("No Clipper") ); + break; + case D3DFWERR_BADDISPLAYMODE: + strcpy( strMsg, TEXT("Bad display mode") ); + break; + case D3DFWERR_NOBACKBUFFER: + strcpy( strMsg, TEXT("No backbuffer") ); + break; + case D3DFWERR_NONZEROREFCOUNT: + strcpy( strMsg, TEXT("Nonzerorefcount") ); + break; + case D3DFWERR_NORENDERTARGET: + strcpy( strMsg, TEXT("No render target") ); + break; + case E_OUTOFMEMORY: + strcpy( strMsg, TEXT("Not enough memory!") ); + break; + case DDERR_OUTOFVIDEOMEMORY: + strcpy( strMsg, TEXT("There was insufficient video memory " + "to use the\nhardware device.") ); + break; + default: + strcpy( strMsg, TEXT("Generic application error.\n\nEnable " + "debug output for detailed information.") ); + } + + if( MSGERR_APPMUSTEXIT == errType ) + { + strcat( strMsg, TEXT("\n\nThis sample will now exit.") ); + MessageBox( NULL, strMsg, g_strAppTitle, MB_ICONERROR|MB_OK ); + } + else + { + if( MSGWARN_SWITCHTOSOFTWARE == errType ) + strcat( strMsg, TEXT("\n\nSwitching to software rasterizer.") ); + MessageBox( NULL, strMsg, g_strAppTitle, MB_ICONWARNING|MB_OK ); + } +} diff --git a/arch/win32/winnet.c b/arch/win32/winnet.c new file mode 100644 index 00000000..f060a5cb --- /dev/null +++ b/arch/win32/winnet.c @@ -0,0 +1,353 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +#include +#include +#include +#include + +#include "types.h" +#include "config.h" +#include "args.h" + +#include "ipx_drv.h" + +extern struct ipx_driver ipx_win; + +#define MAX_IPX_DATA 576 + +int ipx_fd; +ipx_socket_t ipx_socket_data; +ubyte ipx_installed=0; +ushort ipx_socket = 0; +uint ipx_network = 0; +ubyte ipx_MyAddress[10]; +int ipx_packetnum = 0; /* Sequence number */ + +/* User defined routing stuff */ +typedef struct user_address { + ubyte network[4]; + ubyte node[6]; + ubyte address[6]; +} user_address; +#define MAX_USERS 64 +int Ipx_num_users = 0; +user_address Ipx_users[MAX_USERS]; + +#define MAX_NETWORKS 64 +int Ipx_num_networks = 0; +uint Ipx_networks[MAX_NETWORKS]; + +void ipx_close(void); + +int ipx_general_PacketReady(ipx_socket_t *s) { + fd_set set; + struct timeval tv; + + FD_ZERO(&set); + FD_SET(s->fd, &set); + tv.tv_sec = tv.tv_usec = 0; + if (select(FD_SETSIZE, &set, NULL, NULL, &tv) > 0) + return 1; + else + return 0; +} + +struct ipx_driver *driver = &ipx_win; + +ubyte * ipx_get_my_server_address() +{ + return (ubyte *)&ipx_network; +} + +ubyte * ipx_get_my_local_address() +{ + return (ubyte *)(ipx_MyAddress + 4); +} + +//--------------------------------------------------------------- +// Initializes all IPX internals. +// If socket_number==0, then opens next available socket. +// Returns: 0 if successful. +// -1 if socket already open. +// -2 if socket table full. +// -3 if IPX not installed. +// -4 if couldn't allocate low dos memory +// -5 if error with getting internetwork address +int ipx_init( int socket_number, int show_address ) +{ + int i; + + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD(2, 0); + if (WSAStartup( wVersionRequested, &wsaData)) + { + return -1; + } + +#if 0 + if ( LOBYTE( wsaData.wVersion ) != 2 || + HIBYTE( wsaData.wVersion ) != 0 ) { + /* We couldn't find a usable WinSock DLL. */ + WSACleanup( ); + return -2; + } +#endif + + printf("Using real IPX for network games\n"); + driver = &ipx_win; + if ((i = FindArg("-ipxnetwork")) && Args[i + 1]) { + unsigned long n = strtol(Args[i + 1], NULL, 16); + ipx_MyAddress[0] = (unsigned char)n >> 24; ipx_MyAddress[1] = (unsigned char)(n >> 16) & 255; + ipx_MyAddress[2] = (unsigned char)(n >> 8) & 255; ipx_MyAddress[3] = (unsigned char)n & 255; + printf("IPX: Using network %08x\n", (int) n); + } + if (driver->OpenSocket(&ipx_socket_data, socket_number)) { + return -3; + } + driver->GetMyAddress(); + memcpy(&ipx_network, ipx_MyAddress, 4); + Ipx_num_networks = 0; + memcpy( &Ipx_networks[Ipx_num_networks++], &ipx_network, 4 ); + ipx_installed = 1; + atexit(ipx_close); + printf("ipx succesfully installed\n"); + return 0; +} + +void ipx_close() +{ + if (ipx_installed) { + WSACleanup(); + driver->CloseSocket(&ipx_socket_data); + } + ipx_installed = 0; +} + +int ipx_get_packet_data( ubyte * data ) +{ + struct ipx_recv_data rd; + char buf[MAX_IPX_DATA]; + uint best_id = 0; + uint pkt_num; + int size; + int best_size = 0; + + // Like the original, only take latest packet, throw away rest + while (driver->PacketReady(&ipx_socket_data)) { + if ((size = + driver->ReceivePacket(&ipx_socket_data, buf, + sizeof(buf), &rd)) > 4) { + if (!memcmp(rd.src_network, ipx_MyAddress, 10)) + continue; /* don't get own pkts */ + pkt_num = *(uint *)buf; + if (pkt_num >= best_id) { + memcpy(data, buf + 4, size - 4); + best_id = pkt_num; + best_size = size - 4; + } + } + } + return best_size; +} + +void ipx_send_packet_data( ubyte * data, int datasize, ubyte *network, ubyte *address, ubyte *immediate_address ) +{ + u_char buf[MAX_IPX_DATA]; + IPXPacket_t ipx_header; + + memcpy(ipx_header.Destination.Network, network, 4); + memcpy(ipx_header.Destination.Node, immediate_address, 6); + *(u_short *)ipx_header.Destination.Socket = htons(ipx_socket_data.socket); + ipx_header.PacketType = 4; /* Packet Exchange */ + *(uint *)buf = ipx_packetnum++; + memcpy(buf + 4, data, datasize); + driver->SendPacket(&ipx_socket_data, &ipx_header, buf, datasize + 4); +} + +void ipx_get_local_target( ubyte * server, ubyte * node, ubyte * local_target ) +{ + // let's hope Linux knows how to route it + memcpy( local_target, node, 6 ); +} + +void ipx_send_broadcast_packet_data( ubyte * data, int datasize ) +{ + int i, j; + ubyte broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + ubyte local_address[6]; + + // Set to all networks besides mine + for (i=0; iCloseSocket(&ipx_socket_data); + if (driver->OpenSocket(&ipx_socket_data, socket_number)) { + return -3; + } + return 0; +} + +void ipx_read_user_file(char * filename) +{ + FILE * fp; + user_address tmp; + char temp_line[132], *p1; + int n, ln=0, x; + + if (!filename) return; + + Ipx_num_users = 0; + + fp = fopen( filename, "rt" ); + if ( !fp ) return; + + printf( "Broadcast Users:\n" ); + + while (fgets(temp_line, 132, fp)) { + ln++; + p1 = strchr(temp_line,'\n'); if (p1) *p1 = '\0'; + p1 = strchr(temp_line,';'); if (p1) *p1 = '\0'; +#if 1 // adb: replaced sscanf(..., "%2x...", (char *)...) with better, but longer code + if (strlen(temp_line) >= 21 && temp_line[8] == '/') { + for (n = 0; n < 4; n++) { + if (sscanf(temp_line + n * 2, "%2x", &x) != 1) + break; + tmp.network[n] = x; + } + if (n != 4) + continue; + for (n = 0; n < 6; n++) { + if (sscanf(temp_line + 9 + n * 2, "%2x", &x) != 1) + break; + tmp.node[n] = x; + } + if (n != 6) + continue; + } else + continue; +#else + n = sscanf( temp_line, "%2x%2x%2x%2x/%2x%2x%2x%2x%2x%2x", &tmp.network[0], &tmp.network[1], &tmp.network[2], &tmp.network[3], &tmp.node[0], &tmp.node[1], &tmp.node[2],&tmp.node[3], &tmp.node[4], &tmp.node[5] ); + if ( n != 10 ) continue; +#endif + if ( Ipx_num_users < MAX_USERS ) { + ubyte * ipx_real_buffer = (ubyte *)&tmp; + ipx_get_local_target( tmp.network, tmp.node, tmp.address ); + Ipx_users[Ipx_num_users++] = tmp; + printf( "%02X%02X%02X%02X/", ipx_real_buffer[0],ipx_real_buffer[1],ipx_real_buffer[2],ipx_real_buffer[3] ); + printf( "%02X%02X%02X%02X%02X%02X\n", ipx_real_buffer[4],ipx_real_buffer[5],ipx_real_buffer[6],ipx_real_buffer[7],ipx_real_buffer[8],ipx_real_buffer[9] ); + } else { + printf( "Too many addresses in %s! (Limit of %d)\n", filename, MAX_USERS ); + fclose(fp); + return; + } + } + fclose(fp); +} + + +void ipx_read_network_file(char * filename) +{ + FILE * fp; + user_address tmp; + char temp_line[132], *p1; + int i, n, ln=0, x; + + if (!filename) return; + + fp = fopen( filename, "rt" ); + if ( !fp ) return; + + printf( "Using Networks:\n" ); + for (i=0; i= 8) { + for (n = 0; n < 4; n++) { + if (sscanf(temp_line + n * 2, "%2x", &x) != 1) + break; + tmp.network[n] = x; + } + if (n != 4) + continue; + } else + continue; +#else + n = sscanf( temp_line, "%2x%2x%2x%2x", &tmp.network[0], &tmp.network[1], &tmp.network[2], &tmp.network[3] ); + if ( n != 4 ) continue; +#endif + if ( Ipx_num_networks < MAX_NETWORKS ) { + int j; + for (j=0; j= Ipx_num_networks ) { + memcpy( &Ipx_networks[Ipx_num_networks++], tmp.network, 4 ); + printf(" %02x%02x%02x%02x\n", tmp.network[0], tmp.network[1], tmp.network[2], tmp.network[3] ); + } + } else { + printf( "Too many networks in %s! (Limit of %d)\n", filename, MAX_NETWORKS ); + fclose(fp); + return; + } + } + fclose(fp); +} diff --git a/autogen.sh b/autogen.sh new file mode 100644 index 00000000..daf094af --- /dev/null +++ b/autogen.sh @@ -0,0 +1,5 @@ +#!/bin/sh +aclocal +automake --add-missing +autoconf +./configure "$@" diff --git a/cfile/Makefile.am b/cfile/Makefile.am new file mode 100644 index 00000000..e1e0391f --- /dev/null +++ b/cfile/Makefile.am @@ -0,0 +1,4 @@ +noinst_LIBRARIES = libcfile.a +INCLUDES = -I $(top_srcdir)/includes + +libcfile_a_SOURCES = cfile.c diff --git a/cfile/Makefile.in b/cfile/Makefile.in new file mode 100644 index 00000000..3c2d40dd --- /dev/null +++ b/cfile/Makefile.in @@ -0,0 +1,299 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +CFLAGS = @CFLAGS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +NASM = @NASM@ +NASMFLAGS = @NASMFLAGS@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_LIBS = @SDL_LIBS@ +VERSION = @VERSION@ + +noinst_LIBRARIES = libcfile.a +INCLUDES = -I $(top_srcdir)/includes + +libcfile_a_SOURCES = cfile.c +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../conf.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +libcfile_a_LIBADD = +libcfile_a_OBJECTS = cfile.o +AR = ar +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +DEP_FILES = .deps/cfile.P +SOURCES = $(libcfile_a_SOURCES) +OBJECTS = $(libcfile_a_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu cfile/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +libcfile.a: $(libcfile_a_OBJECTS) $(libcfile_a_DEPENDENCIES) + -rm -f libcfile.a + $(AR) cru libcfile.a $(libcfile_a_OBJECTS) $(libcfile_a_LIBADD) + $(RANLIB) libcfile.a + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = cfile + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu cfile/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile $(LIBRARIES) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ + mostlyclean-tags mostlyclean-depend mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \ + clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-noinstLIBRARIES distclean-compile \ + distclean-tags distclean-depend distclean-generic \ + clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cfile/cfile.c b/cfile/cfile.c new file mode 100644 index 00000000..3f59cf34 --- /dev/null +++ b/cfile/cfile.c @@ -0,0 +1,480 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#include +#include +#include + +#include "pstypes.h" +#include "u_mem.h" +#include "strutil.h" +#include "d_io.h" +#include "error.h" +#include "cfile.h" +#include "byteswap.h" + +typedef struct hogfile { + char name[13]; + int offset; + int length; +} hogfile; + +#define MAX_HOGFILES 300 + +hogfile HogFiles[MAX_HOGFILES]; +char Hogfile_initialized = 0; +int Num_hogfiles = 0; + +hogfile AltHogFiles[MAX_HOGFILES]; +char AltHogfile_initialized = 0; +int AltNum_hogfiles = 0; +char HogFilename[64]; +char AltHogFilename[64]; + +char AltHogDir[64]; +char AltHogdir_initialized = 0; + +// routine to take a DOS path and turn it into a macintosh +// pathname. This routine is based on the fact that we should +// see a \ character in the dos path. The sequence .\ a tthe +// beginning of a path is turned into a : + +#ifdef MACINTOSH +void macify_dospath(char *dos_path, char *mac_path) +{ + char *p; + + if (!strncmp(dos_path, ".\\", 2)) { + strcpy(mac_path, ":"); + strcat(mac_path, &(dos_path[2]) ); + } else + strcpy(mac_path, dos_path); + + while ( (p = strchr(mac_path, '\\')) != NULL) + *p = ':'; + +} +#endif + +void cfile_use_alternate_hogdir( char * path ) +{ + if ( path ) { + strcpy( AltHogDir, path ); + AltHogdir_initialized = 1; + } else { + AltHogdir_initialized = 0; + } +} + +//in case no one installs one +int default_error_counter=0; + +//ptr to counter of how many critical errors +int *critical_error_counter_ptr=&default_error_counter; + +//tell cfile about your critical error counter +void cfile_set_critical_error_counter_ptr(int *ptr) +{ + critical_error_counter_ptr = ptr; + +} + + +FILE * cfile_get_filehandle( char * filename, char * mode ) +{ + FILE * fp; + char temp[128]; + + *critical_error_counter_ptr = 0; + fp = fopen( filename, mode ); + if ( fp && *critical_error_counter_ptr ) { + fclose(fp); + fp = NULL; + } + if ( (fp==NULL) && (AltHogdir_initialized) ) { + strcpy( temp, AltHogDir ); + strcat( temp, filename ); + *critical_error_counter_ptr = 0; + fp = fopen( temp, mode ); + if ( fp && *critical_error_counter_ptr ) { + fclose(fp); + fp = NULL; + } + } + return fp; +} + +//returns 1 if file loaded with no errors +int cfile_init_hogfile(char *fname, hogfile * hog_files, int * nfiles ) +{ + char id[4]; + FILE * fp; + int i, len; + + *nfiles = 0; + + fp = cfile_get_filehandle( fname, "rb" ); + if ( fp == NULL ) return 0; + + fread( id, 3, 1, fp ); + if ( strncmp( id, "DHF", 3 ) ) { + fclose(fp); + return 0; + } + + while( 1 ) + { + if ( *nfiles >= MAX_HOGFILES ) { + fclose(fp); + Error( "HOGFILE is limited to %d files.\n", MAX_HOGFILES ); + } + i = fread( hog_files[*nfiles].name, 13, 1, fp ); + if ( i != 1 ) { //eof here is ok + fclose(fp); + return 1; + } + i = fread( &len, 4, 1, fp ); + if ( i != 1 ) { + fclose(fp); + return 0; + } + hog_files[*nfiles].length = INTEL_INT(len); + hog_files[*nfiles].offset = ftell( fp ); + *nfiles = (*nfiles) + 1; + // Skip over + i = fseek( fp, INTEL_INT(len), SEEK_CUR ); + } +} + +//Specify the name of the hogfile. Returns 1 if hogfile found & had files +int cfile_init(char *hogname) +{ + #ifdef MACINTOSH + char mac_path[255]; + + macify_dospath(hogname, mac_path); + #endif + + Assert(Hogfile_initialized == 0); + + #ifndef MACINTOSH + if (cfile_init_hogfile(hogname, HogFiles, &Num_hogfiles )) { + strcpy( HogFilename, hogname ); + #else + if (cfile_init_hogfile(mac_path, HogFiles, &Num_hogfiles )) { + strcpy( HogFilename, mac_path ); + #endif + Hogfile_initialized = 1; + return 1; + } + else + return 0; //not loaded! +} + + +FILE * cfile_find_libfile(char * name, int * length) +{ + FILE * fp; + int i; + + if ( AltHogfile_initialized ) { + for (i=0; i 0); + } else { + AltHogfile_initialized = 0; + return 1; + } +} + +int cfexist( char * filename ) +{ + int length; + FILE *fp; + + + if (filename[0] != '\x01') + fp = cfile_get_filehandle( filename, "rb" ); // Check for non-hog file first... + else { + fp = NULL; //don't look in dir, only in hogfile + filename++; + } + + if ( fp ) { + fclose(fp); + return 1; + } + + fp = cfile_find_libfile(filename, &length ); + if ( fp ) { + fclose(fp); + return 2; // file found in hog + } + + return 0; // Couldn't find it. +} + + +CFILE * cfopen(char * filename, char * mode ) +{ + int length; + FILE * fp; + CFILE *cfile; + + if (stricmp( mode, "rb")) { + Error( "cfiles can only be opened with mode==rb\n" ); + } + + if (filename[0] != '\x01') { + #ifdef MACINTOSH + char mac_path[255]; + + macify_dospath(filename, mac_path); + fp = cfile_get_filehandle( mac_path, mode); + #else + fp = cfile_get_filehandle( filename, mode ); // Check for non-hog file first... + #endif + } else { + fp = NULL; //don't look in dir, only in hogfile + filename++; + } + + if ( !fp ) { + fp = cfile_find_libfile(filename, &length ); + if ( !fp ) + return NULL; // No file found + cfile = d_malloc ( sizeof(CFILE) ); + if ( cfile == NULL ) { + fclose(fp); + return NULL; + } + cfile->file = fp; + cfile->size = length; + cfile->lib_offset = ftell( fp ); + cfile->raw_position = 0; + return cfile; + } else { + cfile = d_malloc ( sizeof(CFILE) ); + if ( cfile == NULL ) { + fclose(fp); + return NULL; + } + cfile->file = fp; + cfile->size = filelength( fileno(fp) ); + cfile->lib_offset = 0; + cfile->raw_position = 0; + return cfile; + } +} + +int cfilelength( CFILE *fp ) +{ + return fp->size; +} + +int cfgetc( CFILE * fp ) +{ + int c; + + if (fp->raw_position >= fp->size ) return EOF; + + c = getc( fp->file ); + if (c!=EOF) + fp->raw_position++; + +// Assert( fp->raw_position==(ftell(fp->file)-fp->lib_offset) ); + + return c; +} + +char * cfgets( char * buf, size_t n, CFILE * fp ) +{ + char * t = buf; + int i; + int c; + + for (i=0; iraw_position >= fp->size ) { + *buf = 0; + return NULL; + } + c = fgetc( fp->file ); + fp->raw_position++; +#ifdef MACINTOSH + if (c == 13) { + int c1; + + c1 = fgetc( fp->file ); + fseek( fp->file, -1, SEEK_CUR); + if ( c1 == 10 ) + continue; + else + break; + } +#endif + } while ( c == 13 ); +#ifdef MACINTOSH // because cr-lf is a bad thing on the mac + if ( c == 13 ) // and anyway -- 0xod is CR on mac, not 0x0a + c = '\n'; +#endif + *buf++ = c; + if ( c=='\n' ) break; + } + *buf++ = 0; + return t; +} + +size_t cfread( void * buf, size_t elsize, size_t nelem, CFILE * fp ) +{ + unsigned int i, size; + + size = elsize * nelem; + if ( size < 1 ) return 0; + + i = fread ( buf, 1, size, fp->file ); + fp->raw_position += i; + return i/elsize; +} + + +int cftell( CFILE *fp ) +{ + return fp->raw_position; +} + +int cfseek( CFILE *fp, long int offset, int where ) +{ + int c, goal_position; + + switch( where ) { + case SEEK_SET: + goal_position = offset; + break; + case SEEK_CUR: + goal_position = fp->raw_position+offset; + break; + case SEEK_END: + goal_position = fp->size+offset; + break; + default: + return 1; + } + c = fseek( fp->file, fp->lib_offset + goal_position, SEEK_SET ); + fp->raw_position = ftell(fp->file)-fp->lib_offset; + return c; +} + +void cfclose( CFILE * fp ) +{ + fclose(fp->file); + d_free(fp); + return; +} + +// routines to read basic data types from CFILE's. Put here to +// simplify mac/pc reading from cfiles. + +int cfile_read_int(CFILE *file) +{ + int i; + + if (cfread( &i, sizeof(i), 1, file) != 1) + Error( "Error reading short in cfile_read_int()" ); + + i = INTEL_INT(i); + return i; +} + +short cfile_read_short(CFILE *file) +{ + short s; + + if (cfread( &s, sizeof(s), 1, file) != 1) + Error( "Error reading short in cfile_read_short()" ); + + s = INTEL_SHORT(s); + return s; +} + +byte cfile_read_byte(CFILE *file) +{ + byte b; + + if (cfread( &b, sizeof(b), 1, file) != 1) + Error( "Error reading byte in cfile_read_byte()" ); + + return b; +} + +#if 0 +fix read_fix(CFILE *file) +{ + fix f; + + if (cfread( &f, sizeof(f), 1, file) != 1) + Error( "Error reading fix in gamesave.c" ); + + f = (fix)INTEL_INT((int)f); + return f; +} + +static void read_vector(vms_vector *v,CFILE *file) +{ + v->x = read_fix(file); + v->y = read_fix(file); + v->z = read_fix(file); +} +#endif + diff --git a/cfile/nocfile.h b/cfile/nocfile.h new file mode 100644 index 00000000..3a537b58 --- /dev/null +++ b/cfile/nocfile.h @@ -0,0 +1,38 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + + +#ifndef _NOCFILE_H +#define _NOCFILE_H + +#include +#include + +#define CFILE FILE + +#define cfopen(file,mode) fopen(file,mode) +#define cfilelength(f) filelength( fileno( f )) +#define cfwrite(buf,elsize,nelem,fp) fwrite(buf,elsize,nelem,fp) +#define cfread(buf,elsize,nelem,fp ) fread(buf,elsize,nelem,fp ) +#define cfclose( cfile ) fclose( cfile ) +#define cfputc(c,fp) fputc(c,fp) +#define cfgetc(fp) fgetc(fp) +#define cfseek(fp,offset,where ) fseek(fp,offset,where ) +#define cftell(fp) ftell(fp) +#define cfgets(buf,n,fp) fgets(buf,n,fp) + +#define CF_READ_MODE "rb" +#define CF_WRITE_MODE "wb" + +#endif diff --git a/conf.h.in b/conf.h.in new file mode 100644 index 00000000..b75dd216 --- /dev/null +++ b/conf.h.in @@ -0,0 +1,35 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define if you need to in order for stat and other things to work. */ +#undef _POSIX_SOURCE + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if you have netipx/ipx.h */ +#undef HAVE_NETIPX_IPX_H + +/* Define if you want an assembler free build */ +#undef NO_ASM + +/* Define if you want a network build */ +#undef NETWORK + +/* Define if you want an OpenGL build */ +#undef OGL + +#define NMONO 1 +#define SDL_AUDIO 1 +#define PIGGY_USE_PAGING 1 +#define NEWDEMO 1 + +#ifdef OGL +# define GLX_VIDEO 1 +# define GII_INPUT 1 +# define GII_XWIN 1 +#else +# define SDL_VIDEO 1 +# define SDL_INPUT 1 +#endif + +#define __ENV_LINUX__ 1 diff --git a/config.guess b/config.guess new file mode 100644 index 00000000..6cb567b8 --- /dev/null +++ b/config.guess @@ -0,0 +1,1087 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999 +# Free Software Foundation, Inc. +# +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Written by Per Bothner . +# The master version of this file is at the FSF in /home/gd/gnu/lib. +# Please send patches to the Autoconf mailing list . +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit system type (host/target name). +# +# Only a few systems have been added to this list; please add others +# (but try to keep the structure clean). +# + +# Use $HOST_CC if defined. $CC may point to a cross-compiler +if test x"$CC_FOR_BUILD" = x; then + if test x"$HOST_CC" != x; then + CC_FOR_BUILD="$HOST_CC" + else + if test x"$CC" != x; then + CC_FOR_BUILD="$CC" + else + CC_FOR_BUILD=cc + fi + fi +fi + + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 8/24/94.) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15 + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + cat <$dummy.s + .globl main + .ent main +main: + .frame \$30,0,\$26,0 + .prologue 0 + .long 0x47e03d80 # implver $0 + lda \$2,259 + .long 0x47e20c21 # amask $2,$1 + srl \$1,8,\$2 + sll \$2,2,\$2 + sll \$0,3,\$0 + addl \$1,\$0,\$0 + addl \$2,\$0,\$0 + ret \$31,(\$26),1 + .end main +EOF + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + ./$dummy + case "$?" in + 7) + UNAME_MACHINE="alpha" + ;; + 15) + UNAME_MACHINE="alphaev5" + ;; + 14) + UNAME_MACHINE="alphaev56" + ;; + 10) + UNAME_MACHINE="alphapca56" + ;; + 16) + UNAME_MACHINE="alphaev6" + ;; + esac + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-cbm-sysv4 + exit 0;; + amiga:NetBSD:*:*) + echo m68k-cbm-netbsd${UNAME_RELEASE} + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + arc64:OpenBSD:*:*) + echo mips64el-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hkmips:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + arm32:NetBSD:*:*) + echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + SR2?01:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + atari*:NetBSD:*:*) + echo m68k-atari-netbsd${UNAME_RELEASE} + exit 0 ;; + atari*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + sun3*:NetBSD:*:*) + echo m68k-sun-netbsd${UNAME_RELEASE} + exit 0 ;; + sun3*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:NetBSD:*:*) + echo m68k-apple-netbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + macppc:NetBSD:*:*) + echo powerpc-apple-netbsd${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \ + -o ${TARGET_BINARY_INTERFACE}x = x ] ; then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i?86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:4) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` + if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=4.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + sed 's/^ //' << EOF >$dummy.c + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + ($CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` + rm -f $dummy.c $dummy + esac + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i?86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + hppa*:OpenBSD:*:*) + echo hppa-unknown-openbsd + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*X-MP:*:*:*) + echo xmp-cray-unicos + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY*T3E:*:*:*) + echo t3e-cray-unicosmk${UNAME_RELEASE} + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + F300:UNIX_System_V:*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + F301:UNIX_System_V:*:*) + echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'` + exit 0 ;; + hp3[0-9][05]:NetBSD:*:*) + echo m68k-hp-netbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + i?86:BSD/386:*:* | i?86:BSD/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + if test -x /usr/bin/objformat; then + if test "elf" = "`/usr/bin/objformat`"; then + echo ${UNAME_MACHINE}-unknown-freebsdelf`echo ${UNAME_RELEASE}|sed -e 's/[-_].*//'` + exit 0 + fi + fi + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + *:NetBSD:*:*) + echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + *:Linux:*:*) + # uname on the ARM produces all sorts of strangeness, and we need to + # filter it out. + case "$UNAME_MACHINE" in + armv*) UNAME_MACHINE=$UNAME_MACHINE ;; + arm* | sa110*) UNAME_MACHINE="arm" ;; + esac + + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + ld_help_string=`cd /; ld --help 2>&1` + ld_supported_emulations=`echo $ld_help_string \ + | sed -ne '/supported emulations:/!d + s/[ ][ ]*/ /g + s/.*supported emulations: *// + s/ .*// + p'` + case "$ld_supported_emulations" in + i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;; + i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;; + sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; + armlinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; + m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; + elf32ppc) + # Determine Lib Version + cat >$dummy.c < +#if defined(__GLIBC__) +extern char __libc_version[]; +extern char __libc_release[]; +#endif +main(argc, argv) + int argc; + char *argv[]; +{ +#if defined(__GLIBC__) + printf("%s %s\n", __libc_version, __libc_release); +#else + printf("unkown\n"); +#endif + return 0; +} +EOF + LIBC="" + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null + if test "$?" = 0 ; then + ./$dummy | grep 1\.99 > /dev/null + if test "$?" = 0 ; then + LIBC="libc1" + fi + fi + rm -f $dummy.c $dummy + echo powerpc-unknown-linux-gnu${LIBC} ; exit 0 ;; + esac + + if test "${UNAME_MACHINE}" = "alpha" ; then + sed 's/^ //' <$dummy.s + .globl main + .ent main + main: + .frame \$30,0,\$26,0 + .prologue 0 + .long 0x47e03d80 # implver $0 + lda \$2,259 + .long 0x47e20c21 # amask $2,$1 + srl \$1,8,\$2 + sll \$2,2,\$2 + sll \$0,3,\$0 + addl \$1,\$0,\$0 + addl \$2,\$0,\$0 + ret \$31,(\$26),1 + .end main +EOF + LIBC="" + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + ./$dummy + case "$?" in + 7) + UNAME_MACHINE="alpha" + ;; + 15) + UNAME_MACHINE="alphaev5" + ;; + 14) + UNAME_MACHINE="alphaev56" + ;; + 10) + UNAME_MACHINE="alphapca56" + ;; + 16) + UNAME_MACHINE="alphaev6" + ;; + esac + + objdump --private-headers $dummy | \ + grep ld.so.1 > /dev/null + if test "$?" = 0 ; then + LIBC="libc1" + fi + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0 + elif test "${UNAME_MACHINE}" = "mips" ; then + cat >$dummy.c </dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + else + # Either a pre-BFD a.out linker (linux-gnuoldld) + # or one that does not give us useful --help. + # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. + # If ld does not provide *any* "supported emulations:" + # that means it is gnuoldld. + echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:" + test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 + + case "${UNAME_MACHINE}" in + i?86) + VENDOR=pc; + ;; + *) + VENDOR=unknown; + ;; + esac + # Determine whether the default compiler is a.out or elf + cat >$dummy.c < +#ifdef __cplusplus + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif +#ifdef __ELF__ +# ifdef __GLIBC__ +# if __GLIBC__ >= 2 + printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +#else + printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); +#endif + return 0; +} +EOF + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + fi ;; +# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions +# are messed up and put the nodename in both sysname and nodename. + i?86:DYNIX/ptx:4*:*) + echo i386-sequent-sysv4 + exit 0 ;; + i?86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*) + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} + fi + exit 0 ;; + i?86:*:5:7*) + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) && UNAME_MACHINE=i586 + (/bin/uname -X|egrep '^Machine.*Pent.*II' >/dev/null) && UNAME_MACHINE=i686 + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) && UNAME_MACHINE=i585 + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}${UNAME_VERSION}-sysv${UNAME_RELEASE} + exit 0 ;; + i?86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + pc:*:*:*) + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:*:6*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +#if !defined (ultrix) + printf ("vax-dec-bsd\n"); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0 +rm -f $dummy.c $dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +#echo '(Unable to guess system type)' 1>&2 + +exit 1 diff --git a/config.sub b/config.sub new file mode 100644 index 00000000..2436b453 --- /dev/null +++ b/config.sub @@ -0,0 +1,1215 @@ +#! /bin/sh +# Configuration validation subroutine script, version 1.1. +# Copyright (C) 1991, 92-97, 1998, 1999 Free Software Foundation, Inc. +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +if [ x$1 = x ] +then + echo Configuration name missing. 1>&2 + echo "Usage: $0 CPU-MFR-OPSYS" 1>&2 + echo "or $0 ALIAS" 1>&2 + echo where ALIAS is a recognized configuration type. 1>&2 + exit 1 +fi + +# First pass through any local machine types. +case $1 in + *local*) + echo $1 + exit 0 + ;; + *) + ;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + linux-gnu*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=vxworks + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ + | arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \ + | 580 | i960 | h8300 \ + | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \ + | alpha | alphaev[4-7] | alphaev56 | alphapca5[67] \ + | we32k | ns16k | clipper | i370 | sh | powerpc | powerpcle \ + | 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \ + | mips64orion | mips64orionel | mipstx39 | mipstx39el \ + | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ + | mips64vr5000 | miprs64vr5000el \ + | sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \ + | thumb | d10v) + basic_machine=$basic_machine-unknown + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i[34567]86) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \ + | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ + | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \ + | xmp-* | ymp-* \ + | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* | hppa2.0n-* \ + | alpha-* | alphaev[4-7]-* | alphaev56-* | alphapca5[67]-* \ + | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ + | clipper-* | orion-* \ + | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ + | sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \ + | mips64el-* | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \ + | mipstx39-* | mipstx39el-* \ + | f301-* | armv*-* | t3e-* \ + | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ + | thumb-* | v850-* | d30v-* | tic30-* | c30-* ) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-cbm + ;; + amigaos | amigados) + basic_machine=m68k-cbm + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-cbm + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | ymp) + basic_machine=ymp-cray + os=-unicos + ;; + cray2) + basic_machine=cray2-cray + os=-unicos + ;; + [ctj]90-cray) + basic_machine=c90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + os=-mvs + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i[34567]86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i[34567]86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i[34567]86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i[34567]86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + i386-go32 | go32) + basic_machine=i386-unknown + os=-go32 + ;; + i386-mingw32 | mingw32) + basic_machine=i386-unknown + os=-mingw32 + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | *MiNT) + basic_machine=m68k-atari + os=-mint + ;; + mipsel*-linux*) + basic_machine=mipsel-unknown + os=-linux-gnu + ;; + mips*-linux*) + basic_machine=mips-unknown + os=-linux-gnu + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + msdos) + basic_machine=i386-unknown + os=-msdos + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-corel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + np1) + basic_machine=np1-gould + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexen) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexen-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=rs6000-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=t3e-cray + os=-unicos + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xmp) + basic_machine=xmp-cray + os=-unicos + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + mips) + if [ x$os = x-linux-gnu ]; then + basic_machine=mips-unknown + else + basic_machine=mips-mips + fi + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sparc | sparcv9) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -openstep* | -oskit*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -ns2 ) + os=-nextstep2 + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -*MiNT) + os=-mint + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-corel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f301-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -*MiNT) + vendor=atari + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os diff --git a/configure b/configure new file mode 100644 index 00000000..02c4ae72 --- /dev/null +++ b/configure @@ -0,0 +1,2285 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer" +ac_help="$ac_help + --without-assembler Do not use assembler optimization " +ac_help="$ac_help + --without-network Do not build network/serial support " +ac_help="$ac_help + --with-opengl Build OpenGL support " + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=main/game.c + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + + + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:569: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 +echo "configure:622: checking whether build environment is sane" >&5 +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "$*" != "X $srcdir/configure conftestfile" \ + && test "$*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { echo "configure: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" 1>&2; exit 1; } + fi + + test "$2" = conftestfile + ) +then + # Ok. + : +else + { echo "configure: error: newly created file is older than distributed files! +Check your system clock" 1>&2; exit 1; } +fi +rm -f conftest* +echo "$ac_t""yes" 1>&6 +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:679: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +PACKAGE=d2x + +VERSION=0.0.8 + +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } +fi +cat >> confdefs.h <> confdefs.h <&6 +echo "configure:725: checking for working aclocal" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (aclocal --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL=aclocal + echo "$ac_t""found" 1>&6 +else + ACLOCAL="$missing_dir/missing aclocal" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 +echo "configure:738: checking for working autoconf" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoconf --version) < /dev/null > /dev/null 2>&1; then + AUTOCONF=autoconf + echo "$ac_t""found" 1>&6 +else + AUTOCONF="$missing_dir/missing autoconf" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working automake""... $ac_c" 1>&6 +echo "configure:751: checking for working automake" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (automake --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake + echo "$ac_t""found" 1>&6 +else + AUTOMAKE="$missing_dir/missing automake" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 +echo "configure:764: checking for working autoheader" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoheader --version) < /dev/null > /dev/null 2>&1; then + AUTOHEADER=autoheader + echo "$ac_t""found" 1>&6 +else + AUTOHEADER="$missing_dir/missing autoheader" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 +echo "configure:777: checking for working makeinfo" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (makeinfo --version) < /dev/null > /dev/null 2>&1; then + MAKEINFO=makeinfo + echo "$ac_t""found" 1>&6 +else + MAKEINFO="$missing_dir/missing makeinfo" + echo "$ac_t""missing" 1>&6 +fi + + + +echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 +echo "configure:792: checking whether to enable maintainer-specific portions of Makefiles" >&5 + # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then + enableval="$enable_maintainer_mode" + USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + echo "$ac_t""$USE_MAINTAINER_MODE" 1>&6 + + +if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + MAINT=$MAINTAINER_MODE_TRUE + + + + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:819: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:849: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:900: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:932: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 943 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:948: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:974: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:979: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:1007: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6 +echo "configure:1039: checking for POSIXized ISC" >&5 +if test -d /etc/conf/kconfig.d && + grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 +then + echo "$ac_t""yes" 1>&6 + ISC=yes # If later tests want to check for ISC. + cat >> confdefs.h <<\EOF +#define _POSIX_SOURCE 1 +EOF + + if test "$GCC" = yes; then + CC="$CC -posix" + else + CC="$CC -Xp" + fi +else + echo "$ac_t""no" 1>&6 + ISC= +fi + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1062: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1092: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1143: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:1175: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 1186 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:1191: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:1217: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:1222: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:1250: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1284: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:1312: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1333: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1350: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1367: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:1392: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +#include +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1405: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext < +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:1472: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + + +echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6 +echo "configure:1497: checking for Cygwin environment" >&5 +if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_cygwin=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_cygwin=no +fi +rm -f conftest* +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_cygwin" 1>&6 +CYGWIN= +test "$ac_cv_cygwin" = yes && CYGWIN=yes +echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6 +echo "configure:1530: checking for mingw32 environment" >&5 +if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_mingw32=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_mingw32=no +fi +rm -f conftest* +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_mingw32" 1>&6 +MINGW32= +test "$ac_cv_mingw32" = yes && MINGW32=yes + +CFLAGS="-D_REENTRANT -g -O2 -Wall -pipe" + + +echo $ac_n "checking for SDL_Init in -lSDL""... $ac_c" 1>&6 +echo "configure:1563: checking for SDL_Init in -lSDL" >&5 +ac_lib_var=`echo SDL'_'SDL_Init | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lSDL -ldl -lpthread $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SDL_LIBS="-lSDL" +else + echo "$ac_t""no" 1>&6 +{ echo "configure: error: The SDL" 1>&2; exit 1; } +fi + +for ac_hdr in netipx/ipx.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1607: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1617: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + + +# Check for NASM and network +NO_ASM=0 +NO_NETWORK=0 +# Check whether --with-assembler or --without-assembler was given. +if test "${with_assembler+set}" = set; then + withval="$with_assembler" + if test x$withval = xno; then + NO_ASM=1 + fi +fi + +# Check whether --with-network or --without-network was given. +if test "${with_network+set}" = set; then + withval="$with_network" + if test x$withval = xno; then + NO_NETWORK=1 + fi +fi + + + +# Extract the first word of "nasm", so it can be a program name with args. +set dummy nasm; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1669: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_NASM'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$NASM" in + /*) + ac_cv_path_NASM="$NASM" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_NASM="$NASM" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_NASM="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_NASM" && ac_cv_path_NASM="no" + ;; +esac +fi +NASM="$ac_cv_path_NASM" +if test -n "$NASM"; then + echo "$ac_t""$NASM" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test "$NASM" = "no"; then + NO_ASM=1 +fi +if test "$NO_ASM" = 1; then + cat >> confdefs.h <<\EOF +#define NO_ASM 1 +EOF + + NASMFLAGS="" +else + case $ARCH in + win32) + NASMFLAGS="-f win32" + ;; + *) + NASMFLAGS="-f elf -d__ENV_LINUX__" + ;; + esac +fi +if test "$NO_NETWORK" = 0; then + cat >> confdefs.h <<\EOF +#define NETWORK 1 +EOF + +fi + + +if test "$NO_ASM" != 1; then + USE_ASM_TRUE= + USE_ASM_FALSE='#' +else + USE_ASM_TRUE='#' + USE_ASM_FALSE= +fi + + +# Check for OpenGL +# Check whether --with-opengl or --without-opengl was given. +if test "${with_opengl+set}" = set; then + withval="$with_opengl" + case "${withval}" in + yes) opengl=true ;; + no) opengl=false ;; + *) { echo "configure: error: bad value ${withval} for --with-opengl" 1>&2; exit 1; } ;; + esac +else + opengl=false +fi + + +if test x$opengl = xtrue; then + echo $ac_n "checking for main in -lMesaGL""... $ac_c" 1>&6 +echo "configure:1754: checking for main in -lMesaGL" >&5 +ac_lib_var=`echo MesaGL'_'main | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lMesaGL -L/usr/X11R6/lib -lX11 -lXext -lm $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + OGL_LIBS="-lMesaGL" +else + echo "$ac_t""no" 1>&6 +{ echo "configure: error: MesaGL not found" 1>&2; exit 1; } + opengl=false +fi + + echo $ac_n "checking for main in -lMesaGLU""... $ac_c" 1>&6 +echo "configure:1792: checking for main in -lMesaGLU" >&5 +ac_lib_var=`echo MesaGLU'_'main | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lMesaGLU -lMesaGL -L/usr/X11R6/lib -lX11 -lXext -lm $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + OGL_LIBS="${OGL_LIBS} -lMesaGLU" +else + echo "$ac_t""no" 1>&6 +{ echo "configure: error: MesaGLU not found" 1>&2; exit 1; } + opengl=false +fi + +fi + +if test x$opengl = xtrue; then + cat >> confdefs.h <<\EOF +#define OGL 1 +EOF + +fi + + +if test x$opengl = xtrue; then + USE_OPENGL_TRUE= + USE_OPENGL_FALSE='#' +else + USE_OPENGL_TRUE='#' + USE_OPENGL_FALSE= +fi + + +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + + +#libdir='$(shell pwd)/${top_srcdir}/main' + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile +2d/Makefile +3d/Makefile +maths/Makefile +mem/Makefile +cfile/Makefile +iff/Makefile +texmap/Makefile +misc/Makefile +input/Makefile +input/sdl/Makefile +input/linux/Makefile +input/ggi/Makefile +video/Makefile +sound/Makefile +arch/Makefile +arch/linux/Makefile +arch/sdl/Makefile +main/Makefile + conf.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@PACKAGE@%$PACKAGE%g +s%@VERSION@%$VERSION%g +s%@ACLOCAL@%$ACLOCAL%g +s%@AUTOCONF@%$AUTOCONF%g +s%@AUTOMAKE@%$AUTOMAKE%g +s%@AUTOHEADER@%$AUTOHEADER%g +s%@MAKEINFO@%$MAKEINFO%g +s%@SET_MAKE@%$SET_MAKE%g +s%@MAINTAINER_MODE_TRUE@%$MAINTAINER_MODE_TRUE%g +s%@MAINTAINER_MODE_FALSE@%$MAINTAINER_MODE_FALSE%g +s%@MAINT@%$MAINT%g +s%@CC@%$CC%g +s%@RANLIB@%$RANLIB%g +s%@CPP@%$CPP%g +s%@SDL_LIBS@%$SDL_LIBS%g +s%@NASM@%$NASM%g +s%@USE_ASM_TRUE@%$USE_ASM_TRUE%g +s%@USE_ASM_FALSE@%$USE_ASM_FALSE%g +s%@NASMFLAGS@%$NASMFLAGS%g +s%@USE_OPENGL_TRUE@%$USE_OPENGL_TRUE%g +s%@USE_OPENGL_FALSE@%$USE_OPENGL_FALSE%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + diff --git a/configure.in b/configure.in new file mode 100644 index 00000000..e0c1969c --- /dev/null +++ b/configure.in @@ -0,0 +1,115 @@ +AC_INIT(main/game.c) + +AM_CONFIG_HEADER(conf.h) +AM_INIT_AUTOMAKE(d2x, 0.0.8) + +AM_MAINTAINER_MODE + + +AC_ISC_POSIX +AC_PROG_CC +AC_PROG_RANLIB +AC_STDC_HEADERS + +AC_CYGWIN +AC_MINGW32 + +CFLAGS="-D_REENTRANT -g -O2 -Wall -pipe" +AC_SUBST(CFLAGS) + +AC_CHECK_LIB(SDL, SDL_Init, SDL_LIBS="-lSDL", AC_MSG_ERROR(The SDL, which is required, not found.),-ldl -lpthread) +AC_CHECK_HEADERS(netipx/ipx.h) +AC_SUBST(SDL_LIBS) + +# Check for NASM and network +NO_ASM=0 +NO_NETWORK=0 +AC_ARG_WITH(assembler, + [ --without-assembler Do not use assembler optimization ], + if test x$withval = xno; then + NO_ASM=1 + fi) +AC_ARG_WITH(network, + [ --without-network Do not build network/serial support ], + if test x$withval = xno; then + NO_NETWORK=1 + fi) + + +AC_PATH_PROG(NASM, nasm, no) +if test "$NASM" = "no"; then + NO_ASM=1 +fi +if test "$NO_ASM" = 1; then + AC_DEFINE(NO_ASM) + NASMFLAGS="" +else + case $ARCH in + win32) + NASMFLAGS="-f win32" + ;; + *) + NASMFLAGS="-f elf -d__ENV_LINUX__" + ;; + esac +fi +if test "$NO_NETWORK" = 0; then + AC_DEFINE(NETWORK) +fi +AM_CONDITIONAL(USE_ASM, test "$NO_ASM" != 1) +AC_SUBST(NASMFLAGS) + +# Check for OpenGL +AC_ARG_WITH(opengl, + [ --with-opengl Build OpenGL support ], + [case "${withval}" in + yes) opengl=true ;; + no) opengl=false ;; + *) AC_MSG_ERROR(bad value ${withval} for --with-opengl) ;; + esac],[opengl=false]) + +if test x$opengl = xtrue; then + AC_CHECK_LIB(MesaGL, main, + OGL_LIBS="-lMesaGL", + [AC_MSG_ERROR(MesaGL not found, OpenGL cannot be built) + opengl=false], + -L/usr/X11R6/lib -lX11 -lXext -lm) + AC_CHECK_LIB(MesaGLU,main, + OGL_LIBS="${OGL_LIBS} -lMesaGLU", + [AC_MSG_ERROR(MesaGLU not found, OpenGL cannot be built) + opengl=false], + -lMesaGL -L/usr/X11R6/lib -lX11 -lXext -lm) +fi + +if test x$opengl = xtrue; then + AC_DEFINE(OGL) +fi +AM_CONDITIONAL(USE_OPENGL, test x$opengl = xtrue) + + +AC_ARG_PROGRAM + +#libdir='$(shell pwd)/${top_srcdir}/main' + +AC_OUTPUT( +Makefile +2d/Makefile +3d/Makefile +maths/Makefile +mem/Makefile +cfile/Makefile +iff/Makefile +texmap/Makefile +misc/Makefile +input/Makefile +input/sdl/Makefile +input/linux/Makefile +input/ggi/Makefile +video/Makefile +sound/Makefile +arch/Makefile +arch/linux/Makefile +arch/sdl/Makefile +main/Makefile +) + diff --git a/iff/Makefile.am b/iff/Makefile.am new file mode 100644 index 00000000..ebed0a87 --- /dev/null +++ b/iff/Makefile.am @@ -0,0 +1,4 @@ +noinst_LIBRARIES = libiff.a +INCLUDES = -I $(top_srcdir)/includes + +libiff_a_SOURCES = iff.c diff --git a/iff/Makefile.in b/iff/Makefile.in new file mode 100644 index 00000000..8a3b3334 --- /dev/null +++ b/iff/Makefile.in @@ -0,0 +1,299 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +CFLAGS = @CFLAGS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +NASM = @NASM@ +NASMFLAGS = @NASMFLAGS@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_LIBS = @SDL_LIBS@ +VERSION = @VERSION@ + +noinst_LIBRARIES = libiff.a +INCLUDES = -I $(top_srcdir)/includes + +libiff_a_SOURCES = iff.c +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../conf.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +libiff_a_LIBADD = +libiff_a_OBJECTS = iff.o +AR = ar +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +DEP_FILES = .deps/iff.P +SOURCES = $(libiff_a_SOURCES) +OBJECTS = $(libiff_a_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu iff/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +libiff.a: $(libiff_a_OBJECTS) $(libiff_a_DEPENDENCIES) + -rm -f libiff.a + $(AR) cru libiff.a $(libiff_a_OBJECTS) $(libiff_a_LIBADD) + $(RANLIB) libiff.a + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = iff + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu iff/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile $(LIBRARIES) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ + mostlyclean-tags mostlyclean-depend mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \ + clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-noinstLIBRARIES distclean-compile \ + distclean-tags distclean-depend distclean-generic \ + clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/iff/archive/iff15bpp.c b/iff/archive/iff15bpp.c new file mode 100644 index 00000000..26d97e69 --- /dev/null +++ b/iff/archive/iff15bpp.c @@ -0,0 +1,92 @@ +#include +#include +#include + + +#include "iff.h" + +#define INDEX_TO_15BPP(i) ((WORD)((((palptr[(i)].r/2)&31)<<10)+(((palptr[(i)].g/2)&31)<<5)+((palptr[(i)].b/2 )&31))) + +extern int parse_iff(FILE *ifile,struct bitmap_header *bitmap_header); + +int x,y,pl,bc; +int bytes_per_row,color; +int mask,first_bit_value; +FILE *ifile; +struct bitmap_header iff_bitmap_header; + +// Parse ilbm style data at my_bh->raw_data. +BITMAP15 * IFF_To_15BPP(char * ifilename) +{ + struct bitmap_header * my_bh; + int Process_width,Process_height; + unsigned char *p; + struct pal_entry *palptr; + int newptr = 0; + int i; + BITMAP15 * new; + + my_bh = &iff_bitmap_header; + palptr=my_bh->palette; + p=my_bh->raw_data; + + Process_width = 32767; // say to process full width of bitmap + Process_height = 32767; // say to process full height of bitmap + + if ((ifile = fopen(ifilename,"rb")) == NULL) { + printf("Unable to open bitmap file %s.\n", ifilename); + exit(1); + } + + parse_iff(ifile,&iff_bitmap_header); + if (Process_width > iff_bitmap_header.w) + Process_width = iff_bitmap_header.w; + + if (Process_height > iff_bitmap_header.h) + Process_height = iff_bitmap_header.h; + + //printf( "%d, %d\n", Process_width, Process_height ); + + new = (BITMAP15 *)malloc( sizeof(BITMAP15)+ (Process_width * Process_height * 2 )); + if (new==NULL) exit(1); + + new->Width = Process_width; + new->Height = Process_height; + + //printf("Process_width = %i, Process_height = %i\n",Process_width,Process_height); + first_bit_value = 1 << (my_bh->nplanes-1); + bytes_per_row = 2*((my_bh->w+15)/16); + for (y=0; yraw_data[y*bytes_per_row*my_bh->nplanes]; + + switch (my_bh->type) { + case PBM_TYPE: + for (x=0; xw; x++) { + new->Data[newptr++] = INDEX_TO_15BPP(my_bh->raw_data[y*my_bh->w+x]); + } + break; + case ILBM_TYPE: + for (x=0; xnplanes; pl++) { + color /= 2; + if ( p[pl*bytes_per_row+x] & mask) + color += first_bit_value; + } + new->Data[newptr++] = INDEX_TO_15BPP(color); + bc--; + if (!bc) + goto line_done; + } + } +line_done: ; + break; + } + } + free( my_bh->raw_data ); + return new; +} + +ÿ \ No newline at end of file diff --git a/iff/archive/iff8bpp.c b/iff/archive/iff8bpp.c new file mode 100644 index 00000000..71caf4d5 --- /dev/null +++ b/iff/archive/iff8bpp.c @@ -0,0 +1,94 @@ +#include +#include +#include + +#include "iff.h" + +extern int parse_iff(FILE *ifile,struct bitmap_header *bitmap_header); + +int x,y,pl,bc; +int bytes_per_row,color; +int mask,first_bit_value; +FILE *ifile; +struct bitmap_header iff_bitmap_header; + +// Parse ilbm style data at my_bh->raw_data. +BITMAP8 * IFF_To_8BPP(char * ifilename) +{ + struct bitmap_header * my_bh; + int Process_width,Process_height; + unsigned char *p; + struct pal_entry *palptr; + int newptr = 0; + int i; + BITMAP8 * new; + + my_bh = &iff_bitmap_header; + palptr=my_bh->palette; + p=my_bh->raw_data; + + Process_width = 32767; // say to process full width of bitmap + Process_height = 32767; // say to process full height of bitmap + + if ((ifile = fopen(ifilename,"rb")) == NULL) { + printf("Unable to open bitmap file %s.\n", ifilename); + exit(1); + } + + parse_iff(ifile,&iff_bitmap_header); + if (Process_width > iff_bitmap_header.w) + Process_width = iff_bitmap_header.w; + + if (Process_height > iff_bitmap_header.h) + Process_height = iff_bitmap_header.h; + + printf( "%d, %d\n", Process_width, Process_height ); + + new = (BITMAP8 *)malloc( sizeof(BITMAP8)+ (Process_width * Process_height ) ); + if (new==NULL) exit(1); + + new->Width = Process_width; + new->Height = Process_height; + for (i=0;i<256;i++) { + new->Palette[3*i] = my_bh->palette[i].r; + new->Palette[3*i+1] = my_bh->palette[i].g; + new->Palette[3*i+2] = my_bh->palette[i].b; + } + printf("Process_width = %i, Process_height = %i\n",Process_width,Process_height); + first_bit_value = 1 << (my_bh->nplanes-1); + bytes_per_row = 2*((my_bh->w+15)/16); + for (y=0; yraw_data[y*bytes_per_row*my_bh->nplanes]; + + switch (my_bh->type) { + case PBM_TYPE: + for (x=0; xw; x++) { + new->Data[newptr++] = my_bh->raw_data[y*my_bh->w+x]; + } + break; + case ILBM_TYPE: + for (x=0; xnplanes; pl++) { + color /= 2; + if ( p[pl*bytes_per_row+x] & mask) + color += first_bit_value; + } + new->Data[newptr++] = color; + bc--; + if (!bc) + goto line_done; + } + } +line_done: ; + break; + } + } + free( my_bh->raw_data ); + fclose(ifile); + return new; +} + +ÿ \ No newline at end of file diff --git a/iff/archive/iffmike.c b/iff/archive/iffmike.c new file mode 100644 index 00000000..6abc0eb7 --- /dev/null +++ b/iff/archive/iffmike.c @@ -0,0 +1,488 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#include +#include +#include + +#include "iff.h" + +#define MIN(a,b) ((a> 8; + c1 = n & 0xff; + + put_byte(c0,f); + return put_byte(c1,f); +} + +int put_long(long n,FILE *f) +{ + int n0,n1; + + n0 = (int) ((n & 0xffff0000l) >> 16); + n1 = (int) (n & 0xffff); + + put_word(n0,f); + return put_word(n1,f); + +} + +long get_long(FILE *f) +{ + unsigned char c0,c1,c2,c3; + + c3=getc(f); + c2=getc(f); + c1=getc(f); + c0=getc(f); + +//printf("get_long %x %x %x %x\n",c3,c2,c1,c0); + +// if (c0==0xff) return(EOF); + + return(((long)c3<<24) + ((long)c2<<16) + ((long)c1<<8) + c0); + +} + +void parse_bmhd(FILE *ifile,long len,struct bitmap_header *bitmap_header) +{ + len++; /* so no "parm not used" warning */ + +// debug("parsing bmhd len=%ld\n",len); + + bitmap_header->w = get_word(ifile); + bitmap_header->h = get_word(ifile); + bitmap_header->x = get_word(ifile); + bitmap_header->y = get_word(ifile); + + bitmap_header->nplanes = get_byte(ifile); + bitmap_header->masking = get_byte(ifile); + bitmap_header->compression = get_byte(ifile); + get_byte(ifile); /* skip pad */ + + bitmap_header->transparentcolor = get_word(ifile); + bitmap_header->xaspect = get_byte(ifile); + bitmap_header->yaspect = get_byte(ifile); + + bitmap_header->pagewidth = get_word(ifile); + bitmap_header->pageheight = get_word(ifile); + +// debug("w,h=%d,%d x,y=%d,%d\n",w,h,x,y); +// debug("nplanes=%d, masking=%d ,compression=%d, transcolor=%d\n",nplanes,masking,compression,transparentcolor); + +} + + +// the buffer pointed to by raw_data is stuffed with a pointer to decompressed pixel data +int parse_body_pbm(FILE *ifile,long len,struct bitmap_header *bitmap_header) +{ + unsigned char huge *p=bitmap_header->raw_data; + int width=bitmap_header->w; + long cnt,old_cnt; + char n; + int nn,wid_cnt; + char ignore; + + if (bitmap_header->compression == cmpNone) { /* no compression */ + int x,y; + + for (y=bitmap_header->h;y;y--) { + for (x=bitmap_header->w;x;x--) *p++=getc(ifile); + if (bitmap_header->w & 1) ignore = getc(ifile); + } + + } + else if (bitmap_header->compression == cmpByteRun1) + for (old_cnt=cnt=len,wid_cnt=width;cnt>0;) { + unsigned char c; + + if (old_cnt-cnt > 2048) { +// printf("."); + old_cnt=cnt; + } + + if (wid_cnt <= 0) wid_cnt = width; + + n=getc(ifile); + if (n >= 0) { // copy next n+1 bytes from source, they are not compressed + nn = (int) n+1; + cnt -= nn+1; + wid_cnt -= nn; + if (wid_cnt==-1) --nn; + while (nn--) *p++=getc(ifile); + if (wid_cnt==-1) ignore = getc(ifile); /* extra char */ + } + else if (n>=-127) { // next -n + 1 bytes are following byte + cnt -= 2; + c=getc(ifile); + nn = (int) -n+1; + wid_cnt -= nn; + if (wid_cnt==-1) --nn; + while (nn--) *p++=c; + } + + } + + if (len & 1) ignore = getc(ifile); + + if (ignore) ignore++; // haha, suppress the evil warning message + + return IFF_NO_ERROR; +} + +// the buffer pointed to by raw_data is stuffed with a pointer to bitplane pixel data +int parse_body_ilbm(FILE *ifile,long len,struct bitmap_header *bitmap_header) +{ + unsigned char huge *p=bitmap_header->raw_data; + int width=bitmap_header->w; + long cnt,old_cnt; + char n; + int nn,wid_cnt; + char ignore; + + if (bitmap_header->compression == cmpNone) { /* no compression */ + int x,y; + + for (y=bitmap_header->h;y;y--) { + for (x=bitmap_header->w;x;x--) *p++=getc(ifile); + if (bitmap_header->w & 1) ignore = getc(ifile); + } + + } + else if (bitmap_header->compression == cmpByteRun1) + for (old_cnt=cnt=len,wid_cnt=width;cnt>0;) { + unsigned char c; + + if (old_cnt-cnt > 2048) { +// printf("."); + old_cnt=cnt; + } + + if (wid_cnt <= 0) wid_cnt = width; + + n=getc(ifile); + if (n >= 0) { // copy next n+1 bytes from source, they are not compressed + nn = (int) n+1; + cnt -= nn+1; + wid_cnt -= nn; + if (wid_cnt==-1) --nn; + while (nn--) *p++=getc(ifile); + if (wid_cnt==-1) ignore = getc(ifile); /* extra char */ + } + else if (n>=-127) { // next -n + 1 bytes are following byte + cnt -= 2; + c=getc(ifile); + nn = (int) -n+1; + wid_cnt -= nn; + if (wid_cnt==-1) --nn; + while (nn--) *p++=c; + } + + } + + if (len & 1) ignore = getc(ifile); + + if (ignore) ignore++; // haha, suppress the evil warning message + + return IFF_NO_ERROR; +} + +void skip_chunk(FILE *ifile,long len) +{ + len = len+1 & ~1; + fseek(ifile,len,SEEK_CUR); +} + +// Pass pointer to opened file, and to empty bitmap header. +int parse_iff(FILE *ifile,struct bitmap_header *bitmap_header) +{ + long sig,form_len,len,form_type; + char ignore; + + sig=get_sig(ifile); + +// printsig(sig); + + if (sig==form_sig) { + + form_len = get_long(ifile); + form_len++; /* get rid of never used message */ + + form_type = get_sig(ifile); + +// printf(" %ld ",form_len); +// printsig(form_type); +// printf("\n"); + + if ((form_type == pbm_sig) || (form_type == ilbm_sig)) { + + if (form_type == pbm_sig) + bitmap_header->type = PBM_TYPE; + else + bitmap_header->type = ILBM_TYPE; + + while ((sig=get_sig(ifile)) != EOF) { + + len=get_long(ifile); + +// printf(" "); +// printsig(sig); +// printf(" %ld\n",len); + + switch (sig) { + + case bmhd_sig: + + parse_bmhd(ifile,len,bitmap_header); + + if (! (bitmap_header->raw_data = farmalloc((long) bitmap_header->w * bitmap_header->h))) return IFF_NO_MEM; + + break; + + case cmap_sig: + { + int ncolors=(int) (len/3),cnum; + unsigned char r,g,b; + + for (cnum=0;cnum>= 2; bitmap_header->palette[cnum].r = r; + g >>= 2; bitmap_header->palette[cnum].g = g; + b >>= 2; bitmap_header->palette[cnum].b = b; + } + if (len & 1) ignore = getc(ifile); + + break; + } + + case body_sig: + { + int r; + switch (form_type) { + case pbm_sig: + if (!(r=parse_body_pbm(ifile,len,bitmap_header))) return r; + break; + case ilbm_sig: + if (!(r=parse_body_ilbm(ifile,len,bitmap_header))) return r; + break; + } + break; + } + default: + skip_chunk(ifile,len); + break; + } + } + } + else return IFF_UNKNOWN_FORM; + } + else + {printf("Not an IFF file\n"); return IFF_NOT_IFF;} + + if (ignore) ignore++; + + return IFF_NO_ERROR; /* ok! */ +} + +#define BMHD_SIZE 20 + +int write_bmhd(FILE *ofile,struct bitmap_header *bitmap_header) +{ + + put_sig(bmhd_sig,ofile); + put_long((long) BMHD_SIZE,ofile); + + put_word(bitmap_header->w,ofile); + put_word(bitmap_header->h,ofile); + put_word(bitmap_header->x,ofile); + put_word(bitmap_header->y,ofile); + + put_byte(bitmap_header->nplanes,ofile); + put_byte(bitmap_header->masking,ofile); + put_byte(bitmap_header->compression,ofile); + put_byte(0,ofile); /* pad */ + + put_word(bitmap_header->transparentcolor,ofile); + put_byte(bitmap_header->xaspect,ofile); + put_byte(bitmap_header->yaspect,ofile); + + put_word(bitmap_header->pagewidth,ofile); + put_word(bitmap_header->pageheight,ofile); + + return 1; + +} + +int write_huge(unsigned char huge *huge_ptr,long len,FILE *f) +{ + unsigned char temp_buffer[256],*t; + +//printf("write_huge %ld\n",len); + + while (len) { + int n,wsize = (int) MIN(len,256); + +//printf("len,wsize=%ld,%d\n",len,wsize); + for (t=temp_buffer,n=wsize;n--;) *t++ = *huge_ptr++; + + fwrite(temp_buffer,wsize,1,f); + + len -= wsize; + + } + + return 1; +} + +int write_pal(FILE *ofile,struct bitmap_header *bitmap_header) +{ + int i; + + int n_colors = 1<nplanes; + + put_sig(cmap_sig,ofile); +// put_long(sizeof(struct pal_entry) * n_colors,ofile); + put_long(3 * n_colors,ofile); + +//printf("new write pal %d %d\n",3,n_colors); + + for (i=0; i<256; i++) { + unsigned char r,g,b; + r = bitmap_header->palette[i].r * 4; + g = bitmap_header->palette[i].g * 4; + b = bitmap_header->palette[i].b * 4; + fputc(r,ofile); + fputc(g,ofile); + fputc(b,ofile); + } + +//printf("write pal %d %d\n",sizeof(struct pal_entry),n_colors); +// fwrite(bitmap_header->palette,sizeof(struct pal_entry),n_colors,ofile); + + return 1; +} + +#define EVEN(a) ((a+1)&0xfffffffel) + +int write_body(FILE *ofile,struct bitmap_header *bitmap_header) +{ + int w=bitmap_header->w,h=bitmap_header->h; + int y,odd=w&1; + long len = EVEN(w) * h; + unsigned char huge *p=bitmap_header->raw_data; + + put_sig(body_sig,ofile); + put_long(len,ofile); + + for (y=bitmap_header->h;y--;) { + + write_huge(p,bitmap_header->w,ofile); + if (odd) putc(0,ofile); + p+=bitmap_header->w; + + } + + return 1; +} + +int write_pbm(FILE *ofile,struct bitmap_header *bitmap_header) /* writes a pbm iff file */ +{ + long raw_size = EVEN(bitmap_header->w) * bitmap_header->h; + long pbm_size = 4 + BMHD_SIZE + 8 + EVEN(raw_size) + sizeof(struct pal_entry)*(1<nplanes)+8; + +//printf("write_pbm\n"); + + put_sig(form_sig,ofile); + put_long(pbm_size+8,ofile); + put_sig(pbm_sig,ofile); + + write_bmhd(ofile,bitmap_header); + + write_pal(ofile,bitmap_header); + + write_body(ofile,bitmap_header); + + return 1; + +} + diff --git a/iff/archive/ifftest.c b/iff/archive/ifftest.c new file mode 100644 index 00000000..73d37d46 --- /dev/null +++ b/iff/archive/ifftest.c @@ -0,0 +1,105 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#include +#include +#include + +#include "iff.h" +#include "vga.h" +#include "palette.h" +#include "mem.h" + +//#define ANIM_TEST 1 //if defined, read in anim brush + +rle_span(ubyte *dest,ubyte *src,int len); + + +ubyte test_span[] = {0,1,2,3,4,4,5,6,7,8,8,8,8,8,9,10,11,11}; +ubyte new_span[256]; + +extern void gr_pal_setblock( int start, int number, unsigned char * pal ); + +main(int argc,char **argv) +{ + int ret; + grs_bitmap my_bitmap; + ubyte my_palette[256*3]; + grs_bitmap *bm_list[100]; + int n_bitmaps; + char key; + +#if 0 + { + int new_len,i; + new_len=rle_span(new_span,test_span,sizeof(test_span)); + printf("old span (%d): ",sizeof(test_span)); + for (i=0;i",iff_errormsg(ret)); + + if (ret == IFF_NO_ERROR) { + int i; + + vga_init(); + gr_init(); + vga_set_mode(SM_320x200C); + + for (i=0;i2) { + ret = iff_write_bitmap(argv[2],bm_list[i],&my_palette); + printf("ret = %d\n",ret); + } + + //gr_pal_setblock(0,256,&my_palette); + gr_palette_load(&my_palette); + //gr_pal_fade_in(grd_curscreen->pal); //in case palette is blacked + + gr_ubitmap(0,0,bm_list[i]); + + key = getch(); + + if (key=='-') {if (i) i--;} + else i++; + + } + + gr_close(); + + for (i=0;ibm_data); + + #ifdef ANIM_TEST + free(bm_list[i]); + #endif + + } + } + +} + diff --git a/iff/archive/ifftestv.c b/iff/archive/ifftestv.c new file mode 100644 index 00000000..c8348432 --- /dev/null +++ b/iff/archive/ifftestv.c @@ -0,0 +1,59 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#include +#include + +#include "iff.h" +//#include "gr.h" +#include "vesa.h" + +draw_ubitmap(int x,int y,grs_bitmap *bm) +{ + int xx,yy; + short *data15 = (short *) bm->bm_data; + +printf("x,y=%d,%d w,h=%d,%d\n",x,y,bm->bm_w,bm->bm_h); + + for (yy=0;yybm_h;yy++) + + for (xx=0;xxbm_w;xx++) + + gr_vesa_pixel15(x+xx,y+yy,data15[yy*bm->bm_w+xx]); + + +} + + +main(int argc,char **argv) +{ + int ret; + grs_bitmap my_bitmap; + ubyte my_palette[256*3]; + + ret = iff_read_bitmap(argv[1],&my_bitmap,BM_RGB15,&my_palette); + + printf("ret = %d\n",ret); + + if (ret == IFF_NO_ERROR) { + + gr_vesa_setmode(0x110); + + draw_ubitmap(0,0,&my_bitmap); + + getch(); + + } + +} + diff --git a/iff/iff.c b/iff/iff.c new file mode 100644 index 00000000..f67f362e --- /dev/null +++ b/iff/iff.c @@ -0,0 +1,1259 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifdef RCS +static char rcsid[] = "$Id: iff.c,v 1.1.1.1 2001-01-19 03:29:58 bradleyb Exp $"; +#endif + +#include + +#define COMPRESS 1 //do the RLE or not? (for debugging mostly) +#define WRITE_TINY 0 //should we write a TINY chunk? + +#define MIN_COMPRESS_WIDTH 65 //don't compress if less than this wide + +#include +#include +#include + +#include "u_mem.h" +#include "iff.h" + +//#include "nocfile.h" +#include "cfile.h" +#include "error.h" + +//Internal constants and structures for this library + +//Type values for bitmaps +#define TYPE_PBM 0 +#define TYPE_ILBM 1 + +//Compression types +#define cmpNone 0 +#define cmpByteRun1 1 + +//Masking types +#define mskNone 0 +#define mskHasMask 1 +#define mskHasTransparentColor 2 + +//Palette entry structure +typedef struct pal_entry {byte r,g,b;} pal_entry; + +//structure of the header in the file +typedef struct iff_bitmap_header { + short w,h; //width and height of this bitmap + short x,y; //generally unused + short type; //see types above + short transparentcolor; //which color is transparent (if any) + short pagewidth,pageheight; //width & height of source screen + byte nplanes; //number of planes (8 for 256 color image) + byte masking,compression; //see constants above + byte xaspect,yaspect; //aspect ratio (usually 5/6) + pal_entry palette[256]; //the palette for this bitmap + ubyte *raw_data; //ptr to array of data + short row_size; //offset to next row +} iff_bitmap_header; + +ubyte iff_transparent_color; +ubyte iff_has_transparency; // 0=no transparency, 1=iff_transparent_color is valid + +typedef struct fake_file { + ubyte *data; + int position; + int length; +} FFILE; + +#define MIN(a,b) ((aposition>=f->length) return EOF; + s[3] = f->data[f->position++]; + if (f->position>=f->length) return EOF; + s[2] = f->data[f->position++]; + if (f->position>=f->length) return EOF; + s[1] = f->data[f->position++]; + if (f->position>=f->length) return EOF; + s[0] = f->data[f->position++]; +#else + if (f->position>=f->length) return EOF; + s[0] = f->data[f->position++]; + if (f->position>=f->length) return EOF; + s[1] = f->data[f->position++]; + if (f->position>=f->length) return EOF; + s[2] = f->data[f->position++]; + if (f->position>=f->length) return EOF; + s[3] = f->data[f->position++]; +#endif + + return(*((long *) s)); +} + +int put_sig(long sig,FILE *f) +{ + char *s = (char *) &sig; + + fputc(s[3],f); + fputc(s[2],f); + fputc(s[1],f); + return fputc(s[0],f); + +} + +char get_byte(FFILE *f) +{ + //return cfgetc(f); + return f->data[f->position++]; +} + +int put_byte(unsigned char c,FILE *f) +{ + return fputc(c,f); +} + + + +int get_word(FFILE *f) +{ + unsigned char c0,c1; + +// c1=cfgetc(f); +// c0=cfgetc(f); + + if (f->position>=f->length) return EOF; + c1 = f->data[f->position++]; + if (f->position>=f->length) return EOF; + c0 = f->data[f->position++]; + + if (c0==0xff) return(EOF); + + return(((int)c1<<8) + c0); + +} + +int put_word(int n,FILE *f) +{ + unsigned char c0,c1; + + c0 = (n & 0xff00) >> 8; + c1 = n & 0xff; + + put_byte(c0,f); + return put_byte(c1,f); +} + +int put_long(long n,FILE *f) +{ + int n0,n1; + + n0 = (int) ((n & 0xffff0000l) >> 16); + n1 = (int) (n & 0xffff); + + put_word(n0,f); + return put_word(n1,f); + +} + +long get_long(FFILE *f) +{ + unsigned char c0,c1,c2,c3; + + //c3=cfgetc(f); + //c2=cfgetc(f); + //c1=cfgetc(f); + //c0=cfgetc(f); + + if (f->position>=f->length) return EOF; + c3 = f->data[f->position++]; + if (f->position>=f->length) return EOF; + c2 = f->data[f->position++]; + if (f->position>=f->length) return EOF; + c1 = f->data[f->position++]; + if (f->position>=f->length) return EOF; + c0 = f->data[f->position++]; + +//printf("get_long %x %x %x %x\n",c3,c2,c1,c0); + +// if (c0==0xff) return(EOF); + + return(((long)c3<<24) + ((long)c2<<16) + ((long)c1<<8) + c0); + +} + +int parse_bmhd(FFILE *ifile,long len,iff_bitmap_header *bmheader) +{ + len++; /* so no "parm not used" warning */ + +// debug("parsing bmhd len=%ld\n",len); + + bmheader->w = get_word(ifile); + bmheader->h = get_word(ifile); + bmheader->x = get_word(ifile); + bmheader->y = get_word(ifile); + + bmheader->nplanes = get_byte(ifile); + bmheader->masking = get_byte(ifile); + bmheader->compression = get_byte(ifile); + get_byte(ifile); /* skip pad */ + + bmheader->transparentcolor = get_word(ifile); + bmheader->xaspect = get_byte(ifile); + bmheader->yaspect = get_byte(ifile); + + bmheader->pagewidth = get_word(ifile); + bmheader->pageheight = get_word(ifile); + + iff_transparent_color = bmheader->transparentcolor; + + iff_has_transparency = 0; + + if (bmheader->masking == mskHasTransparentColor) + iff_has_transparency = 1; + + else if (bmheader->masking != mskNone && bmheader->masking != mskHasMask) + return IFF_UNKNOWN_MASK; + +// debug("w,h=%d,%d x,y=%d,%d\n",w,h,x,y); +// debug("nplanes=%d, masking=%d ,compression=%d, transcolor=%d\n",nplanes,masking,compression,transparentcolor); + + return IFF_NO_ERROR; +} + + +// the buffer pointed to by raw_data is stuffed with a pointer to decompressed pixel data +int parse_body(FFILE *ifile,long len,iff_bitmap_header *bmheader) +{ + unsigned char *p=bmheader->raw_data; + int width,depth; + signed char n; + int nn,wid_cnt,end_cnt,plane; + char ignore=0; + unsigned char *data_end; + int end_pos; + int row_count=0; + + end_pos = ifile->position + len; + if (len&1) + end_pos++; + + if (bmheader->type == TYPE_PBM) { + width=bmheader->w; + depth=1; + } else if (bmheader->type == TYPE_ILBM) { + width = (bmheader->w+7)/8; + depth=bmheader->nplanes; + } + + end_cnt = (width&1)?-1:0; + + data_end = p + width*bmheader->h*depth; + + if (bmheader->compression == cmpNone) { /* no compression */ + int y; + + for (y=bmheader->h;y;y--) { + int x; +// for (x=bmheader->w;x;x--) *p++=cfgetc(ifile); +// cfread(p, bmheader->w, 1, ifile); +// p += bmheader->w; + + for (x=0;xdata[ifile->position++]; + + if (bmheader->masking == mskHasMask) + ifile->position += width; //skip mask! + +// if (bmheader->w & 1) ignore = cfgetc(ifile); + if (bmheader->w & 1) ifile->position++; + } + + //cnt = len - bmheader->h * ((bmheader->w+1)&~1); + + } + else if (bmheader->compression == cmpByteRun1) + for (wid_cnt=width,plane=0;ifile->position 2048) { +// printf("."); +// old_cnt=cnt; +// } + + if (wid_cnt == end_cnt) { + wid_cnt = width; + plane++; + if ((bmheader->masking == mskHasMask && plane==depth+1) || + (bmheader->masking != mskHasMask && plane==depth)) + plane=0; + } + + Assert(wid_cnt > end_cnt); + + //n=cfgetc(ifile); + n=ifile->data[ifile->position++]; + + if (n >= 0) { // copy next n+1 bytes from source, they are not compressed + nn = (int) n+1; + wid_cnt -= nn; + if (wid_cnt==-1) {--nn; Assert(width&1);} + if (plane==depth) //masking row + ifile->position += nn; + else + while (nn--) *p++=ifile->data[ifile->position++]; + if (wid_cnt==-1) ifile->position++; + } + else if (n>=-127) { // next -n + 1 bytes are following byte + c=ifile->data[ifile->position++]; + nn = (int) -n+1; + wid_cnt -= nn; + if (wid_cnt==-1) {--nn; Assert(width&1);} + if (plane!=depth) //not masking row + {memset(p,c,nn); p+=nn;} + } + + #ifndef NDEBUG + if ((p-bmheader->raw_data) % width == 0) + row_count++; + + Assert((p-bmheader->raw_data) - (width*row_count) < width); + #endif + + } + + if (p!=data_end) //if we don't have the whole bitmap... + return IFF_CORRUPT; //...the give an error + + //Pretend we read the whole chuck, because if we didn't, it's because + //we didn't read the last mask like or the last rle record for padding + //or whatever and it's not important, because we check to make sure + //we got the while bitmap, and that's what really counts. + + ifile->position = end_pos; + + if (ignore) ignore++; // haha, suppress the evil warning message + + return IFF_NO_ERROR; +} + +//modify passed bitmap +int parse_delta(FFILE *ifile,long len,iff_bitmap_header *bmheader) +{ + unsigned char *p=bmheader->raw_data; + int y; + long chunk_end = ifile->position + len; + + get_long(ifile); //longword, seems to be equal to 4. Don't know what it is + + for (y=0;yh;y++) { + ubyte n_items; + int cnt = bmheader->w; + ubyte code; + + n_items = get_byte(ifile); + + while (n_items--) { + + code = get_byte(ifile); + + if (code==0) { //repeat + ubyte rep,val; + + rep = get_byte(ifile); + val = get_byte(ifile); + + cnt -= rep; + if (cnt==-1) + rep--; + while (rep--) + *p++ = val; + } + else if (code > 0x80) { //skip + cnt -= (code-0x80); + p += (code-0x80); + if (cnt==-1) + p--; + } + else { //literal + cnt -= code; + if (cnt==-1) + code--; + + while (code--) + *p++ = get_byte(ifile); + + if (cnt==-1) + get_byte(ifile); + } + + } + + if (cnt == -1) { + if (!bmheader->w&1) + return IFF_CORRUPT; + } + else if (cnt) + return IFF_CORRUPT; + } + + if (ifile->position == chunk_end-1) //pad + ifile->position++; + + if (ifile->position != chunk_end) + return IFF_CORRUPT; + else + return IFF_NO_ERROR; +} + +// the buffer pointed to by raw_data is stuffed with a pointer to bitplane pixel data +void skip_chunk(FFILE *ifile,long len) +{ + //int c,i; + int ilen; + ilen = (len+1) & ~1; + +//printf( "Skipping %d chunk\n", ilen ); + + ifile->position += ilen; + + if (ifile->position >= ifile->length ) { + ifile->position = ifile->length; + } + + +// for (i=0; iposition; + end_pos = start_pos-4+form_len; + +// printf(" %ld ",form_len); +// printsig(form_type); +// printf("\n"); + + if (form_type == pbm_sig) + bmheader->type = TYPE_PBM; + else + bmheader->type = TYPE_ILBM; + + while ((ifile->position < end_pos) && (sig=get_sig(ifile)) != EOF) { + + len=get_long(ifile); + if (len==EOF) break; + +// printf(" "); +// printsig(sig); +// printf(" %ld\n",len); + + switch (sig) { + + case bmhd_sig: { + int ret; + int save_w=bmheader->w,save_h=bmheader->h; + + //printf("Parsing header\n"); + + ret = parse_bmhd(ifile,len,bmheader); + + if (ret != IFF_NO_ERROR) + return ret; + + if (bmheader->raw_data) { + + if (save_w != bmheader->w || save_h != bmheader->h) + return IFF_BM_MISMATCH; + + } + else { + + MALLOC( bmheader->raw_data, ubyte, bmheader->w * bmheader->h ); + if (!bmheader->raw_data) + return IFF_NO_MEM; + } + + break; + + } + + case anhd_sig: + + if (!prev_bm) return IFF_CORRUPT; + + bmheader->w = prev_bm->bm_w; + bmheader->h = prev_bm->bm_h; + bmheader->type = prev_bm->bm_type; + + MALLOC( bmheader->raw_data, ubyte, bmheader->w * bmheader->h ); + + memcpy(bmheader->raw_data, prev_bm->bm_data, bmheader->w * bmheader->h ); + skip_chunk(ifile,len); + + break; + + case cmap_sig: + { + int ncolors=(int) (len/3),cnum; + unsigned char r,g,b; + + //printf("Parsing RGB map\n"); + for (cnum=0;cnumdata[ifile->position++]; + g = ifile->data[ifile->position++]; + b = ifile->data[ifile->position++]; + r >>= 2; bmheader->palette[cnum].r = r; + g >>= 2; bmheader->palette[cnum].g = g; + b >>= 2; bmheader->palette[cnum].b = b; + } + //if (len & 1) ignore = cfgetc(ifile); + if (len & 1 ) ifile->position++; + + break; + } + + case body_sig: + { + int r; + //printf("Parsing body\n"); + if ((r=parse_body(ifile,len,bmheader))!=IFF_NO_ERROR) + return r; + break; + } + case dlta_sig: + { + int r; + if ((r=parse_delta(ifile,len,bmheader))!=IFF_NO_ERROR) + return r; + break; + } + default: + skip_chunk(ifile,len); + break; + } + } + + //if (ignore) ignore++; + + if (ifile->position != start_pos-4+form_len) + return IFF_CORRUPT; + + return IFF_NO_ERROR; /* ok! */ +} + +//convert an ILBM file to a PBM file +int convert_ilbm_to_pbm(iff_bitmap_header *bmheader) +{ + int x,y,p; + byte *new_data,*destptr,*rowptr; + int bytes_per_row,byteofs; + ubyte checkmask,newbyte,setbit; + + MALLOC( new_data, byte, bmheader->w * bmheader->h ); + if (new_data == NULL) return IFF_NO_MEM; + + destptr = new_data; + + bytes_per_row = 2*((bmheader->w+15)/16); + + for (y=0;yh;y++) { + + rowptr = &bmheader->raw_data[y * bytes_per_row * bmheader->nplanes]; + + for (x=0,checkmask=0x80;xw;x++) { + + byteofs = x >> 3; + + for (p=newbyte=0,setbit=1;pnplanes;p++) { + + if (rowptr[bytes_per_row * p + byteofs] & checkmask) + newbyte |= setbit; + + setbit <<= 1; + } + + *destptr++ = newbyte; + + if ((checkmask >>= 1) == 0) checkmask=0x80; + } + + } + + d_free(bmheader->raw_data); + bmheader->raw_data = new_data; + + bmheader->type = TYPE_PBM; + + return IFF_NO_ERROR; +} + +#define INDEX_TO_15BPP(i) ((short)((((palptr[(i)].r/2)&31)<<10)+(((palptr[(i)].g/2)&31)<<5)+((palptr[(i)].b/2 )&31))) + +int convert_rgb15(grs_bitmap *bm,iff_bitmap_header *bmheader) +{ + ushort *new_data; + int x,y; + int newptr = 0; + pal_entry *palptr; + + palptr = bmheader->palette; + +// if ((new_data = d_malloc(bm->bm_w * bm->bm_h * 2)) == NULL) +// {ret=IFF_NO_MEM; goto done;} + MALLOC(new_data, ushort, bm->bm_w * bm->bm_h * 2); + if (new_data == NULL) + return IFF_NO_MEM; + + for (y=0; ybm_h; y++) { + + for (x=0; xw; x++) + new_data[newptr++] = INDEX_TO_15BPP(bmheader->raw_data[y*bmheader->w+x]); + + } + + d_free(bm->bm_data); //get rid of old-style data + bm->bm_data = (ubyte *) new_data; //..and point to new data + + bm->bm_rowsize *= 2; //two bytes per row + + return IFF_NO_ERROR; + +} + +//read in a entire file into a fake file structure +int open_fake_file(char *ifilename,FFILE *ffile) +{ + CFILE *ifile; + int ret; + + //printf( "Reading %s\n", ifilename ); + + ffile->data=NULL; + + if ((ifile = cfopen(ifilename,"rb")) == NULL) return IFF_NO_FILE; + + ffile->length = cfilelength(ifile); + + MALLOC(ffile->data,ubyte,ffile->length); + + if (cfread(ffile->data, 1, ffile->length, ifile) < ffile->length) + ret = IFF_READ_ERROR; + else + ret = IFF_NO_ERROR; + + ffile->position = 0; + + if (ifile) cfclose(ifile); + + return ret; +} + +void close_fake_file(FFILE *f) +{ + if (f->data) + d_free(f->data); + + f->data = NULL; +} + +//copy an iff header structure to a grs_bitmap structure +void copy_iff_to_grs(grs_bitmap *bm,iff_bitmap_header *bmheader) +{ + bm->bm_x = bm->bm_y = 0; + bm->bm_w = bmheader->w; + bm->bm_h = bmheader->h; + bm->bm_type = bmheader->type; + bm->bm_rowsize = bmheader->w; + bm->bm_data = bmheader->raw_data; + + bm->bm_flags = bm->bm_handle = 0; + +} + +//if bm->bm_data is set, use it (making sure w & h are correct), else +//allocate the memory +int iff_parse_bitmap(FFILE *ifile,grs_bitmap *bm,int bitmap_type,byte *palette,grs_bitmap *prev_bm) +{ + int ret; //return code + iff_bitmap_header bmheader; + long sig,form_len; + long form_type; + + bmheader.raw_data = bm->bm_data; + + if (bmheader.raw_data) { + bmheader.w = bm->bm_w; + bmheader.h = bm->bm_h; + } + + sig=get_sig(ifile); + + if (sig != form_sig) { + ret = IFF_NOT_IFF; + goto done; + } + + form_len = get_long(ifile); + + form_type = get_sig(ifile); + + if (form_type == anim_sig) + ret = IFF_FORM_ANIM; + else if ((form_type == pbm_sig) || (form_type == ilbm_sig)) + ret = iff_parse_ilbm_pbm(ifile,form_type,&bmheader,form_len,prev_bm); + else + ret = IFF_UNKNOWN_FORM; + + if (ret != IFF_NO_ERROR) { //got an error parsing + if (bmheader.raw_data) d_free(bmheader.raw_data); + goto done; + } + + //If IFF file is ILBM, convert to PPB + if (bmheader.type == TYPE_ILBM) { + + ret = convert_ilbm_to_pbm(&bmheader); + + if (ret != IFF_NO_ERROR) goto done; + } + + //Copy data from iff_bitmap_header structure into grs_bitmap structure + + copy_iff_to_grs(bm,&bmheader); + +#ifndef MACINTOSH + if (palette) memcpy(palette,&bmheader.palette,sizeof(bmheader.palette)); +#else +// if (palette) memcpy(palette,&bmheader.palette, 768); // pal_entry is 4 bytes on mac + if (palette) { + ubyte *c; + int i; + + c = palette; + for (i = 0; i < 256; i++) { + *c++ = bmheader.palette[i].r; + *c++ = bmheader.palette[i].g; + *c++ = bmheader.palette[i].b; + } + } +#endif + + //Now do post-process if required + + if (bitmap_type == BM_RGB15) { + ret = convert_rgb15(bm,&bmheader); + if (ret != IFF_NO_ERROR) goto done; + } + +done: + + return ret; + +} + +//returns error codes - see IFF.H. see GR.H for bitmap_type +int iff_read_bitmap(char *ifilename,grs_bitmap *bm,int bitmap_type,ubyte *palette) +{ + int ret; //return code + FFILE ifile; + + ret = open_fake_file(ifilename,&ifile); //read in entire file + if (ret != IFF_NO_ERROR) goto done; + + bm->bm_data = NULL; + + ret = iff_parse_bitmap(&ifile,bm,bitmap_type,palette,NULL); + +done: + + if (ifile.data) d_free(ifile.data); + + close_fake_file(&ifile); + + return ret; + + +} + +//like iff_read_bitmap(), but reads into a bitmap that already exists, +//without allocating memory for the bitmap. +int iff_read_into_bitmap(char *ifilename,grs_bitmap *bm,byte *palette) +{ + int ret; //return code + FFILE ifile; + + ret = open_fake_file(ifilename,&ifile); //read in entire file + if (ret != IFF_NO_ERROR) goto done; + + ret = iff_parse_bitmap(&ifile,bm,bm->bm_type,palette,NULL); + +done: + + if (ifile.data) d_free(ifile.data); + + close_fake_file(&ifile); + + return ret; + + +} + +#define BMHD_SIZE 20 + +int write_bmhd(FILE *ofile,iff_bitmap_header *bitmap_header) +{ + put_sig(bmhd_sig,ofile); + put_long((long) BMHD_SIZE,ofile); + + put_word(bitmap_header->w,ofile); + put_word(bitmap_header->h,ofile); + put_word(bitmap_header->x,ofile); + put_word(bitmap_header->y,ofile); + + put_byte(bitmap_header->nplanes,ofile); + put_byte(bitmap_header->masking,ofile); + put_byte(bitmap_header->compression,ofile); + put_byte(0,ofile); /* pad */ + + put_word(bitmap_header->transparentcolor,ofile); + put_byte(bitmap_header->xaspect,ofile); + put_byte(bitmap_header->yaspect,ofile); + + put_word(bitmap_header->pagewidth,ofile); + put_word(bitmap_header->pageheight,ofile); + + return IFF_NO_ERROR; + +} + +int write_pal(FILE *ofile,iff_bitmap_header *bitmap_header) +{ + int i; + + int n_colors = 1<nplanes; + + put_sig(cmap_sig,ofile); +// put_long(sizeof(pal_entry) * n_colors,ofile); + put_long(3 * n_colors,ofile); + +//printf("new write pal %d %d\n",3,n_colors); + + for (i=0; i<256; i++) { + unsigned char r,g,b; + r = bitmap_header->palette[i].r * 4 + (bitmap_header->palette[i].r?3:0); + g = bitmap_header->palette[i].g * 4 + (bitmap_header->palette[i].g?3:0); + b = bitmap_header->palette[i].b * 4 + (bitmap_header->palette[i].b?3:0); + fputc(r,ofile); + fputc(g,ofile); + fputc(b,ofile); + } + +//printf("write pal %d %d\n",sizeof(pal_entry),n_colors); +// fwrite(bitmap_header->palette,sizeof(pal_entry),n_colors,ofile); + + return IFF_NO_ERROR; +} + +int rle_span(ubyte *dest,ubyte *src,int len) +{ + int n,lit_cnt,rep_cnt; + ubyte last,*cnt_ptr,*dptr; + + dptr = dest; + + last=src[0]; lit_cnt=1; + + for (n=1;n 2 || lit_cnt < 2) { + + if (lit_cnt > 1) {*cnt_ptr = lit_cnt-2; --dptr;} //save old lit count + *dptr++ = -(rep_cnt-1); + *dptr++ = last; + last = src[n]; + lit_cnt = (n 1) + *cnt_ptr = lit_cnt-1; + + return dptr-dest; +} + +#define EVEN(a) ((a+1)&0xfffffffel) + +//returns length of chunk +int write_body(FILE *ofile,iff_bitmap_header *bitmap_header,int compression_on) +{ + int w=bitmap_header->w,h=bitmap_header->h; + int y,odd=w&1; + long len = EVEN(w) * h,newlen,total_len=0; + ubyte *p=bitmap_header->raw_data,*new_span; + long save_pos; + + put_sig(body_sig,ofile); + save_pos = ftell(ofile); + put_long(len,ofile); + + //if (! (new_span = d_malloc(bitmap_header->w+(bitmap_header->w/128+2)*2))) return IFF_NO_MEM; + MALLOC( new_span, ubyte, bitmap_header->w + (bitmap_header->w/128+2)*2); + if (new_span == NULL) return IFF_NO_MEM; + + for (y=bitmap_header->h;y--;) { + + if (compression_on) { + total_len += newlen = rle_span(new_span,p,bitmap_header->w+odd); + fwrite(new_span,newlen,1,ofile); + } + else + fwrite(p,bitmap_header->w+odd,1,ofile); + + p+=bitmap_header->row_size; //bitmap_header->w; + } + + if (compression_on) { //write actual data length + Assert(fseek(ofile,save_pos,SEEK_SET)==0); + put_long(total_len,ofile); + Assert(fseek(ofile,total_len,SEEK_CUR)==0); + if (total_len&1) fputc(0,ofile); //pad to even + } + + d_free(new_span); + + return ((compression_on) ? (EVEN(total_len)+8) : (len+8)); + +} + +#if WRITE_TINY +//write a small representation of a bitmap. returns size +int write_tiny(CFILE *ofile,iff_bitmap_header *bitmap_header,int compression_on) +{ + int skip; + int new_w,new_h; + int len,total_len=0,newlen; + int x,y,xofs,odd; + ubyte *p = bitmap_header->raw_data; + ubyte tspan[80],new_span[80*2]; + long save_pos; + + skip = max((bitmap_header->w+79)/80,(bitmap_header->h+63)/64); + + new_w = bitmap_header->w / skip; + new_h = bitmap_header->h / skip; + + odd = new_w & 1; + + len = new_w * new_h + 4; + + put_sig(tiny_sig,ofile); + save_pos = cftell(ofile); + put_long(EVEN(len),ofile); + + put_word(new_w,ofile); + put_word(new_h,ofile); + + for (y=0;yrow_size; //bitmap_header->w; + + } + + if (compression_on) { + Assert(cfseek(ofile,save_pos,SEEK_SET)==0); + put_long(4+total_len,ofile); + Assert(cfseek(ofile,4+total_len,SEEK_CUR)==0); + if (total_len&1) cfputc(0,ofile); //pad to even + } + + return ((compression_on) ? (EVEN(total_len)+8+4) : (len+8)); +} +#endif + +int write_pbm(FILE *ofile,iff_bitmap_header *bitmap_header,int compression_on) /* writes a pbm iff file */ +{ + int ret; + long raw_size = EVEN(bitmap_header->w) * bitmap_header->h; + long body_size,tiny_size,pbm_size = 4 + BMHD_SIZE + 8 + EVEN(raw_size) + sizeof(pal_entry)*(1<nplanes)+8; + long save_pos; + +//printf("write_pbm\n"); + + put_sig(form_sig,ofile); + save_pos = ftell(ofile); + put_long(pbm_size+8,ofile); + put_sig(pbm_sig,ofile); + + ret = write_bmhd(ofile,bitmap_header); + if (ret != IFF_NO_ERROR) return ret; + + ret = write_pal(ofile,bitmap_header); + if (ret != IFF_NO_ERROR) return ret; + +#if WRITE_TINY + tiny_size = write_tiny(ofile,bitmap_header,compression_on); +#else + tiny_size = 0; +#endif + + body_size = write_body(ofile,bitmap_header,compression_on); + + pbm_size = 4 + BMHD_SIZE + body_size + tiny_size + sizeof(pal_entry)*(1<nplanes)+8; + + Assert(fseek(ofile,save_pos,SEEK_SET)==0); + put_long(pbm_size+8,ofile); + Assert(fseek(ofile,pbm_size+8,SEEK_CUR)==0); + + return ret; + +} + +//writes an IFF file from a grs_bitmap structure. writes palette if not null +//returns error codes - see IFF.H. +int iff_write_bitmap(char *ofilename,grs_bitmap *bm,ubyte *palette) +{ + FILE *ofile; + iff_bitmap_header bmheader; + int ret; + int compression_on; + + if (bm->bm_type == BM_RGB15) return IFF_BAD_BM_TYPE; + +#if COMPRESS + compression_on = (bm->bm_w>=MIN_COMPRESS_WIDTH); +#else + compression_on = 0; +#endif + + //fill in values in bmheader + + bmheader.x = bmheader.y = 0; + bmheader.w = bm->bm_w; + bmheader.h = bm->bm_h; + bmheader.type = TYPE_PBM; + bmheader.transparentcolor = iff_transparent_color; + bmheader.pagewidth = bm->bm_w; //I don't think it matters what I write + bmheader.pageheight = bm->bm_h; + bmheader.nplanes = 8; + bmheader.masking = mskNone; + if (iff_has_transparency) { + bmheader.masking |= mskHasTransparentColor; + } + bmheader.compression = (compression_on?cmpByteRun1:cmpNone); + + bmheader.xaspect = bmheader.yaspect = 1; //I don't think it matters what I write + bmheader.raw_data = bm->bm_data; + bmheader.row_size = bm->bm_rowsize; + + if (palette) memcpy(&bmheader.palette,palette,256*3); + + //open file and write + + if ((ofile = fopen(ofilename,"wb")) == NULL) {ret=IFF_NO_FILE; goto done;} + + ret = write_pbm(ofile,&bmheader,compression_on); + +done: + + fclose(ofile); + + return ret; +} + +//read in many brushes. fills in array of pointers, and n_bitmaps. +//returns iff error codes +int iff_read_animbrush(char *ifilename,grs_bitmap **bm_list,int max_bitmaps,int *n_bitmaps,ubyte *palette) +{ + int ret; //return code + FFILE ifile; + iff_bitmap_header bmheader; + long sig,form_len; + long form_type; + + *n_bitmaps=0; + + ret = open_fake_file(ifilename,&ifile); //read in entire file + if (ret != IFF_NO_ERROR) goto done; + + bmheader.raw_data = NULL; + + sig=get_sig(&ifile); + form_len = get_long(&ifile); + + if (sig != form_sig) { + ret = IFF_NOT_IFF; + goto done; + } + + form_type = get_sig(&ifile); + + if ((form_type == pbm_sig) || (form_type == ilbm_sig)) + ret = IFF_FORM_BITMAP; + else if (form_type == anim_sig) { + int anim_end = ifile.position + form_len - 4; + + while (ifile.position < anim_end && *n_bitmaps < max_bitmaps) { + + grs_bitmap *prev_bm; + + prev_bm = *n_bitmaps>0?bm_list[*n_bitmaps-1]:NULL; + + MALLOC(bm_list[*n_bitmaps] , grs_bitmap, 1 ); + + bm_list[*n_bitmaps]->bm_data = NULL; + + ret = iff_parse_bitmap(&ifile,bm_list[*n_bitmaps],form_type,*n_bitmaps>0?NULL:palette,prev_bm); + + if (ret != IFF_NO_ERROR) + goto done; + + (*n_bitmaps)++; + } + + if (ifile.position < anim_end) //ran out of room + ret = IFF_TOO_MANY_BMS; + + } + else + ret = IFF_UNKNOWN_FORM; + +done: + + close_fake_file(&ifile); + + return ret; + +} + +//text for error messges +char error_messages[] = { + "No error.\0" + "Not enough mem for loading or processing bitmap.\0" + "IFF file has unknown FORM type.\0" + "Not an IFF file.\0" + "Cannot open file.\0" + "Tried to save invalid type, like BM_RGB15.\0" + "Bad data in file.\0" + "ANIM file cannot be loaded with normal bitmap loader.\0" + "Normal bitmap file cannot be loaded with anim loader.\0" + "Array not big enough on anim brush read.\0" + "Unknown mask type in bitmap header.\0" + "Error reading file.\0" +}; + + +//function to return pointer to error message +char *iff_errormsg(int error_number) +{ + char *p = error_messages; + + while (error_number--) { + + if (!p) return NULL; + + p += strlen(p)+1; + + } + + return p; + +} + + diff --git a/include/3d.h b/include/3d.h new file mode 100644 index 00000000..34bfe28a --- /dev/null +++ b/include/3d.h @@ -0,0 +1,253 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/include/3d.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:16 $ + * + * Header file for 3d library + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:03 donut + * Import of d1x 1.37 source. + * + * Revision 1.2 1995/09/14 14:08:58 allender + * return value for g3_draw_sphere + * + * Revision 1.1 1995/05/05 08:48:41 allender + * Initial revision + * + * + * + */ + +#ifndef _3D_H +#define _3D_H + +extern int g3d_interp_outline; //if on, polygon models outlined in white +extern vms_vector Matrix_scale; +extern short highest_texture_num; + +//Structure for storing u,v,light values. This structure doesn't have a +//prefix because it was defined somewhere else before it was moved here +typedef struct g3s_uvl { + fix u,v,l; +} g3s_uvl; + +//Stucture to store clipping codes in a word +typedef struct g3s_codes { + ubyte or,and; //or is low byte, and is high byte +} g3s_codes; + +//flags for point structure +#define PF_PROJECTED 1 //has been projected, so sx,sy valid +#define PF_OVERFLOW 2 //can't project +#define PF_TEMP_POINT 4 //created during clip +#define PF_UVS 8 //has uv values set +#define PF_LS 16 //has lighting values set + +//clipping codes flags + +#define CC_OFF_LEFT 1 +#define CC_OFF_RIGHT 2 +#define CC_OFF_BOT 4 +#define CC_OFF_TOP 8 +#define CC_BEHIND 0x80 + +//Used to store rotated points for mines. Has frame count to indictate +//if rotated, and flag to indicate if projected. +typedef struct g3s_point { + vms_vector p3_vec; //reference as vector... +#ifdef D1XD3D + vms_vector p3_orig; +#endif + fix p3_u,p3_v,p3_l; + fix p3_sx,p3_sy; //screen x&y + ubyte p3_codes; //clipping codes + ubyte p3_flags; //projected? + short p3_pad; //keep structure longwork aligned +} g3s_point; + +//macros to reference x,y,z elements of a 3d point +#define p3_x p3_vec.x +#define p3_y p3_vec.y +#define p3_z p3_vec.z + +//An object, such as a robot +typedef struct g3s_object { + vms_vector o3_pos; //location of this object + vms_angvec o3_orient; //orientation of this object + int o3_nverts; //number of points in the object + int o3_nfaces; //number of faces in the object + + //this will be filled in later + +} g3s_object; + +//Functions in library + +//3d system startup and shutdown: + +//initialize the 3d system +void g3_init(void); + +//close down the 3d system +void g3_close(void); + + +//Frame setup functions: + +//start the frame +void g3_start_frame(void); + +//set view from x,y,z & p,b,h, zoom. Must call one of g3_set_view_*() +void g3_set_view_angles(vms_vector *view_pos,vms_angvec *view_orient,fix zoom); + +//set view from x,y,z, viewer matrix, and zoom. Must call one of g3_set_view_*() +void g3_set_view_matrix(vms_vector *view_pos,vms_matrix *view_matrix,fix zoom); + +//end the frame +void g3_end_frame(void); + +//draw a horizon +void g3_draw_horizon(int sky_color,int ground_color); + +//get vectors that are edge of horizon +int g3_compute_sky_polygon(fix *points_2d,vms_vector *vecs); + +//Instancing + +//instance at specified point with specified orientation +void g3_start_instance_matrix(vms_vector *pos,vms_matrix *orient); + +//instance at specified point with specified orientation +void g3_start_instance_angles(vms_vector *pos,vms_angvec *angles); + +//pops the old context +void g3_done_instance(); + +//Misc utility functions: + +//get current field of view. Fills in angle for x & y +void g3_get_FOV(fixang *fov_x,fixang *fov_y); + +//get zoom. For a given window size, return the zoom which will achieve +//the given FOV along the given axis. +fix g3_get_zoom(char axis,fixang fov,short window_width,short window_height); + +//returns the normalized, unscaled view vectors +void g3_get_view_vectors(vms_vector *forward,vms_vector *up,vms_vector *right); + +//returns true if a plane is facing the viewer. takes the unrotated surface +//normal of the plane, and a point on it. The normal need not be normalized +bool g3_check_normal_facing(vms_vector *v,vms_vector *norm); + +//Point definition and rotation functions: + +//specify the arrays refered to by the 'pointlist' parms in the following +//functions. I'm not sure if we will keep this function, but I need +//it now. +//void g3_set_points(g3s_point *points,vms_vector *vecs); + +//returns codes_and & codes_or of a list of points numbers +g3s_codes g3_check_codes(int nv,g3s_point **pointlist); + +//rotates a point. returns codes. does not check if already rotated +ubyte g3_rotate_point(g3s_point *dest,vms_vector *src); + +//projects a point +void g3_project_point(g3s_point *point); + +//calculate the depth of a point - returns the z coord of the rotated point +fix g3_calc_point_depth(vms_vector *pnt); + +//from a 2d point, compute the vector through that point +void g3_point_2_vec(vms_vector *v,short sx,short sy); + +//code a point. fills in the p3_codes field of the point, and returns the codes +ubyte g3_code_point(g3s_point *point); + +//delta rotation functions +vms_vector *g3_rotate_delta_x(vms_vector *dest,fix dx); +vms_vector *g3_rotate_delta_y(vms_vector *dest,fix dy); +vms_vector *g3_rotate_delta_z(vms_vector *dest,fix dz); +vms_vector *g3_rotate_delta_vec(vms_vector *dest,vms_vector *src); +ubyte g3_add_delta_vec(g3s_point *dest,g3s_point *src,vms_vector *deltav); + +//Drawing functions: + +//draw a flat-shaded face. +//returns 1 if off screen, 0 if drew +bool g3_draw_poly(int nv,g3s_point **pointlist); + +//draw a texture-mapped face. +//returns 1 if off screen, 0 if drew +bool g3_draw_tmap(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bm); + +//draw a sortof sphere - i.e., the 2d radius is proportional to the 3d +//radius, but not to the distance from the eye +int g3_draw_sphere(g3s_point *pnt,fix rad); + +//@@//return ligting value for a point +//@@fix g3_compute_lighting_value(g3s_point *rotated_point,fix normval); + + +//like g3_draw_poly(), but checks to see if facing. If surface normal is +//NULL, this routine must compute it, which will be slow. It is better to +//pre-compute the normal, and pass it to this function. When the normal +//is passed, this function works like g3_check_normal_facing() plus +//g3_draw_poly(). +//returns -1 if not facing, 1 if off screen, 0 if drew +bool g3_check_and_draw_poly(int nv,g3s_point **pointlist,vms_vector *norm,vms_vector *pnt); +bool g3_check_and_draw_tmap(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bm,vms_vector *norm,vms_vector *pnt); + +//draws a line. takes two points. +bool g3_draw_line(g3s_point *p0,g3s_point *p1); + +//draw a polygon that is always facing you +//returns 1 if off screen, 0 if drew +bool g3_draw_rod_flat(g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width); + +//draw a bitmap object that is always facing you +//returns 1 if off screen, 0 if drew +bool g3_draw_rod_tmap(grs_bitmap *bitmap,g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width,fix light); + +//draws a bitmap with the specified 3d width & height +//returns 1 if off screen, 0 if drew +bool g3_draw_bitmap(vms_vector *pos,fix width,fix height,grs_bitmap *bm,int orientation); + +//specifies 2d drawing routines to use instead of defaults. Passing +//NULL for either or both restores defaults +void g3_set_special_render(void (*tmap_drawer)(),void (*flat_drawer)(),int (*line_drawer)(fix, fix, fix, fix)); + +//Object functions: + +//gives the interpreter an array of points to use +void g3_set_interp_points(g3s_point *pointlist); + +//calls the object interpreter to render an object. The object renderer +//is really a seperate pipeline. returns true if drew +bool g3_draw_polygon_model(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,fix light,fix *glow_values); + +//init code for bitmap models +void g3_init_polygon_model(void *model_ptr); + +//alternate interpreter for morphing object +bool g3_draw_morphing_model(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,fix light,vms_vector *new_points); + +// routine to convert little to big endian in polygon model data +void swap_polygon_model_data(ubyte *data); + +#endif + diff --git a/include/args.h b/include/args.h new file mode 100644 index 00000000..19c27302 --- /dev/null +++ b/include/args.h @@ -0,0 +1,55 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/include/args.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:16 $ + * + * Prototypes for accessing arguments. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:08 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:33:09 john + * New version 2.0, which has no anonymous unions, builds with + * Watcom 10.0, and doesn't require parsing BITMAPS.TBL. + * + * Revision 1.4 1994/07/11 16:27:28 matt + * Took out prototypes for netipx funcs + * + * Revision 1.3 1994/05/11 19:45:34 john + * *** empty log message *** + * + * Revision 1.2 1994/05/09 17:02:55 john + * Split command line parameters into arg.c and arg.h. + * Also added /dma, /port, /irq to digi.c + * + * Revision 1.1 1994/05/09 16:47:49 john + * Initial revision + * + * + */ + + + +#ifndef _ARGS_H +#define _ARGS_H + +extern int Num_args; +extern char * Args[]; +extern int args_find( char * s ); +extern void args_init( int argc, char **argv ); + +#endif diff --git a/include/byteswap.h b/include/byteswap.h new file mode 100644 index 00000000..26f88f10 --- /dev/null +++ b/include/byteswap.h @@ -0,0 +1,35 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + + +#ifndef _BYTESWAP_H +#define _BYTESWAP_H + +#include "pstypes.h" + +extern ushort swapshort(ushort s); +extern uint swapint(uint i); + +#define SWAPSHORT(x) (((ubyte)x << 8) | (((ushort)x) >> 8)) +#define SWAPINT(x) ((x<<24) | (((ulong)x) >> 24) | ((x &0x0000ff00) << 8) | ((x & 0x00ff00000) >> 8)) + +#ifndef MACINTOSH +#define INTEL_INT(x) x +#define INTEL_SHORT(x) x +#else +#define INTEL_INT(x) SWAPINT(x) +#define INTEL_SHORT(x) SWAPSHORT(x) +#endif + +#endif diff --git a/include/cfile.h b/include/cfile.h new file mode 100644 index 00000000..ae8bcab7 --- /dev/null +++ b/include/cfile.h @@ -0,0 +1,58 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + + +#ifndef _CFILE_H +#define _CFILE_H + +typedef struct CFILE { + FILE *file; + int size; + int lib_offset; + int raw_position; +} CFILE; + +//Specify the name of the hogfile. Returns 1 if hogfile found & had files +int cfile_init(char *hogname); + +CFILE * cfopen(char * filename, char * mode); +int cfilelength( CFILE *fp ); // Returns actual size of file... +size_t cfread( void * buf, size_t elsize, size_t nelem, CFILE * fp ); +void cfclose( CFILE * cfile ); +int cfgetc( CFILE * fp ); +int cfseek( CFILE *fp, long int offset, int where ); +int cftell( CFILE * fp ); +char * cfgets( char * buf, size_t n, CFILE * fp ); + +int cfexist( char * filename ); // Returns true if file exists on disk (1) or in hog (2). + +// Allows files to be gotten from an alternate hog file. +// Passing NULL disables this. +// Returns 1 if hogfile found (& contains file), else 0. +// If NULL passed, returns 1 +int cfile_use_alternate_hogfile( char * name ); + +// All cfile functions will check this directory if no file exists +// in the current directory. +void cfile_use_alternate_hogdir( char * path ); + +//tell cfile about your critical error counter +void cfile_set_critical_error_counter_ptr(int *ptr); + +// prototypes for reading basic types from cfile +int cfile_read_int(CFILE *file); +short cfile_read_short(CFILE *file); +byte cfile_read_byte(CFILE *file); + +#endif diff --git a/include/checker.h b/include/checker.h new file mode 100644 index 00000000..e97e41b5 --- /dev/null +++ b/include/checker.h @@ -0,0 +1,34 @@ +//checker.h added 05/17/99 Matt Mueller +//FD_* on linux use asm, but checker doesn't like it. Borrowed these non-asm versions outta +#include + +#ifdef __CHECKER__ + +#undef FD_ZERO(set) +#undef FD_SET(d, set) +#undef FD_CLR(d, set) +#undef FD_ISSET(d, set) + +# define FD_ZERO(set) \ + do { \ + unsigned int __i; \ + for (__i = 0; __i < sizeof (__fd_set) / sizeof (__fd_mask); ++__i) \ + ((__fd_mask *) set)[__i] = 0; \ + } while (0) +# define FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) +# define FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) +# define FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) + +//checker doesn't seem to handle jmp's correctly... +#undef setjmp(env) +#define setjmp(env) __chcksetjmp(env) +#undef longjmp(env,val) +#define longjmp(env,val) __chcklongjmp(env,val) + +int __chcklongjmp(jmp_buf buf,int val); +int __chcksetjmp(jmp_buf buf); + +void chcksetwritable(char * p, int size); +void chcksetunwritable(char * p, int size); + +#endif diff --git a/include/cmd.h b/include/cmd.h new file mode 100644 index 00000000..e4ed2538 --- /dev/null +++ b/include/cmd.h @@ -0,0 +1,21 @@ +#ifndef _CMD_H_ +#define _CMD_H_ 1 + + + +/* Maximum length for a single command */ +#define CMD_MAX_LENGTH 2048 +/* Maximum number of tokens per command */ +#define CMD_MAX_TOKENS 64 + +/* Parse an input string */ +void cmd_parse(char *input); + +typedef void (*xcommand_t)(void); + +/* Warning: these commands are NOT REENTRANT. Do not attempt to thread them! */ +void cmd_tokenize(char *string); +int cmd_argc(void); +char *cmd_argv(int w); + +#endif /* _CMD_H_ */ diff --git a/include/console.h b/include/console.h new file mode 100644 index 00000000..a9bec931 --- /dev/null +++ b/include/console.h @@ -0,0 +1,46 @@ +/* Console */ + +#ifndef _CONSOLE_H_ +#define _CONSOLE_H_ 1 + +/* Priority levels */ +#define CON_CRITICAL -2 +#define CON_URGENT -1 +#define CON_NORMAL 0 +#define CON_VERBOSE 1 +#define CON_DEBUG 2 + +int con_init(void); +void con_printf(int level, char *fmt, ...); + +void con_draw(void); +void con_update(void); + + +/* CVar stuff */ +typedef struct cvar_s +{ + char *name; + char *string; + dboolean archive; + float value; + struct cvar_s *next; +} cvar_t; + +extern cvar_t *cvar_vars; + +/* Register a CVar with the name and string and optionally archive elements set */ +void cvar_registervariable (cvar_t *cvar); + +/* Equivalent to typing at the console */ +void cvar_set(char *cvar_name, char *value); + +/* Get a CVar's value */ +float cvar(char *cvar_name); + +/* Console CVars */ +/* How discriminating we are about which messages are displayed */ +cvar_t con_threshold; + +#endif /* _CONSOLE_H_ */ + diff --git a/include/d.bat b/include/d.bat new file mode 100644 index 00000000..9038a864 --- /dev/null +++ b/include/d.bat @@ -0,0 +1,2 @@ +@wvideo test +@fix diff --git a/include/d_delay.h b/include/d_delay.h new file mode 100644 index 00000000..ce519dc9 --- /dev/null +++ b/include/d_delay.h @@ -0,0 +1,13 @@ +//added on 9/2/98 by Matt Mueller + +#ifndef _D_DELAY +#define _D_DELAY + +//#ifdef __LINUX__ + void d_delay (int ms); +/*#else +#include +#define d_delay delay +#endif + */ +#endif diff --git a/include/d_io.h b/include/d_io.h new file mode 100644 index 00000000..71a8c7e7 --- /dev/null +++ b/include/d_io.h @@ -0,0 +1,18 @@ +// some misc. file/disk routines +// Arne de Bruijn, 1998 +#ifndef _D_IO_H +#define _D_IO_H + +#if (defined(__MSDOS__) && !defined(__DJGPP__)) || defined(__WINDOWS__) +#include +#else +#include +#endif + +extern long ffilelength(FILE *fh); +extern long filelength(int fd); +unsigned long d_getdiskfree(); +// remove extension from filename, doesn't work with paths. +void removeext(const char *filename, char *out); + +#endif diff --git a/include/dtypes.h b/include/dtypes.h new file mode 100644 index 00000000..6b6686af --- /dev/null +++ b/include/dtypes.h @@ -0,0 +1,34 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifndef _TYPES_H +#define _TYPES_H + +//define a byte +typedef signed char byte; + +//define unsigned types; +typedef unsigned char ubyte; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; + +//define a boolean +typedef ubyte bool; + +#ifndef NULL +#define NULL 0 +#endif + +#endif + diff --git a/include/dtypes.inc b/include/dtypes.inc new file mode 100644 index 00000000..4e7fd9e7 --- /dev/null +++ b/include/dtypes.inc @@ -0,0 +1,25 @@ +; THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +; SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +; END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +; ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +; IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +; SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +; FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +; CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +; AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +; COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +option expr32 + +IFNDEF types_inc +types_inc EQU 1 + +ubyte typedef byte +ushort typedef word +long typedef dword +uint typedef dword +ulong typedef dword + +bool typedef ubyte + +ENDIF + diff --git a/include/error.h b/include/error.h new file mode 100644 index 00000000..b3ee671a --- /dev/null +++ b/include/error.h @@ -0,0 +1,146 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/include/error.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:16 $ + * + * Header for error handling/printing/exiting code + * + * $Log: not supported by cvs2svn $ + * Revision 1.3 1999/10/14 04:48:21 donut + * alpha fixes, and gl_font args + * + * Revision 1.2 1999/08/05 22:53:41 sekmu + * + * D3D patch(es) from ADB + * + * Revision 1.1.1.1 1999/06/14 22:02:09 donut + * Import of d1x 1.37 source. + * + * Revision 1.12 1994/06/17 15:22:46 matt + * Added pragma for Error() for when NDEBUG + * + * Revision 1.11 1994/03/07 13:22:14 matt + * Since the Error() function has 'aborts' set in pragma, we do a jmp + * to the function rather than call. + * + * Revision 1.10 1994/02/17 12:37:15 matt + * Combined two pragma's for Error(), since second superseded the first + * + * Revision 1.9 1994/02/10 18:02:53 matt + * Changed 'if DEBUG_ON' to 'ifndef NDEBUG' + * + * Revision 1.8 1994/02/09 15:18:29 matt + * Added pragma saying that Error() never returns + * + * Revision 1.7 1993/10/19 12:57:53 matt + * If DEBUG_ON not defined, define it to be 1 + * + * Revision 1.6 1993/10/15 21:40:39 matt + * Made error functions generate int3's if debugging on + * + * Revision 1.5 1993/10/14 15:29:22 matt + * Added new function clear_warn_func() + * + * Revision 1.4 1993/10/08 16:16:47 matt + * Made Assert() call function _Assert(), rather to do 'if...' inline. + * + * Revision 1.3 1993/09/29 11:39:07 matt + * Added Assert() macro, like the system one, but calls Error() + * + * Revision 1.2 1993/09/27 11:47:03 matt + * Added function set_warn_func() + * + * Revision 1.1 1993/09/23 20:17:46 matt + * Initial revision + * + * + */ + +#ifdef __GNUC__ +#define __noreturn __attribute__ ((noreturn)) +#define __format __attribute__ ((format (printf, 1, 2))) +#else +#define __noreturn +#define __format +#endif + +int error_init(char *fmt,...); //init error system, set default message, returns 0=ok +void set_exit_message(char *fmt,...); //specify message to print at exit +void Warning(char *fmt,...); //print out warning message to user +void set_warn_func(void (*f)(char *s));//specifies the function to call with warning messages +void clear_warn_func(void (*f)(char *s));//say this function no longer valid +void _Assert(int expr,char *expr_text,char *filename,int linenum); //assert func +void Error(char *fmt,...) __noreturn __format; //exit with error code=1, print message +void Assert(int expr); +void Int3(); +#ifndef NDEBUG //macros for debugging + +#ifdef __GNUC__ +//edited 05/17/99 Matt Mueller - I dunno if there is a non-asm way to do a "breakpoint" so this'll have to do. +#ifdef NO_ASM +//#define Int3() Error("int 3 %s:%i\n",__FILE__,__LINE__); +//#define Int3() {volatile int a=0,b=1/a;} +#define Int3() ((void)0) +#else +#define Int3() asm("int $3") +#endif +//end edit -MM + +#elif defined __WATCOMC__ +void Int3(void); //generate int3 +#pragma aux Int3 = "int 3h"; +#elif defined _MSC_VER +#define Int3() __asm { int 3 } +#else +#error Unknown Compiler! +#endif + +#define Assert(expr) ((expr)?(void)0:(void)_Assert(0,#expr,__FILE__,__LINE__)) + +#ifdef __GNUC__ +//#define Error(format, args...) ({ /*Int3();*/ Error(format , ## args); }) +#elif defined __WATCOMC__ +//make error do int3, then call func +#pragma aux Error aborts = \ + "int 3" \ + "jmp Error"; + +//#pragma aux Error aborts; +#else +// DPH: I'm not going to bother... it's not needed... :-) +#endif + +#ifdef __WATCOMC__ +//make assert do int3 (if expr false), then call func +#pragma aux _Assert parm [eax] [edx] [ebx] [ecx] = \ + "test eax,eax" \ + "jnz no_int3" \ + "int 3" \ + "no_int3:" \ + "call _Assert"; +#endif + +#else //macros for real game + +#ifdef __WATCOMC__ +#pragma aux Error aborts; +#endif +//Changed Assert and Int3 because I couldn't get the macros to compile -KRB +#define Assert(__ignore) ((void)0) +//void Assert(int expr); +#define Int3() ((void)0) +//void Int3(); +#endif diff --git a/include/findfile.h b/include/findfile.h new file mode 100644 index 00000000..5fbb9f5c --- /dev/null +++ b/include/findfile.h @@ -0,0 +1,17 @@ +// Empty file +typedef struct FILEFINDSTRUCT { + unsigned long size; + char name[256]; +} FILEFINDSTRUCT; +int FileFindFirst(char *search_str, FILEFINDSTRUCT *ffstruct); +int FileFindNext(FILEFINDSTRUCT *ffstruct); +int FileFindClose(void); + +typedef struct FILETIMESTRUCT { + unsigned short date,time; +} FILETIMESTRUCT; + +//the both return 0 if no error +//int GetFileDateTime(int filehandle, FILETIMESTRUCT *ftstruct); +//int SetFileDateTime(int filehandle, FILETIMESTRUCT *ftstruct); +// diff --git a/include/fix.h b/include/fix.h new file mode 100644 index 00000000..879f42cb --- /dev/null +++ b/include/fix.h @@ -0,0 +1,2 @@ +/* fix.h points to maths.h */ +#include "maths.h" diff --git a/include/gr.h b/include/gr.h new file mode 100644 index 00000000..b5f0713d --- /dev/null +++ b/include/gr.h @@ -0,0 +1,467 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifndef _GR_H +#define _GR_H + +#include "pstypes.h" +#include "fix.h" + +#ifdef MACINTOSH +#define SWAP_0_255 1 // swap black and white +#define TRANSPARENCY_COLOR 0 // palette entry of transparency color -- 0 on the mac +#else +#define SWAP_0_255 0 // no swapping for PC people +#define TRANSPARENCY_COLOR 255 // palette entry of transparency color -- 255 on the PC +#endif + +#define GR_FADE_LEVELS 34 +#define GR_ACTUAL_FADE_LEVELS 32 + +#define GWIDTH grd_curcanv->cv_bitmap.bm_w +#define GHEIGHT grd_curcanv->cv_bitmap.bm_h +#define SWIDTH (grd_curscreen->sc_w) +#define SHEIGHT (grd_curscreen->sc_h) + + +extern int Gr_scanline_darkening_level; + +typedef struct _grs_point { + fix x,y; +} grs_point; + +//these are control characters that have special meaning in the font code + +#define CC_COLOR 1 //next char is new foreground color +#define CC_LSPACING 2 //next char specifies line spacing +#define CC_UNDERLINE 3 //next char is underlined + +//now have string versions of these control characters (can concat inside a string) + +#define CC_COLOR_S "\x1" //next char is new foreground color +#define CC_LSPACING_S "\x2" //next char specifies line spacing +#define CC_UNDERLINE_S "\x3" //next char is underlined + +typedef struct _old_grs_font { + short ft_w,ft_h; // Width and height in pixels + short ft_flags; // Proportional? + short ft_baseline; // + ubyte ft_minchar, // The first and last chars defined by + ft_maxchar; // This font + short ft_bytewidth; // Width in unsigned chars + ubyte * ft_data; // Ptr to raw data. + ubyte ** ft_chars; // Ptrs to data for each char (required for prop font) + short * ft_widths; // Array of widths (required for prop font) + ubyte * ft_kerndata; // Array of kerning triplet data +} __pack__ old_grs_font; + +#define BM_LINEAR 0 +#define BM_MODEX 1 +#define BM_SVGA 2 +#define BM_RGB15 3 //5 bits each r,g,b stored at 16 bits +#define BM_SVGA15 4 +#ifdef OGL +#define BM_OGL 5 +#endif + +//@@// Define these modes for Gameplay too, since the game was developed under +//@@// DOS, we will adapt these modes to other systems thru rendering. +#define SM(w,h) ((((u_int32_t)w)<<16)+(((u_int32_t)h)&0xFFFF)) +#define SM_W(m) (m>>16) +#define SM_H(m) (m&0xFFFF) + +#define SM_ORIGINAL 0 +/* +#define SM_ORIGINAL -1 +#define SM_320x200C 0 +#define SM_320x200U 1 +#define SM_320x240U 2 +#define SM_360x200U 3 +#define SM_360x240U 4 +#define SM_376x282U 5 +#define SM_320x400U 6 +#define SM_320x480U 7 +#define SM_360x400U 8 +#define SM_360x480U 9 +#define SM_360x360U 10 +#define SM_376x308U 11 +#define SM_376x564U 12 +#define SM_640x400V 13 +#define SM_640x480V 14 +#define SM_800x600V 15 +#define SM_1024x768V 16 +#define SM_640x480V15 17 +#define SM_800x600V15 18 +#define SM_1280x1024V 19 +*/ + +#define BM_FLAG_TRANSPARENT 1 +#define BM_FLAG_SUPER_TRANSPARENT 2 +#define BM_FLAG_NO_LIGHTING 4 +#define BM_FLAG_RLE 8 // A run-length encoded bitmap. +#define BM_FLAG_PAGED_OUT 16 // This bitmap's data is paged out. +#define BM_FLAG_RLE_BIG 32 // for bitmaps that RLE to > 255 per row (i.e. cockpits) + +typedef struct _grs_bitmap { + short bm_x,bm_y; // Offset from parent's origin + short bm_w,bm_h; // width,height + byte bm_type; // 0=Linear, 1=ModeX, 2=SVGA + byte bm_flags; // bit 0 on means it has transparency. + // bit 1 on means it has supertransparency + // bit 2 on means it doesn't get passed through lighting. + short bm_rowsize; // unsigned char offset to next row + unsigned char * bm_data; // ptr to pixel data... + // Linear = *parent+(rowsize*y+x) + // ModeX = *parent+(rowsize*y+x/4) + // SVGA = *parent+(rowsize*y+x) + unsigned short bm_handle; //for application. initialized to 0 + ubyte avg_color; // Average color of all pixels in texture map. + byte unused; // to 4-byte align. +#ifdef OGL + struct _ogl_texture *gltexture; + struct _grs_bitmap *bm_parent; +#endif + +} grs_bitmap; + +typedef struct _new_grs_font { + short ft_w,ft_h; // Width and height in pixels + short ft_flags; // Proportional? + short ft_baseline; // + ubyte ft_minchar, // The first and last chars defined by + ft_maxchar; // This font + short ft_bytewidth; // Width in unsigned chars + ubyte * ft_data; // Ptr to raw data. + ubyte ** ft_chars; // Ptrs to data for each char (required for prop font) + short * ft_widths; // Array of widths (required for prop font) + ubyte * ft_kerndata; // Array of kerning triplet data + + +#ifdef OGL + old_grs_font * oldfont; + grs_bitmap *ft_bitmaps; + grs_bitmap ft_parent_bitmap; +#endif +} grs_font; + +typedef struct _grs_canvas { + grs_bitmap cv_bitmap; // the bitmap for this canvas + short cv_color; // current color + short cv_drawmode; // fill,XOR,etc. + grs_font * cv_font; // the currently selected font + short cv_font_fg_color; // current font foreground color (-1==Invisible) + short cv_font_bg_color; // current font background color (-1==Invisible) +} grs_canvas; + +//shortcuts +#define cv_w cv_bitmap.bm_w +#define cv_h cv_bitmap.bm_h + +typedef struct _grs_screen { // This is a video screen + grs_canvas sc_canvas; // Represents the entire screen + int sc_mode; // Video mode number + short sc_w, sc_h; // Actual Width and Height + fix sc_aspect; //aspect ratio (w/h) for this screen +} grs_screen; + + +//========================================================================= +// System functions: +// setup and set mode. this creates a grs_screen structure and sets +// grd_curscreen to point to it. grs_curcanv points to this screen's +// canvas. Saves the current VGA state and screen mode. + +int gr_init(void); + +// This function sets up the main screen. It should be called whenever +// the video mode changes. +int gr_init_screen(int mode, int w, int h, int x, int y, int rowsize, ubyte *data); + +int gr_check_mode(int mode); +int gr_set_mode(u_int32_t mode); + + +// These 4 functions actuall change screen colors. + +extern void gr_pal_fade_out(unsigned char * pal); +extern void gr_pal_fade_in(unsigned char * pal); +extern void gr_pal_clear(void); +extern void gr_pal_setblock( int start, int number, unsigned char * pal ); +extern void gr_pal_getblock( int start, int number, unsigned char * pal ); + + +extern unsigned char *gr_video_memory; + // All graphic modules will define this value. + +//shut down the 2d. Restore the screen mode. +void gr_close(void); + +//========================================================================= +// Canvas functions: + +// Makes a new canvas. allocates memory for the canvas and its bitmap, +// including the raw pixel buffer. + +grs_canvas *gr_create_canvas(int w, int h); +#if defined(POLY_ACC) +grs_canvas *gr_create_canvas2(int w, int h, int type); +#endif + +// Creates a canvas that is part of another canvas. this can be used to make +// a window on the screen. the canvas structure is malloc'd; the address of +// the raw pixel data is inherited from the parent canvas. + +grs_canvas *gr_create_sub_canvas(grs_canvas *canv,int x,int y,int w, int h); + +// Initialize the specified canvas. the raw pixel data buffer is passed as +// a parameter. no memory allocation is performed. + +void gr_init_canvas(grs_canvas *canv,unsigned char *pixdata,int pixtype, int w,int h); + +// Initialize the specified sub canvas. no memory allocation is performed. + +void gr_init_sub_canvas(grs_canvas *new,grs_canvas *src,int x,int y,int w, int h); + +// Free up the canvas and its pixel data. + +void gr_free_canvas(grs_canvas *canv); + +// Free up the canvas. do not free the pixel data, which belongs to the +// parent canvas. + +void gr_free_sub_canvas(grs_canvas *canv); + +// Clear the current canvas to the specified color +void gr_clear_canvas(int color); + +//========================================================================= +// Bitmap functions: + +// Allocate a bitmap and its pixel data buffer. +grs_bitmap *gr_create_bitmap(int w,int h); + +// Allocated a bitmap and makes its data be raw_data that is already somewhere. +grs_bitmap *gr_create_bitmap_raw(int w, int h, unsigned char * raw_data ); + +#if defined(POLY_ACC) +// Allocates a bitmap of a specific type. data is either NULL or raw data. +grs_bitmap *gr_create_bitmap2(int w, int h, int type, void *data ); +#endif + +// Creates a bitmap which is part of another bitmap +grs_bitmap *gr_create_sub_bitmap(grs_bitmap *bm,int x,int y,int w, int h); + +// Free the bitmap and its pixel data +void gr_free_bitmap(grs_bitmap *bm); + +// Free the bitmap, but not the pixel data buffer +void gr_free_sub_bitmap(grs_bitmap *bm); + +void gr_bm_pixel( grs_bitmap * bm, int x, int y, unsigned char color ); +void gr_bm_upixel( grs_bitmap * bm, int x, int y, unsigned char color ); +void gr_bm_ubitblt( int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); +void gr_bm_ubitbltm(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); + +#ifdef MACINTOSH +void gr_bm_ubitblt_double(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap *src, grs_bitmap *dest); +void gr_linear_movsd_double(ubyte *src, ubyte *dest, int num_pixels); +#endif + +void gr_update_buffer( void * sbuf1, void * sbuf2, void * dbuf, int size ); + +//========================================================================= +// Color functions: + +// When this function is called, the guns are set to gr_palette, and +// the palette stays the same until gr_close is called + +void gr_use_palette_table(char * filename ); +void gr_copy_palette(ubyte *gr_palette, ubyte *pal, int size); + +//========================================================================= +// Drawing functions: + +// For solid, XOR, or other fill modes. +int gr_set_drawmode(int mode); + +// Sets the color in the current canvas. should be a macro +// Use: gr_setcolor(int color); +void gr_setcolor(int color); + +// Draw a polygon into the current canvas in the current color and drawmode. +// verts points to an ordered list of x,y pairs. the polygon should be +// convex; a concave polygon will be handled in some reasonable manner, +// but not necessarily shaded as a concave polygon. It shouldn't hang. +// probably good solution is to shade from minx to maxx on each scan line. +// int should really be fix +int gr_poly(int nverts,int *verts); +int gr_upoly(int nverts,int *verts); + + +// Draws a point into the current canvas in the current color and drawmode. +void gr_pixel(int x,int y); +void gr_upixel(int x,int y); + +// Gets a pixel; +unsigned char gr_gpixel( grs_bitmap * bitmap, int x, int y ); +unsigned char gr_ugpixel( grs_bitmap * bitmap, int x, int y ); + +// Draws a line into the current canvas in the current color and drawmode. +int gr_line(fix x0,fix y0,fix x1,fix y1); +int gr_uline(fix x0,fix y0,fix x1,fix y1); + +// Draws an anti-aliased line into the current canvas in the current color and drawmode. +int gr_aaline(fix x0,fix y0,fix x1,fix y1); +int gr_uaaline(fix x0,fix y0,fix x1,fix y1); + +// Draw the bitmap into the current canvas at the specified location. +void gr_bitmap(int x,int y,grs_bitmap *bm); +void gr_ubitmap(int x,int y,grs_bitmap *bm); +// bitmap function with transparency +void gr_bitmapm( int x, int y, grs_bitmap *bm ); +void gr_ubitmapm( int x, int y, grs_bitmap *bm ); + +// Draw a rectangle into the current canvas. +void gr_rect(int left,int top,int right,int bot); +void gr_urect(int left,int top,int right,int bot); + +// Draw a filled circle +int gr_disk(fix x,fix y,fix r); +int gr_udisk(fix x,fix y,fix r); + +// Draw an outline circle +int gr_circle(fix x,fix y,fix r); +int gr_ucircle(fix x,fix y,fix r); + +// Draw an unfilled rectangle into the current canvas +void gr_box(int left,int top,int right,int bot); +void gr_ubox(int left,int top,int right,int bot); + +void gr_scanline( int x1, int x2, int y ); +void gr_uscanline( int x1, int x2, int y ); + + +// Reads in a font file... current font set to this one. +grs_font * gr_init_font( char * fontfile ); +void gr_close_font( grs_font * font ); + +//remap a font, re-reading its data & palette +void gr_remap_font( grs_font *font, char * fontname ); + +//remap (by re-reading) all the color fonts +void gr_remap_color_fonts(); + +// Writes a string using current font. Returns the next column after last char. +void gr_set_fontcolor( int fg, int bg ); +void gr_set_curfont( grs_font * new ); +int gr_string(int x, int y, char *s ); +int gr_ustring(int x, int y, char *s ); +int gr_printf( int x, int y, char * format, ... ); +int gr_uprintf( int x, int y, char * format, ... ); +void gr_get_string_size(char *s, int *string_width, int *string_height, int *average_width ); + + +// From roller.c +void rotate_bitmap(grs_bitmap *bp, grs_point *vertbuf, int light_value); + +// From scale.c +void scale_bitmap(grs_bitmap *bp, grs_point *vertbuf, int orientation ); + +//=========================================================================== +// Global variables +extern grs_canvas *grd_curcanv; //active canvas +extern grs_screen *grd_curscreen; //active screen +extern unsigned char Test_bitmap_data[64*64]; + +//shortcut to look at current font +#define grd_curfont grd_curcanv->cv_font + +extern unsigned int FixDivide( unsigned int x, unsigned int y ); + +extern void gr_show_canvas( grs_canvas *canv ); +extern void gr_set_current_canvas( grs_canvas *canv ); + +//flags for fonts +#define FT_COLOR 1 +#define FT_PROPORTIONAL 2 +#define FT_KERNED 4 + +extern void gr_vesa_update( grs_bitmap * source1, grs_bitmap * dest, grs_bitmap * source2 ); + +// Special effects +extern void gr_snow_out(int num_dots); + +extern void test_rotate_bitmap(void); +extern void rotate_bitmap(grs_bitmap *bp, grs_point *vertbuf, int light_value); + +extern ubyte gr_palette[256*3]; +extern ubyte gr_fade_table[256*GR_FADE_LEVELS]; +extern ubyte gr_inverse_table[32*32*32]; + +extern ushort gr_palette_selector; +extern ushort gr_inverse_table_selector; +extern ushort gr_fade_table_selector; + +// Remaps a bitmap into the current palette. If transparent_color is between 0 and 255 +// then all occurances of that color are mapped to whatever color the 2d uses for +// transparency. This is normally used right after a call to iff_read_bitmap like +// this: +// iff_error = iff_read_bitmap(filename,new,BM_LINEAR,newpal); +// if (iff_error != IFF_NO_ERROR) Error("Can't load IFF file <%s>, error=%d",filename,iff_error); +// if ( iff_has_transparency ) +// gr_remap_bitmap( new, newpal, iff_transparent_color ); +// else +// gr_remap_bitmap( new, newpal, -1 ); +extern void gr_remap_bitmap( grs_bitmap * bmp, ubyte * palette, int transparent_color, int super_transparent_color ); + +// Same as above, but searches using gr_find_closest_color which uses 18-bit accurracy +// instaed of 15bit when translating colors. +extern void gr_remap_bitmap_good( grs_bitmap * bmp, ubyte * palette, int transparent_color, int super_transparent_color ); + +extern void gr_palette_step_up( int r, int g, int b ); + +extern void gr_bitmap_check_transparency( grs_bitmap * bmp ); + +// Allocates a selector that has a base address at 'address' and length 'size'. +// Returns 0 if successful... BE SURE TO CHECK the return value since there +// is a limited number of selectors available!!! +extern int get_selector( void * address, int size, unsigned int * selector ); + +// Assigns a selector to a bitmap. Returns 0 if successful. BE SURE TO CHECK +// this return value since there is a limited number of selectors!!!!!!! +extern int gr_bitmap_assign_selector( grs_bitmap * bmp ); + +//#define GR_GETCOLOR(r,g,b) (gr_inverse_table[( (((r)&31)<<10) | (((g)&31)<<5) | ((b)&31) )]) +//#define gr_getcolor(r,g,b) (gr_inverse_table[( (((r)&31)<<10) | (((g)&31)<<5) | ((b)&31) )]) +//#define BM_XRGB(r,g,b) (gr_inverse_table[( (((r)&31)<<10) | (((g)&31)<<5) | ((b)&31) )]) + +#define BM_RGB(r,g,b) ( (((r)&31)<<10) | (((g)&31)<<5) | ((b)&31) ) +#define BM_XRGB(r,g,b) gr_find_closest_color( (r)*2,(g)*2,(b)*2 ) +#define GR_GETCOLOR(r,g,b) gr_find_closest_color( (r)*2,(g)*2,(b)*2 ) +#define gr_getcolor(r,g,b) gr_find_closest_color( (r)*2,(g)*2,(b)*2 ) + +// Given: r,g,b, each in range of 0-63, return the color index that +// best matches the input. +int gr_find_closest_color( int r, int g, int b ); +int gr_find_closest_color_15bpp( int rgb ); + +extern void gr_merge_textures( ubyte * lower, ubyte * upper, ubyte * dest ); +extern void gr_merge_textures_1( ubyte * lower, ubyte * upper, ubyte * dest ); +extern void gr_merge_textures_2( ubyte * lower, ubyte * upper, ubyte * dest ); +extern void gr_merge_textures_3( ubyte * lower, ubyte * upper, ubyte * dest ); + +extern void gr_update(void); + +#endif + + diff --git a/include/grdef.h b/include/grdef.h new file mode 100644 index 00000000..17f24b5a --- /dev/null +++ b/include/grdef.h @@ -0,0 +1,119 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/include/grdef.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:16 $ + * + * Internal definitions for graphics lib. + * + * $Log: not supported by cvs2svn $ + * Revision 1.2 1999/11/20 10:05:16 donut + * variable size menu patch from Jan Bobrowski. Variable menu font size support and a bunch of fixes for menus that didn't work quite right, by me (MPM). + * + * Revision 1.1.1.1 1999/06/14 22:02:14 donut + * Import of d1x 1.37 source. + * + * Revision 1.5 1995/09/14 15:36:33 allender + * added stuff for 68k version + * + * Revision 1.4 1995/07/05 16:10:57 allender + * gr_linear_movsd prototype changes + * + * Revision 1.3 1995/04/19 14:39:28 allender + * changed function prototype + * + * Revision 1.2 1995/04/18 09:49:53 allender + * *** empty log message *** + * + * Revision 1.1 1995/03/09 09:04:56 allender + * Initial revision + * + * + * --- PC RCS information --- + * Revision 1.8 1994/05/06 12:50:09 john + * Added supertransparency; neatend things up; took out warnings. + * + * Revision 1.7 1994/01/25 11:40:29 john + * Added gr_check_mode function. + * + * Revision 1.6 1993/10/15 16:22:53 john + * y + * + * Revision 1.5 1993/09/29 17:31:00 john + * added gr_vesa_pixel + * + * Revision 1.4 1993/09/29 16:14:43 john + * added global canvas descriptors. + * + * Revision 1.3 1993/09/08 17:38:02 john + * Looking for errors + * + * Revision 1.2 1993/09/08 15:54:29 john + * *** empty log message *** + * + * Revision 1.1 1993/09/08 11:37:57 john + * Initial revision + * + * + */ +#define USE_2D_ASM 1 + +void gr_init_bitmap_alloc( grs_bitmap *bm, int mode, int x, int y, int w, int h, int bytesperline); +void show_fullscr(grs_bitmap *bm); +void gr_init_bitmap_data (grs_bitmap *bm); +void gr_free_bitmap_data (grs_bitmap *bm); +void gr_init_sub_bitmap (grs_bitmap *bm, grs_bitmap *bmParent, int x, int y, int w, int h ); +void gr_init_bitmap( grs_bitmap *bm, int mode, int x, int y, int w, int h, int bytesperline, unsigned char * data ); + +extern void gr_set_buffer(int w, int h, int r, int (*buffer_func)()); + +extern void gr_pal_setblock( int start, int n, unsigned char * palette ); +extern void gr_pal_getblock( int start, int n, unsigned char * palette ); +extern void gr_pal_setone( int index, unsigned char red, unsigned char green, unsigned char blue ); + +void gr_linear_movsb( ubyte * source, ubyte * dest, int nbytes); +void gr_linear_movsw( ubyte * source, ubyte * dest, int nbytes); +#if ( defined(__MWERKS__) && defined(__MC68K__) && defined(USE_2D_ASM) ) +void gr_linear_movsd(ubyte * src:__A0, ubyte * dest:__A1, uint num_pixels:__D0 ); +#else +void gr_linear_movsd( ubyte * source, ubyte * dest, unsigned int nbytes); +#endif +void gr_linear_rep_movsd_2x( ubyte * source, ubyte * dest, uint nbytes); +void gr_linear_stosd( ubyte * dest, unsigned char color, unsigned int nbytes); +extern unsigned int gr_var_color; +extern unsigned int gr_var_bwidth; +extern unsigned char * gr_var_bitmap; + +void gr_linear_line( int x0, int y0, int x1, int y1); + +extern unsigned int Table8to32[256]; + +#ifdef __MSDOS__ +extern unsigned char * gr_video_memory; +#endif + + +#define MINX 0 +#define MINY 0 +#define MAXX (GWIDTH-1) +#define MAXY (GHEIGHT-1) +#define TYPE grd_curcanv->cv_bitmap.bm_type +#define DATA grd_curcanv->cv_bitmap.bm_data +#define XOFFSET grd_curcanv->cv_bitmap.bm_x +#define YOFFSET grd_curcanv->cv_bitmap.bm_y +#define ROWSIZE grd_curcanv->cv_bitmap.bm_rowsize +#define COLOR grd_curcanv->cv_color + +void order( int *x1, int *x2 ); diff --git a/include/hash.h b/include/hash.h new file mode 100644 index 00000000..0041d89f --- /dev/null +++ b/include/hash.h @@ -0,0 +1,33 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + + +#ifndef _HASH_H +#define _HASH_H + +typedef struct hashtable { + int bitsize; + int and_mask; + int size; + int nitems; + char **key; + int *value; +} hashtable; + +int hashtable_init( hashtable *ht, int size ); +void hashtable_free( hashtable *ht ); +int hashtable_search( hashtable *ht, char *key ); +void hashtable_insert( hashtable *ht, char *key, int value ); + +#endif diff --git a/include/ibitblt.h b/include/ibitblt.h new file mode 100644 index 00000000..c1c068ac --- /dev/null +++ b/include/ibitblt.h @@ -0,0 +1,60 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/include/ibitblt.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:16 $ + * + * Prototypes for the ibitblt functions. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:14 donut + * Import of d1x 1.37 source. + * + * Revision 1.2 1994/05/31 11:10:56 john + * *** empty log message *** + * + * Revision 1.1 1994/05/30 16:08:46 john + * Initial revision + * + * + */ + + + +#ifndef _IBITBLT_H +#define _IBITBLT_H + +// Finds location/size of the largest "hole" in bitmap mask_bmp +void gr_ibitblt_find_hole_size ( grs_bitmap * mask_bmp, int *minx, int *miny, int *maxx, int *maxy ); + +// Creates a code mask that will copy data from a bitmap that is sw by sh starting from +// location sx, sy with a rowsize of srowsize onto another bitmap but only copies +// into pixel locations that are defined as transparent in bitmap bmp. +#ifdef PCCODE +ubyte * gr_ibitblt_create_mask ( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize ); +#else +void gr_ibitblt_create_mask ( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize ); +#endif + +// Copy source bitmap onto destination bitmap, not copying pixels that are defined +// transparent by the mask +#ifdef PCCODE +void gr_ibitblt (grs_bitmap * source_bmp, grs_bitmap * dest_bmp, ubyte * mask ); +#else +void gr_ibitblt(grs_bitmap *src_bmp, grs_bitmap *dest_bmp, ubyte pixel_double); +#endif + +#endif + diff --git a/include/iff.h b/include/iff.h new file mode 100644 index 00000000..9624fca0 --- /dev/null +++ b/include/iff.h @@ -0,0 +1,73 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifndef _IFF_H +#define _IFF_H + +#include "pstypes.h" +#include "gr.h" + +//Prototypes for IFF library functions + +int iff_read_bitmap(char *ifilename,grs_bitmap *bm,int bitmap_type,ubyte *palette); + //reads an IFF file into a grs_bitmap structure. fills in palette if not null + //returns error codes - see IFF.H. see GR.H for bitmap_type + //MEM DETAILS: This routines assumes that you already have the grs_bitmap + //structure allocated, but that you don't have the data for this bitmap + //allocated. In other words, do this: + // grs_bitmap * MyPicture; + // MALLOC( MyPicture, grs_bitmap, 1); + // iff_read_bitmap( filename, MyPicture, BM_LINEAR, NULL ); + // ...do whatever with your bitmap ... + // gr_free_bitmap( MyPicture ); + // exit(0) + +//like iff_read_bitmap(), but reads into a bitmap that already exists, +//without allocating memory for the bitmap. +int iff_read_into_bitmap(char *ifilename,grs_bitmap *bm,byte *palette); + +//read in animator brush (.abm) file +//fills in array of pointers, and n_bitmaps. +//returns iff error codes. max_bitmaps is size of array. +int iff_read_animbrush(char *ifilename,grs_bitmap **bm,int max_bitmaps,int *n_bitmaps,ubyte *palette); + +// After a read +extern ubyte iff_transparent_color; +extern ubyte iff_has_transparency; // 0=no transparency, 1=iff_transparent_color is valid + +int iff_write_bitmap(char *ofilename,grs_bitmap *bm,ubyte *palette); + //writes an IFF file from a grs_bitmap structure. writes palette if not null + //returns error codes - see IFF.H. + +//function to return pointer to error message +char *iff_errormsg(int error_number); + + +//Error codes for read & write routines + +#define IFF_NO_ERROR 0 //everything is fine, have a nice day +#define IFF_NO_MEM 1 //not enough mem for loading or processing +#define IFF_UNKNOWN_FORM 2 //IFF file, but not a bitmap +#define IFF_NOT_IFF 3 //this isn't even an IFF file +#define IFF_NO_FILE 4 //cannot find or open file +#define IFF_BAD_BM_TYPE 5 //tried to save invalid type, like BM_RGB15 +#define IFF_CORRUPT 6 //bad data in file +#define IFF_FORM_ANIM 7 //this is an anim, with non-anim load rtn +#define IFF_FORM_BITMAP 8 //this is not an anim, with anim load rtn +#define IFF_TOO_MANY_BMS 9 //anim read had more bitmaps than room for +#define IFF_UNKNOWN_MASK 10 //unknown masking type +#define IFF_READ_ERROR 11 //error reading from file +#define IFF_BM_MISMATCH 12 //bm being loaded doesn't match bm loaded into + +#endif + diff --git a/include/ipx.h b/include/ipx.h new file mode 100644 index 00000000..61d35c02 --- /dev/null +++ b/include/ipx.h @@ -0,0 +1,152 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/include/ipx.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:16 $ + * + * Prototype for IPX communications. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:16 donut + * Import of d1x 1.37 source. + * + * Revision 2.6 1995/03/29 11:19:32 john + * Added broadcasting over a net. + * + * Revision 2.5 1995/03/28 20:04:43 john + * Took away alternate server stuff. + * + * Revision 2.4 1995/03/23 19:00:10 john + * Added user list capabitly. + * + * Revision 2.3 1995/03/23 12:26:57 john + * Move IPX into bios lib. + * + * Revision 2.2 1995/03/22 19:08:14 john + * Added code to fix sending packets over router... now + * we just need to make broadcasts go over router!! + * + * Revision 2.1 1995/03/21 08:39:56 john + * Ifdef'd out the NETWORK code. + * + * Revision 2.0 1995/02/27 11:30:16 john + * New version 2.0, which has no anonymous unions, builds with + * Watcom 10.0, and doesn't require parsing BITMAPS.TBL. + * + * Revision 1.16 1995/02/16 17:34:52 john + * Added code to allow dynamic socket changing. + * + * Revision 1.15 1995/01/04 21:43:27 rob + * Remove SPX size definition. + * + * Revision 1.14 1995/01/03 13:46:18 john + * Added code that should make ipx work over different servers, + * but ifdef'd it out with SHAREWARE in ipx.c. I haven't tested + * this, and I hope it doesn't introduce net bugs. + * + * Revision 1.13 1994/11/02 11:37:16 rob + * Changed default socket number to a higher regions. + * + * Revision 1.12 1994/11/01 15:56:51 rob + * Added defines for SPX socketsx. + * + * Revision 1.11 1994/10/31 19:23:31 rob + * Added a prototype for the new object send function. + * + * Revision 1.10 1994/09/07 13:37:25 john + * Changed default socket to 0x4000, because + * the ipx/spx book says that we can only use + * sockets 0x4000 - 0x7fff. + * + * Revision 1.9 1994/08/25 18:14:45 matt + * Changed socket because of packet change + * + * Revision 1.8 1994/08/12 22:42:24 john + * Took away Player_stats; added Players array. + * + * Revision 1.7 1994/08/09 19:31:47 john + * Networking changes. + * + * Revision 1.6 1994/08/05 16:11:46 john + * Psuedo working version of networking. + * + * Revision 1.5 1994/08/04 19:17:20 john + * Inbetween version of network stuff. + * + * Revision 1.4 1994/07/29 16:08:59 john + * *** empty log message *** + * + * Revision 1.3 1994/07/25 12:33:22 john + * Network "pinging" in. + * + * Revision 1.2 1994/07/20 15:58:29 john + * First installment of ipx stuff. + * + * Revision 1.1 1994/07/19 15:43:05 john + * Initial revision + * + * + */ + +#ifndef _IPX_H +#define _IPX_H + +// The default socket to use. +#ifdef SHAREWARE + #define IPX_DEFAULT_SOCKET 0x5110 +#else + #define IPX_DEFAULT_SOCKET 0x5130 +#endif + +//--------------------------------------------------------------- +// Initializes all IPX internals. +// If socket_number==0, then opens next available socket. +// Returns: 0 if successful. +// -1 if socket already open. +// -2 if socket table full. +// -3 if IPX not installed. +// -4 if couldn't allocate low dos memory +// -5 if error with getting internetwork address +extern int ipx_init( int socket_number, int show_address ); + +extern int ipx_change_default_socket( ushort socket_number ); + +// Returns a pointer to 6-byte address +extern ubyte * ipx_get_my_local_address(); +// Returns a pointer to 4-byte server +extern ubyte * ipx_get_my_server_address(); + +// Determines the local address equivalent of an internetwork address. +void ipx_get_local_target( ubyte * server, ubyte * node, ubyte * local_target ); + +// If any packets waiting to be read in, this fills data in with the packet data and returns +// the number of bytes read. Else returns 0 if no packets waiting. +extern int ipx_get_packet_data( ubyte * data ); + +// Sends a broadcast packet to everyone on this socket. +extern void ipx_send_broadcast_packet_data( ubyte * data, int datasize ); + +// Sends a packet to a certain address +extern void ipx_send_packet_data( ubyte * data, int datasize, ubyte *network, ubyte *address, ubyte *immediate_address ); +extern void ipx_send_internetwork_packet_data( ubyte * data, int datasize, ubyte * server, ubyte *address ); + +#define IPX_MAX_DATA_SIZE (542) //(546-4) + +extern void ipx_read_user_file(char * filename); +extern void ipx_read_network_file(char * filename); + +#endif + + diff --git a/include/loadgl.h b/include/loadgl.h new file mode 100644 index 00000000..40361dd8 --- /dev/null +++ b/include/loadgl.h @@ -0,0 +1,1935 @@ +//loadgl.h - dynamic opengl loading - curtousy (sp) of Jeff Slutter + +#ifndef __LOADGL_H__ +#define __LOADGL_H__ + +#ifndef WIN32 +#ifdef __WINDOWS__ +#define WIN32 +#endif +#endif + +#if defined(WIN32) +#include +#define OGLFUNCCALL __stdcall +#else +#define OGLFUNCCALL +#endif + +#include +#include "types.h" + +#ifdef _cplusplus +#define OEXTERN extern "C" +#else +#define OEXTERN extern +#define true 1 +#define false 0 +#endif + +#ifdef DECLARE_VARS +#define DEFVAR +#else +#define DEFVAR OEXTERN +#endif + +#define glAccum dglAccum +#define glAlphaFunc dglAlphaFunc +#define glAreTexturesResident dglAreTexturesResident +#define glArrayElement dglArrayElement +#define glBegin dglBegin +#define glBindTexture dglBindTexture +#define glBitmap dglBitmap +#define glBlendFunc dglBlendFunc +#define glCallList dglCallList +#define glCallLists dglCallLists +#define glClear dglClear +#define glClearAccum dglClearAccum +#define glClearColor dglClearColor +#define glClearDepth dglClearDepth +#define glClearIndex dglClearIndex +#define glClearStencil dglClearStencil +#define glClipPlane dglClipPlane +#define glColor3b dglColor3b +#define glColor3bv dglColor3bv +#define glColor3d dglColor3d +#define glColor3dv dglColor3dv +#define glColor3f dglColor3f +#define glColor3fv dglColor3fv +#define glColor3i dglColor3i +#define glColor3iv dglColor3iv +#define glColor3s dglColor3s +#define glColor3sv dglColor3sv +#define glColor3ub dglColor3ub +#define glColor3ubv dglColor3ubv +#define glColor3ui dglColor3ui +#define glColor3uiv dglColor3uiv +#define glColor3us dglColor3us +#define glColor3usv dglColor3usv +#define glColor4b dglColor4b +#define glColor4bv dglColor4bv +#define glColor4d dglColor4d +#define glColor4dv dglColor4dv +#define glColor4f dglColor4f +#define glColor4fv dglColor4fv +#define glColor4i dglColor4i +#define glColor4iv dglColor4iv +#define glColor4s dglColor4s +#define glColor4sv dglColor4sv +#define glColor4ub dglColor4ub +#define glColor4ubv dglColor4ubv +#define glColor4ui dglColor4ui +#define glColor4uiv dglColor4uiv +#define glColor4us dglColor4us +#define glColor4usv dglColor4usv +#define glColorMask dglColorMask +#define glColorMaterial dglColorMaterial +#define glColorPointer dglColorPointer +#define glCopyPixels dglCopyPixels +#define glCopyTexImage1D dglCopyTexImage1D +#define glCopyTexImage2D dglCopyTexImage2D +#define glCopyTexSubImage1D dglCopyTexSubImage1D +#define glCopyTexSubImage2D dglCopyTexSubImage2D +#define glCullFace dglCullFace +#define glDeleteLists dglDeleteLists +#define glDeleteTextures dglDeleteTextures +#define glDepthFunc dglDepthFunc +#define glDepthMask dglDepthMask +#define glDepthRange dglDepthRange +#define glDisable dglDisable +#define glDisableClientState dglDisableClientState +#define glDrawArrays dglDrawArrays +#define glDrawBuffer dglDrawBuffer +#define glDrawElements dglDrawElements +#define glDrawPixels dglDrawPixels +#define glEdgeFlag dglEdgeFlag +#define glEdgeFlagPointer dglEdgeFlagPointer +#define glEdgeFlagv dglEdgeFlagv +#define glEnable dglEnable +#define glEnableClientState dglEnableClientState +#define glEnd dglEnd +#define glEndList dglEndList +#define glEvalCoord1d dglEvalCoord1d +#define glEvalCoord1dv dglEvalCoord1dv +#define glEvalCoord1f dglEvalCoord1f +#define glEvalCoord1fv dglEvalCoord1fv +#define glEvalCoord2d dglEvalCoord2d +#define glEvalCoord2dv dglEvalCoord2dv +#define glEvalCoord2f dglEvalCoord2f +#define glEvalCoord2fv dglEvalCoord2fv +#define glEvalMesh1 dglEvalMesh1 +#define glEvalMesh2 dglEvalMesh2 +#define glEvalPoint1 dglEvalPoint1 +#define glEvalPoint2 dglEvalPoint2 +#define glFeedbackBuffer dglFeedbackBuffer +#define glFinish dglFinish +#define glFlush dglFlush +#define glFogf dglFogf +#define glFogfv dglFogfv +#define glFogi dglFogi +#define glFogiv dglFogiv +#define glFrontFace dglFrontFace +#define glFrustum dglFrustum +#define glGenLists dglGenLists +#define glGenTextures dglGenTextures +#define glGetBooleanv dglGetBooleanv +#define glGetClipPlane dglGetClipPlane +#define glGetDoublev dglGetDoublev +#define glGetError dglGetError +#define glGetFloatv dglGetFloatv +#define glGetIntegerv dglGetIntegerv +#define glGetLightfv dglGetLightfv +#define glGetLightiv dglGetLightiv +#define glGetMapdv dglGetMapdv +#define glGetMapfv dglGetMapfv +#define glGetMapiv dglGetMapiv +#define glGetMaterialfv dglGetMaterialfv +#define glGetMaterialiv dglGetMaterialiv +#define glGetPixelMapfv dglGetPixelMapfv +#define glGetPixelMapuiv dglGetPixelMapuiv +#define glGetPixelMapusv dglGetPixelMapusv +#define glGetPointerv dglGetPointerv +#define glGetPolygonStipple dglGetPolygonStipple +#define glGetString dglGetString +#define glGetTexEnvfv dglGetTexEnvfv +#define glGetTexEnviv dglGetTexEnviv +#define glGetTexGendv dglGetTexGendv +#define glGetTexGenfv dglGetTexGenfv +#define glGetTexGeniv dglGetTexGeniv +#define glGetTexImage dglGetTexImage +#define glGetTexLevelParameterfv dglGetTexLevelParameterfv +#define glGetTexLevelParameteriv dglGetTexLevelParameteriv +#define glGetTexParameterfv dglGetTexParameterfv +#define glGetTexParameteriv dglGetTexParameteriv +#define glHint dglHint +#define glIndexMask dglIndexMask +#define glIndexPointer dglIndexPointer +#define glIndexd dglIndexd +#define glIndexdv dglIndexdv +#define glIndexf dglIndexf +#define glIndexfv dglIndexfv +#define glIndexi dglIndexi +#define glIndexiv dglIndexiv +#define glIndexs dglIndexs +#define glIndexsv dglIndexsv +#define glIndexub dglIndexub +#define glIndexubv dglIndexubv +#define glInitNames dglInitNames +#define glInterleavedArrays dglInterleavedArrays +#define glIsEnabled dglIsEnabled +#define glIsList dglIsList +#define glIsTexture dglIsTexture +#define glLightModelf dglLightModelf +#define glLightModelfv dglLightModelfv +#define glLightModeli dglLightModeli +#define glLightModeliv dglLightModeliv +#define glLightf dglLightf +#define glLightfv dglLightfv +#define glLighti dglLighti +#define glLightiv dglLightiv +#define glLineStipple dglLineStipple +#define glLineWidth dglLineWidth +#define glListBase dglListBase +#define glLoadIdentity dglLoadIdentity +#define glLoadMatrixd dglLoadMatrixd +#define glLoadMatrixf dglLoadMatrixf +#define glLoadName dglLoadName +#define glLogicOp dglLogicOp +#define glMap1d dglMap1d +#define glMap1f dglMap1f +#define glMap2d dglMap2d +#define glMap2f dglMap2f +#define glMapGrid1d dglMapGrid1d +#define glMapGrid1f dglMapGrid1f +#define glMapGrid2d dglMapGrid2d +#define glMapGrid2f dglMapGrid2f +#define glMaterialf dglMaterialf +#define glMaterialfv dglMaterialfv +#define glMateriali dglMateriali +#define glMaterialiv dglMaterialiv +#define glMatrixMode dglMatrixMode +#define glMultMatrixd dglMultMatrixd +#define glMultMatrixf dglMultMatrixf +#define glNewList dglNewList +#define glNormal3b dglNormal3b +#define glNormal3bv dglNormal3bv +#define glNormal3d dglNormal3d +#define glNormal3dv dglNormal3dv +#define glNormal3f dglNormal3f +#define glNormal3fv dglNormal3fv +#define glNormal3i dglNormal3i +#define glNormal3iv dglNormal3iv +#define glNormal3s dglNormal3s +#define glNormal3sv dglNormal3sv +#define glNormalPointer dglNormalPointer +#define glOrtho dglOrtho +#define glPassThrough dglPassThrough +#define glPixelMapfv dglPixelMapfv +#define glPixelMapuiv dglPixelMapuiv +#define glPixelMapusv dglPixelMapusv +#define glPixelStoref dglPixelStoref +#define glPixelStorei dglPixelStorei +#define glPixelTransferf dglPixelTransferf +#define glPixelTransferi dglPixelTransferi +#define glPixelZoom dglPixelZoom +#define glPointSize dglPointSize +#define glPolygonMode dglPolygonMode +#define glPolygonOffset dglPolygonOffset +#define glPolygonStipple dglPolygonStipple +#define glPopAttrib dglPopAttrib +#define glPopClientAttrib dglPopClientAttrib +#define glPopMatrix dglPopMatrix +#define glPopName dglPopName +#define glPrioritizeTextures dglPrioritizeTextures +#define glPushAttrib dglPushAttrib +#define glPushClientAttrib dglPushClientAttrib +#define glPushMatrix dglPushMatrix +#define glPushName dglPushName +#define glRasterPos2d dglRasterPos2d +#define glRasterPos2dv dglRasterPos2dv +#define glRasterPos2f dglRasterPos2f +#define glRasterPos2fv dglRasterPos2fv +#define glRasterPos2i dglRasterPos2i +#define glRasterPos2iv dglRasterPos2iv +#define glRasterPos2s dglRasterPos2s +#define glRasterPos2sv dglRasterPos2sv +#define glRasterPos3d dglRasterPos3d +#define glRasterPos3dv dglRasterPos3dv +#define glRasterPos3f dglRasterPos3f +#define glRasterPos3fv dglRasterPos3fv +#define glRasterPos3i dglRasterPos3i +#define glRasterPos3iv dglRasterPos3iv +#define glRasterPos3s dglRasterPos3s +#define glRasterPos3sv dglRasterPos3sv +#define glRasterPos4d dglRasterPos4d +#define glRasterPos4dv dglRasterPos4dv +#define glRasterPos4f dglRasterPos4f +#define glRasterPos4fv dglRasterPos4fv +#define glRasterPos4i dglRasterPos4i +#define glRasterPos4iv dglRasterPos4iv +#define glRasterPos4s dglRasterPos4s +#define glRasterPos4sv dglRasterPos4sv +#define glReadBuffer dglReadBuffer +#define glReadPixels dglReadPixels +#define glRectd dglRectd +#define glRectdv dglRectdv +#define glRectf dglRectf +#define glRectfv dglRectfv +#define glRecti dglRecti +#define glRectiv dglRectiv +#define glRects dglRects +#define glRectsv dglRectsv +#define glRenderMode dglRenderMode +#define glRotated dglRotated +#define glRotatef dglRotatef +#define glScaled dglScaled +#define glScalef dglScalef +#define glScissor dglScissor +#define glSelectBuffer dglSelectBuffer +#define glShadeModel dglShadeModel +#define glStencilFunc dglStencilFunc +#define glStencilMask dglStencilMask +#define glStencilOp dglStencilOp +#define glTexCoord1d dglTexCoord1d +#define glTexCoord1dv dglTexCoord1dv +#define glTexCoord1f dglTexCoord1f +#define glTexCoord1fv dglTexCoord1fv +#define glTexCoord1i dglTexCoord1i +#define glTexCoord1iv dglTexCoord1iv +#define glTexCoord1s dglTexCoord1s +#define glTexCoord1sv dglTexCoord1sv +#define glTexCoord2d dglTexCoord2d +#define glTexCoord2dv dglTexCoord2dv +#define glTexCoord2f dglTexCoord2f +#define glTexCoord2fv dglTexCoord2fv +#define glTexCoord2i dglTexCoord2i +#define glTexCoord2iv dglTexCoord2iv +#define glTexCoord2s dglTexCoord2s +#define glTexCoord2sv dglTexCoord2sv +#define glTexCoord3d dglTexCoord3d +#define glTexCoord3dv dglTexCoord3dv +#define glTexCoord3f dglTexCoord3f +#define glTexCoord3fv dglTexCoord3fv +#define glTexCoord3i dglTexCoord3i +#define glTexCoord3iv dglTexCoord3iv +#define glTexCoord3s dglTexCoord3s +#define glTexCoord3sv dglTexCoord3sv +#define glTexCoord4d dglTexCoord4d +#define glTexCoord4dv dglTexCoord4dv +#define glTexCoord4f dglTexCoord4f +#define glTexCoord4fv dglTexCoord4fv +#define glTexCoord4i dglTexCoord4i +#define glTexCoord4iv dglTexCoord4iv +#define glTexCoord4s dglTexCoord4s +#define glTexCoord4sv dglTexCoord4sv +#define glTexCoordPointer dglTexCoordPointer +#define glTexEnvf dglTexEnvf +#define glTexEnvfv dglTexEnvfv +#define glTexEnvi dglTexEnvi +#define glTexEnviv dglTexEnviv +#define glTexGend dglTexGend +#define glTexGendv dglTexGendv +#define glTexGenf dglTexGenf +#define glTexGenfv dglTexGenfv +#define glTexGeni dglTexGeni +#define glTexGeniv dglTexGeniv +#define glTexImage1D dglTexImage1D +#define glTexImage2D dglTexImage2D +#define glTexParameterf dglTexParameterf +#define glTexParameterfv dglTexParameterfv +#define glTexParameteri dglTexParameteri +#define glTexParameteriv dglTexParameteriv +#define glTexSubImage1D dglTexSubImage1D +#define glTexSubImage2D dglTexSubImage2D +#define glTranslated dglTranslated +#define glTranslatef dglTranslatef +#define glVertex2d dglVertex2d +#define glVertex2dv dglVertex2dv +#define glVertex2f dglVertex2f +#define glVertex2fv dglVertex2fv +#define glVertex2i dglVertex2i +#define glVertex2iv dglVertex2iv +#define glVertex2s dglVertex2s +#define glVertex2sv dglVertex2sv +#define glVertex3d dglVertex3d +#define glVertex3dv dglVertex3dv +#define glVertex3f dglVertex3f +#define glVertex3fv dglVertex3fv +#define glVertex3i dglVertex3i +#define glVertex3iv dglVertex3iv +#define glVertex3s dglVertex3s +#define glVertex3sv dglVertex3sv +#define glVertex4d dglVertex4d +#define glVertex4dv dglVertex4dv +#define glVertex4f dglVertex4f +#define glVertex4fv dglVertex4fv +#define glVertex4i dglVertex4i +#define glVertex4iv dglVertex4iv +#define glVertex4s dglVertex4s +#define glVertex4sv dglVertex4sv +#define glVertexPointer dglVertexPointer +#define glViewport dglViewport + + +#ifdef WIN32 +#define wglCopyContext dwglCopyContext +#define wglCreateContext dwglCreateContext +#define wglCreateLayerContext dwglCreateLayerContext +#define wglDeleteContext dwglDeleteContext +#define wglGetCurrentContext dwglGetCurrentContext +#define wglGetCurrentDC dwglGetCurrentDC +#define wglGetProcAddress dwglGetProcAddress +#define wglMakeCurrent dwglMakeCurrent +#define wglShareLists dwglShareLists +#define wglUseFontBitmapsA dwglUseFontBitmapsA +#define wglUseFontBitmapsW dwglUseFontBitmapsW +#define wglUseFontOutlinesA dwglUseFontOutlinesA +#define wglUseFontOutlinesW dwglUseFontOutlinesW +#define wglDescribeLayerPlane dwglDescribeLayerPlane +#define wglSetLayerPaletteEntries dwglSetLayerPaletteEntries +#define wglGetLayerPaletteEntries dwglGetLayerPaletteEntries +#define wglRealizeLayerPalette dwglRealizeLayerPalette +#define wglSwapLayerBuffers dwglSwapLayerBuffers +#if (WINVER >= 0x0500) +#define wglSwapMultipleBuffers dwglSwapMultipleBuffers +#endif +#endif + +typedef void (OGLFUNCCALL *glAccum_fp)(GLenum op, GLfloat value); +typedef void (OGLFUNCCALL *glAlphaFunc_fp)(GLenum func, GLclampf ref); +typedef GLboolean (OGLFUNCCALL *glAreTexturesResident_fp)(GLsizei n, const GLuint *textures, GLboolean *residences); +typedef void (OGLFUNCCALL *glArrayElement_fp)(GLint i); +typedef void (OGLFUNCCALL *glBegin_fp)(GLenum mode); +typedef void (OGLFUNCCALL *glBindTexture_fp)(GLenum target, GLuint texture); +typedef void (OGLFUNCCALL *glBitmap_fp)(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); +typedef void (OGLFUNCCALL *glBlendFunc_fp)(GLenum sfactor, GLenum dfactor); +typedef void (OGLFUNCCALL *glCallList_fp)(GLuint list); +typedef void (OGLFUNCCALL *glCallLists_fp)(GLsizei n, GLenum type, const GLvoid *lists); +typedef void (OGLFUNCCALL *glClear_fp)(GLbitfield mask); +typedef void (OGLFUNCCALL *glClearAccum_fp)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (OGLFUNCCALL *glClearColor_fp)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +typedef void (OGLFUNCCALL *glClearDepth_fp)(GLclampd depth); +typedef void (OGLFUNCCALL *glClearIndex_fp)(GLfloat c); +typedef void (OGLFUNCCALL *glClearStencil_fp)(GLint s); +typedef void (OGLFUNCCALL *glClipPlane_fp)(GLenum plane, const GLdouble *equation); +typedef void (OGLFUNCCALL *glColor3b_fp)(GLbyte red, GLbyte green, GLbyte blue); +typedef void (OGLFUNCCALL *glColor3bv_fp)(const GLbyte *v); +typedef void (OGLFUNCCALL *glColor3d_fp)(GLdouble red, GLdouble green, GLdouble blue); +typedef void (OGLFUNCCALL *glColor3dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glColor3f_fp)(GLfloat red, GLfloat green, GLfloat blue); +typedef void (OGLFUNCCALL *glColor3fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glColor3i_fp)(GLint red, GLint green, GLint blue); +typedef void (OGLFUNCCALL *glColor3iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glColor3s_fp)(GLshort red, GLshort green, GLshort blue); +typedef void (OGLFUNCCALL *glColor3sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glColor3ub_fp)(GLubyte red, GLubyte green, GLubyte blue); +typedef void (OGLFUNCCALL *glColor3ubv_fp)(const GLubyte *v); +typedef void (OGLFUNCCALL *glColor3ui_fp)(GLuint red, GLuint green, GLuint blue); +typedef void (OGLFUNCCALL *glColor3uiv_fp)(const GLuint *v); +typedef void (OGLFUNCCALL *glColor3us_fp)(GLushort red, GLushort green, GLushort blue); +typedef void (OGLFUNCCALL *glColor3usv_fp)(const GLushort *v); +typedef void (OGLFUNCCALL *glColor4b_fp)(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); +typedef void (OGLFUNCCALL *glColor4bv_fp)(const GLbyte *v); +typedef void (OGLFUNCCALL *glColor4d_fp)(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); +typedef void (OGLFUNCCALL *glColor4dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glColor4f_fp)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (OGLFUNCCALL *glColor4fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glColor4i_fp)(GLint red, GLint green, GLint blue, GLint alpha); +typedef void (OGLFUNCCALL *glColor4iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glColor4s_fp)(GLshort red, GLshort green, GLshort blue, GLshort alpha); +typedef void (OGLFUNCCALL *glColor4sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glColor4ub_fp)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +typedef void (OGLFUNCCALL *glColor4ubv_fp)(const GLubyte *v); +typedef void (OGLFUNCCALL *glColor4ui_fp)(GLuint red, GLuint green, GLuint blue, GLuint alpha); +typedef void (OGLFUNCCALL *glColor4uiv_fp)(const GLuint *v); +typedef void (OGLFUNCCALL *glColor4us_fp)(GLushort red, GLushort green, GLushort blue, GLushort alpha); +typedef void (OGLFUNCCALL *glColor4usv_fp)(const GLushort *v); +typedef void (OGLFUNCCALL *glColorMask_fp)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +typedef void (OGLFUNCCALL *glColorMaterial_fp)(GLenum face, GLenum mode); +typedef void (OGLFUNCCALL *glColorPointer_fp)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (OGLFUNCCALL *glCopyPixels_fp)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); +typedef void (OGLFUNCCALL *glCopyTexImage1D_fp)(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (OGLFUNCCALL *glCopyTexImage2D_fp)(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (OGLFUNCCALL *glCopyTexSubImage1D_fp)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (OGLFUNCCALL *glCopyTexSubImage2D_fp)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (OGLFUNCCALL *glCullFace_fp)(GLenum mode); +typedef void (OGLFUNCCALL *glDeleteLists_fp)(GLuint list, GLsizei range); +typedef void (OGLFUNCCALL *glDeleteTextures_fp)(GLsizei n, const GLuint *textures); +typedef void (OGLFUNCCALL *glDepthFunc_fp)(GLenum func); +typedef void (OGLFUNCCALL *glDepthMask_fp)(GLboolean flag); +typedef void (OGLFUNCCALL *glDepthRange_fp)(GLclampd zNear, GLclampd zFar); +typedef void (OGLFUNCCALL *glDisable_fp)(GLenum cap); +typedef void (OGLFUNCCALL *glDisableClientState_fp)(GLenum array); +typedef void (OGLFUNCCALL *glDrawArrays_fp)(GLenum mode, GLint first, GLsizei count); +typedef void (OGLFUNCCALL *glDrawBuffer_fp)(GLenum mode); +typedef void (OGLFUNCCALL *glDrawElements_fp)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +typedef void (OGLFUNCCALL *glDrawPixels_fp)(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (OGLFUNCCALL *glEdgeFlag_fp)(GLboolean flag); +typedef void (OGLFUNCCALL *glEdgeFlagPointer_fp)(GLsizei stride, const GLvoid *pointer); +typedef void (OGLFUNCCALL *glEdgeFlagv_fp)(const GLboolean *flag); +typedef void (OGLFUNCCALL *glEnable_fp)(GLenum cap); +typedef void (OGLFUNCCALL *glEnableClientState_fp)(GLenum array); +typedef void (OGLFUNCCALL *glEnd_fp)(void); +typedef void (OGLFUNCCALL *glEndList_fp)(void); +typedef void (OGLFUNCCALL *glEvalCoord1d_fp)(GLdouble u); +typedef void (OGLFUNCCALL *glEvalCoord1dv_fp)(const GLdouble *u); +typedef void (OGLFUNCCALL *glEvalCoord1f_fp)(GLfloat u); +typedef void (OGLFUNCCALL *glEvalCoord1fv_fp)(const GLfloat *u); +typedef void (OGLFUNCCALL *glEvalCoord2d_fp)(GLdouble u, GLdouble v); +typedef void (OGLFUNCCALL *glEvalCoord2dv_fp)(const GLdouble *u); +typedef void (OGLFUNCCALL *glEvalCoord2f_fp)(GLfloat u, GLfloat v); +typedef void (OGLFUNCCALL *glEvalCoord2fv_fp)(const GLfloat *u); +typedef void (OGLFUNCCALL *glEvalMesh1_fp)(GLenum mode, GLint i1, GLint i2); +typedef void (OGLFUNCCALL *glEvalMesh2_fp)(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); +typedef void (OGLFUNCCALL *glEvalPoint1_fp)(GLint i); +typedef void (OGLFUNCCALL *glEvalPoint2_fp)(GLint i, GLint j); +typedef void (OGLFUNCCALL *glFeedbackBuffer_fp)(GLsizei size, GLenum type, GLfloat *buffer); +typedef void (OGLFUNCCALL *glFinish_fp)(void); +typedef void (OGLFUNCCALL *glFlush_fp)(void); +typedef void (OGLFUNCCALL *glFogf_fp)(GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glFogfv_fp)(GLenum pname, const GLfloat *params); +typedef void (OGLFUNCCALL *glFogi_fp)(GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glFogiv_fp)(GLenum pname, const GLint *params); +typedef void (OGLFUNCCALL *glFrontFace_fp)(GLenum mode); +typedef void (OGLFUNCCALL *glFrustum_fp)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +typedef GLuint (OGLFUNCCALL *glGenLists_fp)(GLsizei range); +typedef void (OGLFUNCCALL *glGenTextures_fp)(GLsizei n, GLuint *textures); +typedef void (OGLFUNCCALL *glGetBooleanv_fp)(GLenum pname, GLboolean *params); +typedef void (OGLFUNCCALL *glGetClipPlane_fp)(GLenum plane, GLdouble *equation); +typedef void (OGLFUNCCALL *glGetDoublev_fp)(GLenum pname, GLdouble *params); +typedef GLenum (OGLFUNCCALL *glGetError_fp)(void); +typedef void (OGLFUNCCALL *glGetFloatv_fp)(GLenum pname, GLfloat *params); +typedef void (OGLFUNCCALL *glGetIntegerv_fp)(GLenum pname, GLint *params); +typedef void (OGLFUNCCALL *glGetLightfv_fp)(GLenum light, GLenum pname, GLfloat *params); +typedef void (OGLFUNCCALL *glGetLightiv_fp)(GLenum light, GLenum pname, GLint *params); +typedef void (OGLFUNCCALL *glGetMapdv_fp)(GLenum target, GLenum query, GLdouble *v); +typedef void (OGLFUNCCALL *glGetMapfv_fp)(GLenum target, GLenum query, GLfloat *v); +typedef void (OGLFUNCCALL *glGetMapiv_fp)(GLenum target, GLenum query, GLint *v); +typedef void (OGLFUNCCALL *glGetMaterialfv_fp)(GLenum face, GLenum pname, GLfloat *params); +typedef void (OGLFUNCCALL *glGetMaterialiv_fp)(GLenum face, GLenum pname, GLint *params); +typedef void (OGLFUNCCALL *glGetPixelMapfv_fp)(GLenum map, GLfloat *values); +typedef void (OGLFUNCCALL *glGetPixelMapuiv_fp)(GLenum map, GLuint *values); +typedef void (OGLFUNCCALL *glGetPixelMapusv_fp)(GLenum map, GLushort *values); +typedef void (OGLFUNCCALL *glGetPointerv_fp)(GLenum pname, GLvoid* *params); +typedef void (OGLFUNCCALL *glGetPolygonStipple_fp)(GLubyte *mask); +typedef const GLubyte *(OGLFUNCCALL *glGetString_fp)(GLenum name); +typedef void (OGLFUNCCALL *glGetTexEnvfv_fp)(GLenum target, GLenum pname, GLfloat *params); +typedef void (OGLFUNCCALL *glGetTexEnviv_fp)(GLenum target, GLenum pname, GLint *params); +typedef void (OGLFUNCCALL *glGetTexGendv_fp)(GLenum coord, GLenum pname, GLdouble *params); +typedef void (OGLFUNCCALL *glGetTexGenfv_fp)(GLenum coord, GLenum pname, GLfloat *params); +typedef void (OGLFUNCCALL *glGetTexGeniv_fp)(GLenum coord, GLenum pname, GLint *params); +typedef void (OGLFUNCCALL *glGetTexImage_fp)(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +typedef void (OGLFUNCCALL *glGetTexLevelParameterfv_fp)(GLenum target, GLint level, GLenum pname, GLfloat *params); +typedef void (OGLFUNCCALL *glGetTexLevelParameteriv_fp)(GLenum target, GLint level, GLenum pname, GLint *params); +typedef void (OGLFUNCCALL *glGetTexParameterfv_fp)(GLenum target, GLenum pname, GLfloat *params); +typedef void (OGLFUNCCALL *glGetTexParameteriv_fp)(GLenum target, GLenum pname, GLint *params); +typedef void (OGLFUNCCALL *glHint_fp)(GLenum target, GLenum mode); +typedef void (OGLFUNCCALL *glIndexMask_fp)(GLuint mask); +typedef void (OGLFUNCCALL *glIndexPointer_fp)(GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (OGLFUNCCALL *glIndexd_fp)(GLdouble c); +typedef void (OGLFUNCCALL *glIndexdv_fp)(const GLdouble *c); +typedef void (OGLFUNCCALL *glIndexf_fp)(GLfloat c); +typedef void (OGLFUNCCALL *glIndexfv_fp)(const GLfloat *c); +typedef void (OGLFUNCCALL *glIndexi_fp)(GLint c); +typedef void (OGLFUNCCALL *glIndexiv_fp)(const GLint *c); +typedef void (OGLFUNCCALL *glIndexs_fp)(GLshort c); +typedef void (OGLFUNCCALL *glIndexsv_fp)(const GLshort *c); +typedef void (OGLFUNCCALL *glIndexub_fp)(GLubyte c); +typedef void (OGLFUNCCALL *glIndexubv_fp)(const GLubyte *c); +typedef void (OGLFUNCCALL *glInitNames_fp)(void); +typedef void (OGLFUNCCALL *glInterleavedArrays_fp)(GLenum format, GLsizei stride, const GLvoid *pointer); +typedef GLboolean (OGLFUNCCALL *glIsEnabled_fp)(GLenum cap); +typedef GLboolean (OGLFUNCCALL *glIsList_fp)(GLuint list); +typedef GLboolean (OGLFUNCCALL *glIsTexture_fp)(GLuint texture); +typedef void (OGLFUNCCALL *glLightModelf_fp)(GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glLightModelfv_fp)(GLenum pname, const GLfloat *params); +typedef void (OGLFUNCCALL *glLightModeli_fp)(GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glLightModeliv_fp)(GLenum pname, const GLint *params); +typedef void (OGLFUNCCALL *glLightf_fp)(GLenum light, GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glLightfv_fp)(GLenum light, GLenum pname, const GLfloat *params); +typedef void (OGLFUNCCALL *glLighti_fp)(GLenum light, GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glLightiv_fp)(GLenum light, GLenum pname, const GLint *params); +typedef void (OGLFUNCCALL *glLineStipple_fp)(GLint factor, GLushort pattern); +typedef void (OGLFUNCCALL *glLineWidth_fp)(GLfloat width); +typedef void (OGLFUNCCALL *glListBase_fp)(GLuint base); +typedef void (OGLFUNCCALL *glLoadIdentity_fp)(void); +typedef void (OGLFUNCCALL *glLoadMatrixd_fp)(const GLdouble *m); +typedef void (OGLFUNCCALL *glLoadMatrixf_fp)(const GLfloat *m); +typedef void (OGLFUNCCALL *glLoadName_fp)(GLuint name); +typedef void (OGLFUNCCALL *glLogicOp_fp)(GLenum opcode); +typedef void (OGLFUNCCALL *glMap1d_fp)(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); +typedef void (OGLFUNCCALL *glMap1f_fp)(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); +typedef void (OGLFUNCCALL *glMap2d_fp)(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); +typedef void (OGLFUNCCALL *glMap2f_fp)(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); +typedef void (OGLFUNCCALL *glMapGrid1d_fp)(GLint un, GLdouble u1, GLdouble u2); +typedef void (OGLFUNCCALL *glMapGrid1f_fp)(GLint un, GLfloat u1, GLfloat u2); +typedef void (OGLFUNCCALL *glMapGrid2d_fp)(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); +typedef void (OGLFUNCCALL *glMapGrid2f_fp)(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); +typedef void (OGLFUNCCALL *glMaterialf_fp)(GLenum face, GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glMaterialfv_fp)(GLenum face, GLenum pname, const GLfloat *params); +typedef void (OGLFUNCCALL *glMateriali_fp)(GLenum face, GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glMaterialiv_fp)(GLenum face, GLenum pname, const GLint *params); +typedef void (OGLFUNCCALL *glMatrixMode_fp)(GLenum mode); +typedef void (OGLFUNCCALL *glMultMatrixd_fp)(const GLdouble *m); +typedef void (OGLFUNCCALL *glMultMatrixf_fp)(const GLfloat *m); +typedef void (OGLFUNCCALL *glNewList_fp)(GLuint list, GLenum mode); +typedef void (OGLFUNCCALL *glNormal3b_fp)(GLbyte nx, GLbyte ny, GLbyte nz); +typedef void (OGLFUNCCALL *glNormal3bv_fp)(const GLbyte *v); +typedef void (OGLFUNCCALL *glNormal3d_fp)(GLdouble nx, GLdouble ny, GLdouble nz); +typedef void (OGLFUNCCALL *glNormal3dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glNormal3f_fp)(GLfloat nx, GLfloat ny, GLfloat nz); +typedef void (OGLFUNCCALL *glNormal3fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glNormal3i_fp)(GLint nx, GLint ny, GLint nz); +typedef void (OGLFUNCCALL *glNormal3iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glNormal3s_fp)(GLshort nx, GLshort ny, GLshort nz); +typedef void (OGLFUNCCALL *glNormal3sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glNormalPointer_fp)(GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (OGLFUNCCALL *glOrtho_fp)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +typedef void (OGLFUNCCALL *glPassThrough_fp)(GLfloat token); +typedef void (OGLFUNCCALL *glPixelMapfv_fp)(GLenum map, GLsizei mapsize, const GLfloat *values); +typedef void (OGLFUNCCALL *glPixelMapuiv_fp)(GLenum map, GLsizei mapsize, const GLuint *values); +typedef void (OGLFUNCCALL *glPixelMapusv_fp)(GLenum map, GLsizei mapsize, const GLushort *values); +typedef void (OGLFUNCCALL *glPixelStoref_fp)(GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glPixelStorei_fp)(GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glPixelTransferf_fp)(GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glPixelTransferi_fp)(GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glPixelZoom_fp)(GLfloat xfactor, GLfloat yfactor); +typedef void (OGLFUNCCALL *glPointSize_fp)(GLfloat size); +typedef void (OGLFUNCCALL *glPolygonMode_fp)(GLenum face, GLenum mode); +typedef void (OGLFUNCCALL *glPolygonOffset_fp)(GLfloat factor, GLfloat units); +typedef void (OGLFUNCCALL *glPolygonStipple_fp)(const GLubyte *mask); +typedef void (OGLFUNCCALL *glPopAttrib_fp)(void); +typedef void (OGLFUNCCALL *glPopClientAttrib_fp)(void); +typedef void (OGLFUNCCALL *glPopMatrix_fp)(void); +typedef void (OGLFUNCCALL *glPopName_fp)(void); +typedef void (OGLFUNCCALL *glPrioritizeTextures_fp)(GLsizei n, const GLuint *textures, const GLclampf *priorities); +typedef void (OGLFUNCCALL *glPushAttrib_fp)(GLbitfield mask); +typedef void (OGLFUNCCALL *glPushClientAttrib_fp)(GLbitfield mask); +typedef void (OGLFUNCCALL *glPushMatrix_fp)(void); +typedef void (OGLFUNCCALL *glPushName_fp)(GLuint name); +typedef void (OGLFUNCCALL *glRasterPos2d_fp)(GLdouble x, GLdouble y); +typedef void (OGLFUNCCALL *glRasterPos2dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glRasterPos2f_fp)(GLfloat x, GLfloat y); +typedef void (OGLFUNCCALL *glRasterPos2fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glRasterPos2i_fp)(GLint x, GLint y); +typedef void (OGLFUNCCALL *glRasterPos2iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glRasterPos2s_fp)(GLshort x, GLshort y); +typedef void (OGLFUNCCALL *glRasterPos2sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glRasterPos3d_fp)(GLdouble x, GLdouble y, GLdouble z); +typedef void (OGLFUNCCALL *glRasterPos3dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glRasterPos3f_fp)(GLfloat x, GLfloat y, GLfloat z); +typedef void (OGLFUNCCALL *glRasterPos3fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glRasterPos3i_fp)(GLint x, GLint y, GLint z); +typedef void (OGLFUNCCALL *glRasterPos3iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glRasterPos3s_fp)(GLshort x, GLshort y, GLshort z); +typedef void (OGLFUNCCALL *glRasterPos3sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glRasterPos4d_fp)(GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (OGLFUNCCALL *glRasterPos4dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glRasterPos4f_fp)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (OGLFUNCCALL *glRasterPos4fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glRasterPos4i_fp)(GLint x, GLint y, GLint z, GLint w); +typedef void (OGLFUNCCALL *glRasterPos4iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glRasterPos4s_fp)(GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (OGLFUNCCALL *glRasterPos4sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glReadBuffer_fp)(GLenum mode); +typedef void (OGLFUNCCALL *glReadPixels_fp)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); +typedef void (OGLFUNCCALL *glRectd_fp)(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); +typedef void (OGLFUNCCALL *glRectdv_fp)(const GLdouble *v1, const GLdouble *v2); +typedef void (OGLFUNCCALL *glRectf_fp)(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); +typedef void (OGLFUNCCALL *glRectfv_fp)(const GLfloat *v1, const GLfloat *v2); +typedef void (OGLFUNCCALL *glRecti_fp)(GLint x1, GLint y1, GLint x2, GLint y2); +typedef void (OGLFUNCCALL *glRectiv_fp)(const GLint *v1, const GLint *v2); +typedef void (OGLFUNCCALL *glRects_fp)(GLshort x1, GLshort y1, GLshort x2, GLshort y2); +typedef void (OGLFUNCCALL *glRectsv_fp)(const GLshort *v1, const GLshort *v2); +typedef GLint (OGLFUNCCALL *glRenderMode_fp)(GLenum mode); +typedef void (OGLFUNCCALL *glRotated_fp)(GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +typedef void (OGLFUNCCALL *glRotatef_fp)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +typedef void (OGLFUNCCALL *glScaled_fp)(GLdouble x, GLdouble y, GLdouble z); +typedef void (OGLFUNCCALL *glScalef_fp)(GLfloat x, GLfloat y, GLfloat z); +typedef void (OGLFUNCCALL *glScissor_fp)(GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (OGLFUNCCALL *glSelectBuffer_fp)(GLsizei size, GLuint *buffer); +typedef void (OGLFUNCCALL *glShadeModel_fp)(GLenum mode); +typedef void (OGLFUNCCALL *glStencilFunc_fp)(GLenum func, GLint ref, GLuint mask); +typedef void (OGLFUNCCALL *glStencilMask_fp)(GLuint mask); +typedef void (OGLFUNCCALL *glStencilOp_fp)(GLenum fail, GLenum zfail, GLenum zpass); +typedef void (OGLFUNCCALL *glTexCoord1d_fp)(GLdouble s); +typedef void (OGLFUNCCALL *glTexCoord1dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glTexCoord1f_fp)(GLfloat s); +typedef void (OGLFUNCCALL *glTexCoord1fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glTexCoord1i_fp)(GLint s); +typedef void (OGLFUNCCALL *glTexCoord1iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glTexCoord1s_fp)(GLshort s); +typedef void (OGLFUNCCALL *glTexCoord1sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glTexCoord2d_fp)(GLdouble s, GLdouble t); +typedef void (OGLFUNCCALL *glTexCoord2dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glTexCoord2f_fp)(GLfloat s, GLfloat t); +typedef void (OGLFUNCCALL *glTexCoord2fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glTexCoord2i_fp)(GLint s, GLint t); +typedef void (OGLFUNCCALL *glTexCoord2iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glTexCoord2s_fp)(GLshort s, GLshort t); +typedef void (OGLFUNCCALL *glTexCoord2sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glTexCoord3d_fp)(GLdouble s, GLdouble t, GLdouble r); +typedef void (OGLFUNCCALL *glTexCoord3dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glTexCoord3f_fp)(GLfloat s, GLfloat t, GLfloat r); +typedef void (OGLFUNCCALL *glTexCoord3fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glTexCoord3i_fp)(GLint s, GLint t, GLint r); +typedef void (OGLFUNCCALL *glTexCoord3iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glTexCoord3s_fp)(GLshort s, GLshort t, GLshort r); +typedef void (OGLFUNCCALL *glTexCoord3sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glTexCoord4d_fp)(GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (OGLFUNCCALL *glTexCoord4dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glTexCoord4f_fp)(GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (OGLFUNCCALL *glTexCoord4fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glTexCoord4i_fp)(GLint s, GLint t, GLint r, GLint q); +typedef void (OGLFUNCCALL *glTexCoord4iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glTexCoord4s_fp)(GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (OGLFUNCCALL *glTexCoord4sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glTexCoordPointer_fp)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (OGLFUNCCALL *glTexEnvf_fp)(GLenum target, GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glTexEnvfv_fp)(GLenum target, GLenum pname, const GLfloat *params); +typedef void (OGLFUNCCALL *glTexEnvi_fp)(GLenum target, GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glTexEnviv_fp)(GLenum target, GLenum pname, const GLint *params); +typedef void (OGLFUNCCALL *glTexGend_fp)(GLenum coord, GLenum pname, GLdouble param); +typedef void (OGLFUNCCALL *glTexGendv_fp)(GLenum coord, GLenum pname, const GLdouble *params); +typedef void (OGLFUNCCALL *glTexGenf_fp)(GLenum coord, GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glTexGenfv_fp)(GLenum coord, GLenum pname, const GLfloat *params); +typedef void (OGLFUNCCALL *glTexGeni_fp)(GLenum coord, GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glTexGeniv_fp)(GLenum coord, GLenum pname, const GLint *params); +typedef void (OGLFUNCCALL *glTexImage1D_fp)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (OGLFUNCCALL *glTexImage2D_fp)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (OGLFUNCCALL *glTexParameterf_fp)(GLenum target, GLenum pname, GLfloat param); +typedef void (OGLFUNCCALL *glTexParameterfv_fp)(GLenum target, GLenum pname, const GLfloat *params); +typedef void (OGLFUNCCALL *glTexParameteri_fp)(GLenum target, GLenum pname, GLint param); +typedef void (OGLFUNCCALL *glTexParameteriv_fp)(GLenum target, GLenum pname, const GLint *params); +typedef void (OGLFUNCCALL *glTexSubImage1D_fp)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (OGLFUNCCALL *glTexSubImage2D_fp)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (OGLFUNCCALL *glTranslated_fp)(GLdouble x, GLdouble y, GLdouble z); +typedef void (OGLFUNCCALL *glTranslatef_fp)(GLfloat x, GLfloat y, GLfloat z); +typedef void (OGLFUNCCALL *glVertex2d_fp)(GLdouble x, GLdouble y); +typedef void (OGLFUNCCALL *glVertex2dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glVertex2f_fp)(GLfloat x, GLfloat y); +typedef void (OGLFUNCCALL *glVertex2fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glVertex2i_fp)(GLint x, GLint y); +typedef void (OGLFUNCCALL *glVertex2iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glVertex2s_fp)(GLshort x, GLshort y); +typedef void (OGLFUNCCALL *glVertex2sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glVertex3d_fp)(GLdouble x, GLdouble y, GLdouble z); +typedef void (OGLFUNCCALL *glVertex3dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glVertex3f_fp)(GLfloat x, GLfloat y, GLfloat z); +typedef void (OGLFUNCCALL *glVertex3fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glVertex3i_fp)(GLint x, GLint y, GLint z); +typedef void (OGLFUNCCALL *glVertex3iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glVertex3s_fp)(GLshort x, GLshort y, GLshort z); +typedef void (OGLFUNCCALL *glVertex3sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glVertex4d_fp)(GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (OGLFUNCCALL *glVertex4dv_fp)(const GLdouble *v); +typedef void (OGLFUNCCALL *glVertex4f_fp)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (OGLFUNCCALL *glVertex4fv_fp)(const GLfloat *v); +typedef void (OGLFUNCCALL *glVertex4i_fp)(GLint x, GLint y, GLint z, GLint w); +typedef void (OGLFUNCCALL *glVertex4iv_fp)(const GLint *v); +typedef void (OGLFUNCCALL *glVertex4s_fp)(GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (OGLFUNCCALL *glVertex4sv_fp)(const GLshort *v); +typedef void (OGLFUNCCALL *glVertexPointer_fp)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (OGLFUNCCALL *glViewport_fp)(GLint x, GLint y, GLsizei width, GLsizei height); + +#ifdef WIN32 +typedef BOOL (OGLFUNCCALL *wglCopyContext_fp)(HGLRC, HGLRC, UINT); +typedef HGLRC (OGLFUNCCALL *wglCreateContext_fp)(HDC); +typedef HGLRC (OGLFUNCCALL *wglCreateLayerContext_fp)(HDC, int); +typedef BOOL (OGLFUNCCALL *wglDeleteContext_fp)(HGLRC); +typedef HGLRC (OGLFUNCCALL *wglGetCurrentContext_fp)(VOID); +typedef HDC (OGLFUNCCALL *wglGetCurrentDC_fp)(VOID); +typedef PROC (OGLFUNCCALL *wglGetProcAddress_fp)(LPCSTR); +typedef BOOL (OGLFUNCCALL *wglMakeCurrent_fp)(HDC, HGLRC); +typedef BOOL (OGLFUNCCALL *wglShareLists_fp)(HGLRC, HGLRC); +typedef BOOL (OGLFUNCCALL *wglUseFontBitmapsA_fp)(HDC, DWORD, DWORD, DWORD); +typedef BOOL (OGLFUNCCALL *wglUseFontBitmapsW_fp)(HDC, DWORD, DWORD, DWORD); +typedef BOOL (OGLFUNCCALL *wglUseFontOutlinesA_fp)(HDC, DWORD, DWORD, DWORD, FLOAT,FLOAT, int, LPGLYPHMETRICSFLOAT); +typedef BOOL (OGLFUNCCALL *wglUseFontOutlinesW_fp)(HDC, DWORD, DWORD, DWORD, FLOAT,FLOAT, int, LPGLYPHMETRICSFLOAT); +typedef BOOL (OGLFUNCCALL *wglDescribeLayerPlane_fp)(HDC, int, int, UINT,LPLAYERPLANEDESCRIPTOR); +typedef int (OGLFUNCCALL *wglSetLayerPaletteEntries_fp)(HDC, int, int, int,CONST COLORREF *); +typedef int (OGLFUNCCALL *wglGetLayerPaletteEntries_fp)(HDC, int, int, int,COLORREF *); +typedef BOOL (OGLFUNCCALL *wglRealizeLayerPalette_fp)(HDC, int, BOOL); +typedef BOOL (OGLFUNCCALL *wglSwapLayerBuffers_fp)(HDC, UINT); +#if (WINVER >= 0x0500) +typedef DWORD (OGLFUNCCALL *wglSwapMultipleBuffers_fp)(UINT, CONST WGLSWAP *); +#endif +#endif + +DEFVAR glAccum_fp dglAccum; +DEFVAR glAlphaFunc_fp dglAlphaFunc; +DEFVAR glAreTexturesResident_fp dglAreTexturesResident; +DEFVAR glArrayElement_fp dglArrayElement; +DEFVAR glBegin_fp dglBegin; +DEFVAR glBindTexture_fp dglBindTexture; +DEFVAR glBitmap_fp dglBitmap; +DEFVAR glBlendFunc_fp dglBlendFunc; +DEFVAR glCallList_fp dglCallList; +DEFVAR glCallLists_fp dglCallLists; +DEFVAR glClear_fp dglClear; +DEFVAR glClearAccum_fp dglClearAccum; +DEFVAR glClearColor_fp dglClearColor; +DEFVAR glClearDepth_fp dglClearDepth; +DEFVAR glClearIndex_fp dglClearIndex; +DEFVAR glClearStencil_fp dglClearStencil; +DEFVAR glClipPlane_fp dglClipPlane; +DEFVAR glColor3b_fp dglColor3b; +DEFVAR glColor3bv_fp dglColor3bv; +DEFVAR glColor3d_fp dglColor3d; +DEFVAR glColor3dv_fp dglColor3dv; +DEFVAR glColor3f_fp dglColor3f; +DEFVAR glColor3fv_fp dglColor3fv; +DEFVAR glColor3i_fp dglColor3i; +DEFVAR glColor3iv_fp dglColor3iv; +DEFVAR glColor3s_fp dglColor3s; +DEFVAR glColor3sv_fp dglColor3sv; +DEFVAR glColor3ub_fp dglColor3ub; +DEFVAR glColor3ubv_fp dglColor3ubv; +DEFVAR glColor3ui_fp dglColor3ui; +DEFVAR glColor3uiv_fp dglColor3uiv; +DEFVAR glColor3us_fp dglColor3us; +DEFVAR glColor3usv_fp dglColor3usv; +DEFVAR glColor4b_fp dglColor4b; +DEFVAR glColor4bv_fp dglColor4bv; +DEFVAR glColor4d_fp dglColor4d; +DEFVAR glColor4dv_fp dglColor4dv; +DEFVAR glColor4f_fp dglColor4f; +DEFVAR glColor4fv_fp dglColor4fv; +DEFVAR glColor4i_fp dglColor4i; +DEFVAR glColor4iv_fp dglColor4iv; +DEFVAR glColor4s_fp dglColor4s; +DEFVAR glColor4sv_fp dglColor4sv; +DEFVAR glColor4ub_fp dglColor4ub; +DEFVAR glColor4ubv_fp dglColor4ubv; +DEFVAR glColor4ui_fp dglColor4ui; +DEFVAR glColor4uiv_fp dglColor4uiv; +DEFVAR glColor4us_fp dglColor4us; +DEFVAR glColor4usv_fp dglColor4usv; +DEFVAR glColorMask_fp dglColorMask; +DEFVAR glColorMaterial_fp dglColorMaterial; +DEFVAR glColorPointer_fp dglColorPointer; +DEFVAR glCopyPixels_fp dglCopyPixels; +DEFVAR glCopyTexImage1D_fp dglCopyTexImage1D; +DEFVAR glCopyTexImage2D_fp dglCopyTexImage2D; +DEFVAR glCopyTexSubImage1D_fp dglCopyTexSubImage1D; +DEFVAR glCopyTexSubImage2D_fp dglCopyTexSubImage2D; +DEFVAR glCullFace_fp dglCullFace; +DEFVAR glDeleteLists_fp dglDeleteLists; +DEFVAR glDeleteTextures_fp dglDeleteTextures; +DEFVAR glDepthFunc_fp dglDepthFunc; +DEFVAR glDepthMask_fp dglDepthMask; +DEFVAR glDepthRange_fp dglDepthRange; +DEFVAR glDisable_fp dglDisable; +DEFVAR glDisableClientState_fp dglDisableClientState; +DEFVAR glDrawArrays_fp dglDrawArrays; +DEFVAR glDrawBuffer_fp dglDrawBuffer; +DEFVAR glDrawElements_fp dglDrawElements; +DEFVAR glDrawPixels_fp dglDrawPixels; +DEFVAR glEdgeFlag_fp dglEdgeFlag; +DEFVAR glEdgeFlagPointer_fp dglEdgeFlagPointer; +DEFVAR glEdgeFlagv_fp dglEdgeFlagv; +DEFVAR glEnable_fp dglEnable; +DEFVAR glEnableClientState_fp dglEnableClientState; +DEFVAR glEnd_fp dglEnd; +DEFVAR glEndList_fp dglEndList; +DEFVAR glEvalCoord1d_fp dglEvalCoord1d; +DEFVAR glEvalCoord1dv_fp dglEvalCoord1dv; +DEFVAR glEvalCoord1f_fp dglEvalCoord1f; +DEFVAR glEvalCoord1fv_fp dglEvalCoord1fv; +DEFVAR glEvalCoord2d_fp dglEvalCoord2d; +DEFVAR glEvalCoord2dv_fp dglEvalCoord2dv; +DEFVAR glEvalCoord2f_fp dglEvalCoord2f; +DEFVAR glEvalCoord2fv_fp dglEvalCoord2fv; +DEFVAR glEvalMesh1_fp dglEvalMesh1; +DEFVAR glEvalMesh2_fp dglEvalMesh2; +DEFVAR glEvalPoint1_fp dglEvalPoint1; +DEFVAR glEvalPoint2_fp dglEvalPoint2; +DEFVAR glFeedbackBuffer_fp dglFeedbackBuffer; +DEFVAR glFinish_fp dglFinish; +DEFVAR glFlush_fp dglFlush; +DEFVAR glFogf_fp dglFogf; +DEFVAR glFogfv_fp dglFogfv; +DEFVAR glFogi_fp dglFogi; +DEFVAR glFogiv_fp dglFogiv; +DEFVAR glFrontFace_fp dglFrontFace; +DEFVAR glFrustum_fp dglFrustum; +DEFVAR glGenLists_fp dglGenLists; +DEFVAR glGenTextures_fp dglGenTextures; +DEFVAR glGetBooleanv_fp dglGetBooleanv; +DEFVAR glGetClipPlane_fp dglGetClipPlane; +DEFVAR glGetDoublev_fp dglGetDoublev; +DEFVAR glGetError_fp dglGetError; +DEFVAR glGetFloatv_fp dglGetFloatv; +DEFVAR glGetIntegerv_fp dglGetIntegerv; +DEFVAR glGetLightfv_fp dglGetLightfv; +DEFVAR glGetLightiv_fp dglGetLightiv; +DEFVAR glGetMapdv_fp dglGetMapdv; +DEFVAR glGetMapfv_fp dglGetMapfv; +DEFVAR glGetMapiv_fp dglGetMapiv; +DEFVAR glGetMaterialfv_fp dglGetMaterialfv; +DEFVAR glGetMaterialiv_fp dglGetMaterialiv; +DEFVAR glGetPixelMapfv_fp dglGetPixelMapfv; +DEFVAR glGetPixelMapuiv_fp dglGetPixelMapuiv; +DEFVAR glGetPixelMapusv_fp dglGetPixelMapusv; +DEFVAR glGetPointerv_fp dglGetPointerv; +DEFVAR glGetPolygonStipple_fp dglGetPolygonStipple; +DEFVAR glGetString_fp dglGetString; +DEFVAR glGetTexEnvfv_fp dglGetTexEnvfv; +DEFVAR glGetTexEnviv_fp dglGetTexEnviv; +DEFVAR glGetTexGendv_fp dglGetTexGendv; +DEFVAR glGetTexGenfv_fp dglGetTexGenfv; +DEFVAR glGetTexGeniv_fp dglGetTexGeniv; +DEFVAR glGetTexImage_fp dglGetTexImage; +DEFVAR glGetTexLevelParameterfv_fp dglGetTexLevelParameterfv; +DEFVAR glGetTexLevelParameteriv_fp dglGetTexLevelParameteriv; +DEFVAR glGetTexParameterfv_fp dglGetTexParameterfv; +DEFVAR glGetTexParameteriv_fp dglGetTexParameteriv; +DEFVAR glHint_fp dglHint; +DEFVAR glIndexMask_fp dglIndexMask; +DEFVAR glIndexPointer_fp dglIndexPointer; +DEFVAR glIndexd_fp dglIndexd; +DEFVAR glIndexdv_fp dglIndexdv; +DEFVAR glIndexf_fp dglIndexf; +DEFVAR glIndexfv_fp dglIndexfv; +DEFVAR glIndexi_fp dglIndexi; +DEFVAR glIndexiv_fp dglIndexiv; +DEFVAR glIndexs_fp dglIndexs; +DEFVAR glIndexsv_fp dglIndexsv; +DEFVAR glIndexub_fp dglIndexub; +DEFVAR glIndexubv_fp dglIndexubv; +DEFVAR glInitNames_fp dglInitNames; +DEFVAR glInterleavedArrays_fp dglInterleavedArrays; +DEFVAR glIsEnabled_fp dglIsEnabled; +DEFVAR glIsList_fp dglIsList; +DEFVAR glIsTexture_fp dglIsTexture; +DEFVAR glLightModelf_fp dglLightModelf; +DEFVAR glLightModelfv_fp dglLightModelfv; +DEFVAR glLightModeli_fp dglLightModeli; +DEFVAR glLightModeliv_fp dglLightModeliv; +DEFVAR glLightf_fp dglLightf; +DEFVAR glLightfv_fp dglLightfv; +DEFVAR glLighti_fp dglLighti; +DEFVAR glLightiv_fp dglLightiv; +DEFVAR glLineStipple_fp dglLineStipple; +DEFVAR glLineWidth_fp dglLineWidth; +DEFVAR glListBase_fp dglListBase; +DEFVAR glLoadIdentity_fp dglLoadIdentity; +DEFVAR glLoadMatrixd_fp dglLoadMatrixd; +DEFVAR glLoadMatrixf_fp dglLoadMatrixf; +DEFVAR glLoadName_fp dglLoadName; +DEFVAR glLogicOp_fp dglLogicOp; +DEFVAR glMap1d_fp dglMap1d; +DEFVAR glMap1f_fp dglMap1f; +DEFVAR glMap2d_fp dglMap2d; +DEFVAR glMap2f_fp dglMap2f; +DEFVAR glMapGrid1d_fp dglMapGrid1d; +DEFVAR glMapGrid1f_fp dglMapGrid1f; +DEFVAR glMapGrid2d_fp dglMapGrid2d; +DEFVAR glMapGrid2f_fp dglMapGrid2f; +DEFVAR glMaterialf_fp dglMaterialf; +DEFVAR glMaterialfv_fp dglMaterialfv; +DEFVAR glMateriali_fp dglMateriali; +DEFVAR glMaterialiv_fp dglMaterialiv; +DEFVAR glMatrixMode_fp dglMatrixMode; +DEFVAR glMultMatrixd_fp dglMultMatrixd; +DEFVAR glMultMatrixf_fp dglMultMatrixf; +DEFVAR glNewList_fp dglNewList; +DEFVAR glNormal3b_fp dglNormal3b; +DEFVAR glNormal3bv_fp dglNormal3bv; +DEFVAR glNormal3d_fp dglNormal3d; +DEFVAR glNormal3dv_fp dglNormal3dv; +DEFVAR glNormal3f_fp dglNormal3f; +DEFVAR glNormal3fv_fp dglNormal3fv; +DEFVAR glNormal3i_fp dglNormal3i; +DEFVAR glNormal3iv_fp dglNormal3iv; +DEFVAR glNormal3s_fp dglNormal3s; +DEFVAR glNormal3sv_fp dglNormal3sv; +DEFVAR glNormalPointer_fp dglNormalPointer; +DEFVAR glOrtho_fp dglOrtho; +DEFVAR glPassThrough_fp dglPassThrough; +DEFVAR glPixelMapfv_fp dglPixelMapfv; +DEFVAR glPixelMapuiv_fp dglPixelMapuiv; +DEFVAR glPixelMapusv_fp dglPixelMapusv; +DEFVAR glPixelStoref_fp dglPixelStoref; +DEFVAR glPixelStorei_fp dglPixelStorei; +DEFVAR glPixelTransferf_fp dglPixelTransferf; +DEFVAR glPixelTransferi_fp dglPixelTransferi; +DEFVAR glPixelZoom_fp dglPixelZoom; +DEFVAR glPointSize_fp dglPointSize; +DEFVAR glPolygonMode_fp dglPolygonMode; +DEFVAR glPolygonOffset_fp dglPolygonOffset; +DEFVAR glPolygonStipple_fp dglPolygonStipple; +DEFVAR glPopAttrib_fp dglPopAttrib; +DEFVAR glPopClientAttrib_fp dglPopClientAttrib; +DEFVAR glPopMatrix_fp dglPopMatrix; +DEFVAR glPopName_fp dglPopName; +DEFVAR glPrioritizeTextures_fp dglPrioritizeTextures; +DEFVAR glPushAttrib_fp dglPushAttrib; +DEFVAR glPushClientAttrib_fp dglPushClientAttrib; +DEFVAR glPushMatrix_fp dglPushMatrix; +DEFVAR glPushName_fp dglPushName; +DEFVAR glRasterPos2d_fp dglRasterPos2d; +DEFVAR glRasterPos2dv_fp dglRasterPos2dv; +DEFVAR glRasterPos2f_fp dglRasterPos2f; +DEFVAR glRasterPos2fv_fp dglRasterPos2fv; +DEFVAR glRasterPos2i_fp dglRasterPos2i; +DEFVAR glRasterPos2iv_fp dglRasterPos2iv; +DEFVAR glRasterPos2s_fp dglRasterPos2s; +DEFVAR glRasterPos2sv_fp dglRasterPos2sv; +DEFVAR glRasterPos3d_fp dglRasterPos3d; +DEFVAR glRasterPos3dv_fp dglRasterPos3dv; +DEFVAR glRasterPos3f_fp dglRasterPos3f; +DEFVAR glRasterPos3fv_fp dglRasterPos3fv; +DEFVAR glRasterPos3i_fp dglRasterPos3i; +DEFVAR glRasterPos3iv_fp dglRasterPos3iv; +DEFVAR glRasterPos3s_fp dglRasterPos3s; +DEFVAR glRasterPos3sv_fp dglRasterPos3sv; +DEFVAR glRasterPos4d_fp dglRasterPos4d; +DEFVAR glRasterPos4dv_fp dglRasterPos4dv; +DEFVAR glRasterPos4f_fp dglRasterPos4f; +DEFVAR glRasterPos4fv_fp dglRasterPos4fv; +DEFVAR glRasterPos4i_fp dglRasterPos4i; +DEFVAR glRasterPos4iv_fp dglRasterPos4iv; +DEFVAR glRasterPos4s_fp dglRasterPos4s; +DEFVAR glRasterPos4sv_fp dglRasterPos4sv; +DEFVAR glReadBuffer_fp dglReadBuffer; +DEFVAR glReadPixels_fp dglReadPixels; +DEFVAR glRectd_fp dglRectd; +DEFVAR glRectdv_fp dglRectdv; +DEFVAR glRectf_fp dglRectf; +DEFVAR glRectfv_fp dglRectfv; +DEFVAR glRecti_fp dglRecti; +DEFVAR glRectiv_fp dglRectiv; +DEFVAR glRects_fp dglRects; +DEFVAR glRectsv_fp dglRectsv; +DEFVAR glRenderMode_fp dglRenderMode; +DEFVAR glRotated_fp dglRotated; +DEFVAR glRotatef_fp dglRotatef; +DEFVAR glScaled_fp dglScaled; +DEFVAR glScalef_fp dglScalef; +DEFVAR glScissor_fp dglScissor; +DEFVAR glSelectBuffer_fp dglSelectBuffer; +DEFVAR glShadeModel_fp dglShadeModel; +DEFVAR glStencilFunc_fp dglStencilFunc; +DEFVAR glStencilMask_fp dglStencilMask; +DEFVAR glStencilOp_fp dglStencilOp; +DEFVAR glTexCoord1d_fp dglTexCoord1d; +DEFVAR glTexCoord1dv_fp dglTexCoord1dv; +DEFVAR glTexCoord1f_fp dglTexCoord1f; +DEFVAR glTexCoord1fv_fp dglTexCoord1fv; +DEFVAR glTexCoord1i_fp dglTexCoord1i; +DEFVAR glTexCoord1iv_fp dglTexCoord1iv; +DEFVAR glTexCoord1s_fp dglTexCoord1s; +DEFVAR glTexCoord1sv_fp dglTexCoord1sv; +DEFVAR glTexCoord2d_fp dglTexCoord2d; +DEFVAR glTexCoord2dv_fp dglTexCoord2dv; +DEFVAR glTexCoord2f_fp dglTexCoord2f; +DEFVAR glTexCoord2fv_fp dglTexCoord2fv; +DEFVAR glTexCoord2i_fp dglTexCoord2i; +DEFVAR glTexCoord2iv_fp dglTexCoord2iv; +DEFVAR glTexCoord2s_fp dglTexCoord2s; +DEFVAR glTexCoord2sv_fp dglTexCoord2sv; +DEFVAR glTexCoord3d_fp dglTexCoord3d; +DEFVAR glTexCoord3dv_fp dglTexCoord3dv; +DEFVAR glTexCoord3f_fp dglTexCoord3f; +DEFVAR glTexCoord3fv_fp dglTexCoord3fv; +DEFVAR glTexCoord3i_fp dglTexCoord3i; +DEFVAR glTexCoord3iv_fp dglTexCoord3iv; +DEFVAR glTexCoord3s_fp dglTexCoord3s; +DEFVAR glTexCoord3sv_fp dglTexCoord3sv; +DEFVAR glTexCoord4d_fp dglTexCoord4d; +DEFVAR glTexCoord4dv_fp dglTexCoord4dv; +DEFVAR glTexCoord4f_fp dglTexCoord4f; +DEFVAR glTexCoord4fv_fp dglTexCoord4fv; +DEFVAR glTexCoord4i_fp dglTexCoord4i; +DEFVAR glTexCoord4iv_fp dglTexCoord4iv; +DEFVAR glTexCoord4s_fp dglTexCoord4s; +DEFVAR glTexCoord4sv_fp dglTexCoord4sv; +DEFVAR glTexCoordPointer_fp dglTexCoordPointer; +DEFVAR glTexEnvf_fp dglTexEnvf; +DEFVAR glTexEnvfv_fp dglTexEnvfv; +DEFVAR glTexEnvi_fp dglTexEnvi; +DEFVAR glTexEnviv_fp dglTexEnviv; +DEFVAR glTexGend_fp dglTexGend; +DEFVAR glTexGendv_fp dglTexGendv; +DEFVAR glTexGenf_fp dglTexGenf; +DEFVAR glTexGenfv_fp dglTexGenfv; +DEFVAR glTexGeni_fp dglTexGeni; +DEFVAR glTexGeniv_fp dglTexGeniv; +DEFVAR glTexImage1D_fp dglTexImage1D; +DEFVAR glTexImage2D_fp dglTexImage2D; +DEFVAR glTexParameterf_fp dglTexParameterf; +DEFVAR glTexParameterfv_fp dglTexParameterfv; +DEFVAR glTexParameteri_fp dglTexParameteri; +DEFVAR glTexParameteriv_fp dglTexParameteriv; +DEFVAR glTexSubImage1D_fp dglTexSubImage1D; +DEFVAR glTexSubImage2D_fp dglTexSubImage2D; +DEFVAR glTranslated_fp dglTranslated; +DEFVAR glTranslatef_fp dglTranslatef; +DEFVAR glVertex2d_fp dglVertex2d; +DEFVAR glVertex2dv_fp dglVertex2dv; +DEFVAR glVertex2f_fp dglVertex2f; +DEFVAR glVertex2fv_fp dglVertex2fv; +DEFVAR glVertex2i_fp dglVertex2i; +DEFVAR glVertex2iv_fp dglVertex2iv; +DEFVAR glVertex2s_fp dglVertex2s; +DEFVAR glVertex2sv_fp dglVertex2sv; +DEFVAR glVertex3d_fp dglVertex3d; +DEFVAR glVertex3dv_fp dglVertex3dv; +DEFVAR glVertex3f_fp dglVertex3f; +DEFVAR glVertex3fv_fp dglVertex3fv; +DEFVAR glVertex3i_fp dglVertex3i; +DEFVAR glVertex3iv_fp dglVertex3iv; +DEFVAR glVertex3s_fp dglVertex3s; +DEFVAR glVertex3sv_fp dglVertex3sv; +DEFVAR glVertex4d_fp dglVertex4d; +DEFVAR glVertex4dv_fp dglVertex4dv; +DEFVAR glVertex4f_fp dglVertex4f; +DEFVAR glVertex4fv_fp dglVertex4fv; +DEFVAR glVertex4i_fp dglVertex4i; +DEFVAR glVertex4iv_fp dglVertex4iv; +DEFVAR glVertex4s_fp dglVertex4s; +DEFVAR glVertex4sv_fp dglVertex4sv; +DEFVAR glVertexPointer_fp dglVertexPointer; +DEFVAR glViewport_fp dglViewport; + +#ifdef WIN32 +DEFVAR wglCopyContext_fp dwglCopyContext; +DEFVAR wglCreateContext_fp dwglCreateContext; +DEFVAR wglCreateLayerContext_fp dwglCreateLayerContext; +DEFVAR wglDeleteContext_fp dwglDeleteContext; +DEFVAR wglGetCurrentContext_fp dwglGetCurrentContext; +DEFVAR wglGetCurrentDC_fp dwglGetCurrentDC; +DEFVAR wglGetProcAddress_fp dwglGetProcAddress; +DEFVAR wglMakeCurrent_fp dwglMakeCurrent; +DEFVAR wglShareLists_fp dwglShareLists; +DEFVAR wglUseFontBitmapsA_fp dwglUseFontBitmapsA; +DEFVAR wglUseFontBitmapsW_fp dwglUseFontBitmapsW; +DEFVAR wglUseFontOutlinesA_fp dwglUseFontOutlinesA; +DEFVAR wglUseFontOutlinesW_fp dwglUseFontOutlinesW; +DEFVAR wglDescribeLayerPlane_fp dwglDescribeLayerPlane; +DEFVAR wglSetLayerPaletteEntries_fp dwglSetLayerPaletteEntries; +DEFVAR wglGetLayerPaletteEntries_fp dwglGetLayerPaletteEntries; +DEFVAR wglRealizeLayerPalette_fp dwglRealizeLayerPalette; +DEFVAR wglSwapLayerBuffers_fp dwglSwapLayerBuffers; +#if (WINVER >= 0x0500) +DEFVAR wglSwapMultipleBuffers_fp dwglSwapMultipleBuffers; +#endif +#endif + +#ifdef DECLARE_VARS + +// Dynamic module load functions +#ifdef WIN32 +void *dll_LoadModule(const char *name) +{ + HINSTANCE handle; + handle = LoadLibrary(name); + return (void *)handle; +} +void dll_UnloadModule(void *hdl) +{ + HINSTANCE handle; + handle = (HINSTANCE)hdl; + + if(hdl) + { + FreeLibrary(handle); + } +} +void *dll_GetSymbol(void *dllhandle,const char *symname) +{ + if(!dllhandle) + return NULL; + return (void *)GetProcAddress((HINSTANCE)dllhandle,symname); +} +#endif +#ifdef __LINUX__ +#include +void *dll_LoadModule(const char *name) +{ + return (void *)dlopen(name,RTLD_NOW|RTLD_GLOBAL); +} +void dll_UnloadModule(void *hdl) +{ + if(hdl) + { + dlclose(hdl); + } +} +void *dll_GetSymbol(void *dllhandle,const char *symname) +{ + if(!dllhandle) + return NULL; + return dlsym(dllhandle,symname); +} +#endif + +#endif //DECLARE_VARS + +void OpenGL_SetFuncsToNull(void); + +extern char *OglLibPath; + +#ifndef DECLARE_VARS +// pass true to load the library +// pass false to unload it +bool OpenGL_LoadLibrary(bool load);//load=true removed because not c++ +#else +void *OpenGLModuleHandle=NULL; +//char *OglLibPath="opengl32.dll"; +bool OpenGL_LoadLibrary(bool load) +{ + if(load && OpenGLModuleHandle) + return true; + + OpenGL_SetFuncsToNull(); + + if(!load) + { + if(OpenGLModuleHandle) + { + dll_UnloadModule(OpenGLModuleHandle); + OpenGLModuleHandle = NULL; + } + return true; + }else + { + OpenGLModuleHandle = dll_LoadModule(OglLibPath); + if(!OpenGLModuleHandle) + return false; + + dglAccum = (glAccum_fp)dll_GetSymbol(OpenGLModuleHandle,"glAccum"); + dglAlphaFunc = (glAlphaFunc_fp)dll_GetSymbol(OpenGLModuleHandle,"glAlphaFunc"); + dglAreTexturesResident = (glAreTexturesResident_fp)dll_GetSymbol(OpenGLModuleHandle,"glAreTexturesResident"); + dglArrayElement = (glArrayElement_fp)dll_GetSymbol(OpenGLModuleHandle,"glArrayElement"); + dglBegin = (glBegin_fp)dll_GetSymbol(OpenGLModuleHandle,"glBegin"); + dglBindTexture = (glBindTexture_fp)dll_GetSymbol(OpenGLModuleHandle,"glBindTexture"); + dglBitmap = (glBitmap_fp)dll_GetSymbol(OpenGLModuleHandle,"glBitmap"); + dglBlendFunc = (glBlendFunc_fp)dll_GetSymbol(OpenGLModuleHandle,"glBlendFunc"); + dglCallList = (glCallList_fp)dll_GetSymbol(OpenGLModuleHandle,"glCallList"); + dglCallLists = (glCallLists_fp)dll_GetSymbol(OpenGLModuleHandle,"glCallLists"); + dglClear = (glClear_fp)dll_GetSymbol(OpenGLModuleHandle,"glClear"); + dglClearAccum = (glClearAccum_fp)dll_GetSymbol(OpenGLModuleHandle,"glClearAccum"); + dglClearColor = (glClearColor_fp)dll_GetSymbol(OpenGLModuleHandle,"glClearColor"); + dglClearDepth = (glClearDepth_fp)dll_GetSymbol(OpenGLModuleHandle,"glClearDepth"); + dglClearIndex = (glClearIndex_fp)dll_GetSymbol(OpenGLModuleHandle,"glClearIndex"); + dglClearStencil = (glClearStencil_fp)dll_GetSymbol(OpenGLModuleHandle,"glClearStencil"); + dglClipPlane = (glClipPlane_fp)dll_GetSymbol(OpenGLModuleHandle,"glClipPlane"); + dglColor3b = (glColor3b_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3b"); + dglColor3bv = (glColor3bv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3bv"); + dglColor3d = (glColor3d_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3d"); + dglColor3dv = (glColor3dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3dv"); + dglColor3f = (glColor3f_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3f"); + dglColor3fv = (glColor3fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3fv"); + dglColor3i = (glColor3i_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3i"); + dglColor3iv = (glColor3iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3iv"); + dglColor3s = (glColor3s_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3s"); + dglColor3sv = (glColor3sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3sv"); + dglColor3ub = (glColor3ub_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3ub"); + dglColor3ubv = (glColor3ubv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3ubv"); + dglColor3ui = (glColor3ui_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3ui"); + dglColor3uiv = (glColor3uiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3uiv"); + dglColor3us = (glColor3us_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3us"); + dglColor3usv = (glColor3usv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3usv"); + dglColor4b = (glColor4b_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4b"); + dglColor4bv = (glColor4bv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4bv"); + dglColor4d = (glColor4d_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4d"); + dglColor4dv = (glColor4dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4dv"); + dglColor4f = (glColor4f_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4f"); + dglColor4fv = (glColor4fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4fv"); + dglColor4i = (glColor4i_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4i"); + dglColor4iv = (glColor4iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4iv"); + dglColor4s = (glColor4s_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4s"); + dglColor4sv = (glColor4sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4sv"); + dglColor4ub = (glColor4ub_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4ub"); + dglColor4ubv = (glColor4ubv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4ubv"); + dglColor4ui = (glColor4ui_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4ui"); + dglColor4uiv = (glColor4uiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4uiv"); + dglColor4us = (glColor4us_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4us"); + dglColor4usv = (glColor4usv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4usv"); + dglColorMask = (glColorMask_fp)dll_GetSymbol(OpenGLModuleHandle,"glColorMask"); + dglColorMaterial = (glColorMaterial_fp)dll_GetSymbol(OpenGLModuleHandle,"glColorMaterial"); + dglColorPointer = (glColorPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glColorPointer"); + dglCopyPixels = (glCopyPixels_fp)dll_GetSymbol(OpenGLModuleHandle,"glCopyPixels"); + dglCopyTexImage1D = (glCopyTexImage1D_fp)dll_GetSymbol(OpenGLModuleHandle,"glCopyTexImage1D"); + dglCopyTexImage2D = (glCopyTexImage2D_fp)dll_GetSymbol(OpenGLModuleHandle,"glCopyTexImage2D"); + dglCopyTexSubImage1D = (glCopyTexSubImage1D_fp)dll_GetSymbol(OpenGLModuleHandle,"glCopyTexSubImage1D"); + dglCopyTexSubImage2D = (glCopyTexSubImage2D_fp)dll_GetSymbol(OpenGLModuleHandle,"glCopyTexSubImage2D"); + dglCullFace = (glCullFace_fp)dll_GetSymbol(OpenGLModuleHandle,"glCullFace"); + dglDeleteLists = (glDeleteLists_fp)dll_GetSymbol(OpenGLModuleHandle,"glDeleteLists"); + dglDeleteTextures = (glDeleteTextures_fp)dll_GetSymbol(OpenGLModuleHandle,"glDeleteTextures"); + dglDepthFunc = (glDepthFunc_fp)dll_GetSymbol(OpenGLModuleHandle,"glDepthFunc"); + dglDepthMask = (glDepthMask_fp)dll_GetSymbol(OpenGLModuleHandle,"glDepthMask"); + dglDepthRange = (glDepthRange_fp)dll_GetSymbol(OpenGLModuleHandle,"glDepthRange"); + dglDisable = (glDisable_fp)dll_GetSymbol(OpenGLModuleHandle,"glDisable"); + dglDisableClientState = (glDisableClientState_fp)dll_GetSymbol(OpenGLModuleHandle,"glDisableClientState"); + dglDrawArrays = (glDrawArrays_fp)dll_GetSymbol(OpenGLModuleHandle,"glDrawArrays"); + dglDrawBuffer = (glDrawBuffer_fp)dll_GetSymbol(OpenGLModuleHandle,"glDrawBuffer"); + dglDrawElements = (glDrawElements_fp)dll_GetSymbol(OpenGLModuleHandle,"glDrawElements"); + dglDrawPixels = (glDrawPixels_fp)dll_GetSymbol(OpenGLModuleHandle,"glDrawPixels"); + dglEdgeFlag = (glEdgeFlag_fp)dll_GetSymbol(OpenGLModuleHandle,"glEdgeFlag"); + dglEdgeFlagPointer = (glEdgeFlagPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glEdgeFlagPointer"); + dglEdgeFlagv = (glEdgeFlagv_fp)dll_GetSymbol(OpenGLModuleHandle,"glEdgeFlagv"); + dglEnable = (glEnable_fp)dll_GetSymbol(OpenGLModuleHandle,"glEnable"); + dglEnableClientState = (glEnableClientState_fp)dll_GetSymbol(OpenGLModuleHandle,"glEnableClientState"); + dglEnd = (glEnd_fp)dll_GetSymbol(OpenGLModuleHandle,"glEnd"); + dglEndList = (glEndList_fp)dll_GetSymbol(OpenGLModuleHandle,"glEndList"); + dglEvalCoord1d = (glEvalCoord1d_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord1d"); + dglEvalCoord1dv = (glEvalCoord1dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord1dv"); + dglEvalCoord1f = (glEvalCoord1f_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord1f"); + dglEvalCoord1fv = (glEvalCoord1fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord1fv"); + dglEvalCoord2d = (glEvalCoord2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord2d"); + dglEvalCoord2dv = (glEvalCoord2dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord2dv"); + dglEvalCoord2f = (glEvalCoord2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord2f"); + dglEvalCoord2fv = (glEvalCoord2fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord2fv"); + dglEvalMesh1 = (glEvalMesh1_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalMesh1"); + dglEvalMesh2 = (glEvalMesh2_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalMesh2"); + dglEvalPoint1 = (glEvalPoint1_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalPoint1"); + dglEvalPoint2 = (glEvalPoint2_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalPoint2"); + dglFeedbackBuffer = (glFeedbackBuffer_fp)dll_GetSymbol(OpenGLModuleHandle,"glFeedbackBuffer"); + dglFinish = (glFinish_fp)dll_GetSymbol(OpenGLModuleHandle,"glFinish"); + dglFlush = (glFlush_fp)dll_GetSymbol(OpenGLModuleHandle,"glFlush"); + dglFogf = (glFogf_fp)dll_GetSymbol(OpenGLModuleHandle,"glFogf"); + dglFogfv = (glFogfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glFogfv"); + dglFogi = (glFogi_fp)dll_GetSymbol(OpenGLModuleHandle,"glFogi"); + dglFogiv = (glFogiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glFogiv"); + dglFrontFace = (glFrontFace_fp)dll_GetSymbol(OpenGLModuleHandle,"glFrontFace"); + dglFrustum = (glFrustum_fp)dll_GetSymbol(OpenGLModuleHandle,"glFrustum"); + dglGenLists = (glGenLists_fp)dll_GetSymbol(OpenGLModuleHandle,"glGenLists"); + dglGenTextures = (glGenTextures_fp)dll_GetSymbol(OpenGLModuleHandle,"glGenTextures"); + dglGetBooleanv = (glGetBooleanv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetBooleanv"); + dglGetClipPlane = (glGetClipPlane_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetClipPlane"); + dglGetDoublev = (glGetDoublev_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetDoublev"); + dglGetError = (glGetError_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetError"); + dglGetFloatv = (glGetFloatv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetFloatv"); + dglGetIntegerv = (glGetIntegerv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetIntegerv"); + dglGetLightfv = (glGetLightfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetLightfv"); + dglGetLightiv = (glGetLightiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetLightiv"); + dglGetMapdv = (glGetMapdv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetMapdv"); + dglGetMapfv = (glGetMapfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetMapfv"); + dglGetMapiv = (glGetMapiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetMapiv"); + dglGetMaterialfv = (glGetMaterialfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetMaterialfv"); + dglGetMaterialiv = (glGetMaterialiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetMaterialiv"); + dglGetPixelMapfv = (glGetPixelMapfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetPixelMapfv"); + dglGetPixelMapuiv = (glGetPixelMapuiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetPixelMapuiv"); + dglGetPixelMapusv = (glGetPixelMapusv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetPixelMapusv"); + dglGetPointerv = (glGetPointerv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetPointerv"); + dglGetPolygonStipple = (glGetPolygonStipple_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetPolygonStipple"); + dglGetString = (glGetString_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetString"); + dglGetTexEnvfv = (glGetTexEnvfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexEnvfv"); + dglGetTexEnviv = (glGetTexEnviv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexEnviv"); + dglGetTexGendv = (glGetTexGendv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexGendv"); + dglGetTexGenfv = (glGetTexGenfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexGenfv"); + dglGetTexGeniv = (glGetTexGeniv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexGeniv"); + dglGetTexImage = (glGetTexImage_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexImage"); + dglGetTexLevelParameterfv = (glGetTexLevelParameterfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexLevelParameterfv"); + dglGetTexLevelParameteriv = (glGetTexLevelParameteriv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexLevelParameteriv"); + dglGetTexParameterfv = (glGetTexParameterfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexParameterfv"); + dglGetTexParameteriv = (glGetTexParameteriv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexParameteriv"); + dglHint = (glHint_fp)dll_GetSymbol(OpenGLModuleHandle,"glHint"); + dglIndexMask = (glIndexMask_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexMask"); + dglIndexPointer = (glIndexPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexPointer"); + dglIndexd = (glIndexd_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexd"); + dglIndexdv = (glIndexdv_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexdv"); + dglIndexf = (glIndexf_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexf"); + dglIndexfv = (glIndexfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexfv"); + dglIndexi = (glIndexi_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexi"); + dglIndexiv = (glIndexiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexiv"); + dglIndexs = (glIndexs_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexs"); + dglIndexsv = (glIndexsv_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexsv"); + dglIndexub = (glIndexub_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexub"); + dglIndexubv = (glIndexubv_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexubv"); + dglInitNames = (glInitNames_fp)dll_GetSymbol(OpenGLModuleHandle,"glInitNames"); + dglInterleavedArrays = (glInterleavedArrays_fp)dll_GetSymbol(OpenGLModuleHandle,"glInterleavedArrays"); + dglIsEnabled = (glIsEnabled_fp)dll_GetSymbol(OpenGLModuleHandle,"glIsEnabled"); + dglIsList = (glIsList_fp)dll_GetSymbol(OpenGLModuleHandle,"glIsList"); + dglIsTexture = (glIsTexture_fp)dll_GetSymbol(OpenGLModuleHandle,"glIsTexture"); + dglLightModelf = (glLightModelf_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightModelf"); + dglLightModelfv = (glLightModelfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightModelfv"); + dglLightModeli = (glLightModeli_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightModeli"); + dglLightModeliv = (glLightModeliv_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightModeliv"); + dglLightf = (glLightf_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightf"); + dglLightfv = (glLightfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightfv"); + dglLighti = (glLighti_fp)dll_GetSymbol(OpenGLModuleHandle,"glLighti"); + dglLightiv = (glLightiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightiv"); + dglLineStipple = (glLineStipple_fp)dll_GetSymbol(OpenGLModuleHandle,"glLineStipple"); + dglLineWidth = (glLineWidth_fp)dll_GetSymbol(OpenGLModuleHandle,"glLineWidth"); + dglListBase = (glListBase_fp)dll_GetSymbol(OpenGLModuleHandle,"glListBase"); + dglLoadIdentity = (glLoadIdentity_fp)dll_GetSymbol(OpenGLModuleHandle,"glLoadIdentity"); + dglLoadMatrixd = (glLoadMatrixd_fp)dll_GetSymbol(OpenGLModuleHandle,"glLoadMatrixd"); + dglLoadMatrixf = (glLoadMatrixf_fp)dll_GetSymbol(OpenGLModuleHandle,"glLoadMatrixf"); + dglLoadName = (glLoadName_fp)dll_GetSymbol(OpenGLModuleHandle,"glLoadName"); + dglLogicOp = (glLogicOp_fp)dll_GetSymbol(OpenGLModuleHandle,"glLogicOp"); + dglMap1d = (glMap1d_fp)dll_GetSymbol(OpenGLModuleHandle,"glMap1d"); + dglMap1f = (glMap1f_fp)dll_GetSymbol(OpenGLModuleHandle,"glMap1f"); + dglMap2d = (glMap2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glMap2d"); + dglMap2f = (glMap2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glMap2f"); + dglMapGrid1d = (glMapGrid1d_fp)dll_GetSymbol(OpenGLModuleHandle,"glMapGrid1d"); + dglMapGrid1f = (glMapGrid1f_fp)dll_GetSymbol(OpenGLModuleHandle,"glMapGrid1f"); + dglMapGrid2d = (glMapGrid2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glMapGrid2d"); + dglMapGrid2f = (glMapGrid2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glMapGrid2f"); + dglMaterialf = (glMaterialf_fp)dll_GetSymbol(OpenGLModuleHandle,"glMaterialf"); + dglMaterialfv = (glMaterialfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glMaterialfv"); + dglMateriali = (glMateriali_fp)dll_GetSymbol(OpenGLModuleHandle,"glMateriali"); + dglMaterialiv = (glMaterialiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glMaterialiv"); + dglMatrixMode = (glMatrixMode_fp)dll_GetSymbol(OpenGLModuleHandle,"glMatrixMode"); + dglMultMatrixd = (glMultMatrixd_fp)dll_GetSymbol(OpenGLModuleHandle,"glMultMatrixd"); + dglMultMatrixf = (glMultMatrixf_fp)dll_GetSymbol(OpenGLModuleHandle,"glMultMatrixf"); + dglNewList = (glNewList_fp)dll_GetSymbol(OpenGLModuleHandle,"glNewList"); + dglNormal3b = (glNormal3b_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3b"); + dglNormal3bv = (glNormal3bv_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3bv"); + dglNormal3d = (glNormal3d_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3d"); + dglNormal3dv = (glNormal3dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3dv"); + dglNormal3f = (glNormal3f_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3f"); + dglNormal3fv = (glNormal3fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3fv"); + dglNormal3i = (glNormal3i_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3i"); + dglNormal3iv = (glNormal3iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3iv"); + dglNormal3s = (glNormal3s_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3s"); + dglNormal3sv = (glNormal3sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3sv"); + dglNormalPointer = (glNormalPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormalPointer"); + dglOrtho = (glOrtho_fp)dll_GetSymbol(OpenGLModuleHandle,"glOrtho"); + dglPassThrough = (glPassThrough_fp)dll_GetSymbol(OpenGLModuleHandle,"glPassThrough"); + dglPixelMapfv = (glPixelMapfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelMapfv"); + dglPixelMapuiv = (glPixelMapuiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelMapuiv"); + dglPixelMapusv = (glPixelMapusv_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelMapusv"); + dglPixelStoref = (glPixelStoref_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelStoref"); + dglPixelStorei = (glPixelStorei_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelStorei"); + dglPixelTransferf = (glPixelTransferf_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelTransferf"); + dglPixelTransferi = (glPixelTransferi_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelTransferi"); + dglPixelZoom = (glPixelZoom_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelZoom"); + dglPointSize = (glPointSize_fp)dll_GetSymbol(OpenGLModuleHandle,"glPointSize"); + dglPolygonMode = (glPolygonMode_fp)dll_GetSymbol(OpenGLModuleHandle,"glPolygonMode"); + dglPolygonOffset = (glPolygonOffset_fp)dll_GetSymbol(OpenGLModuleHandle,"glPolygonOffset"); + dglPolygonStipple = (glPolygonStipple_fp)dll_GetSymbol(OpenGLModuleHandle,"glPolygonStipple"); + dglPopAttrib = (glPopAttrib_fp)dll_GetSymbol(OpenGLModuleHandle,"glPopAttrib"); + dglPopClientAttrib = (glPopClientAttrib_fp)dll_GetSymbol(OpenGLModuleHandle,"glPopClientAttrib"); + dglPopMatrix = (glPopMatrix_fp)dll_GetSymbol(OpenGLModuleHandle,"glPopMatrix"); + dglPopName = (glPopName_fp)dll_GetSymbol(OpenGLModuleHandle,"glPopName"); + dglPrioritizeTextures = (glPrioritizeTextures_fp)dll_GetSymbol(OpenGLModuleHandle,"glPrioritizeTextures"); + dglPushAttrib = (glPushAttrib_fp)dll_GetSymbol(OpenGLModuleHandle,"glPushAttrib"); + dglPushClientAttrib = (glPushClientAttrib_fp)dll_GetSymbol(OpenGLModuleHandle,"glPushClientAttrib"); + dglPushMatrix = (glPushMatrix_fp)dll_GetSymbol(OpenGLModuleHandle,"glPushMatrix"); + dglPushName = (glPushName_fp)dll_GetSymbol(OpenGLModuleHandle,"glPushName"); + dglRasterPos2d = (glRasterPos2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2d"); + dglRasterPos2dv = (glRasterPos2dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2dv"); + dglRasterPos2f = (glRasterPos2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2f"); + dglRasterPos2fv = (glRasterPos2fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2fv"); + dglRasterPos2i = (glRasterPos2i_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2i"); + dglRasterPos2iv = (glRasterPos2iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2iv"); + dglRasterPos2s = (glRasterPos2s_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2s"); + dglRasterPos2sv = (glRasterPos2sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2sv"); + dglRasterPos3d = (glRasterPos3d_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3d"); + dglRasterPos3dv = (glRasterPos3dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3dv"); + dglRasterPos3f = (glRasterPos3f_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3f"); + dglRasterPos3fv = (glRasterPos3fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3fv"); + dglRasterPos3i = (glRasterPos3i_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3i"); + dglRasterPos3iv = (glRasterPos3iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3iv"); + dglRasterPos3s = (glRasterPos3s_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3s"); + dglRasterPos3sv = (glRasterPos3sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3sv"); + dglRasterPos4d = (glRasterPos4d_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4d"); + dglRasterPos4dv = (glRasterPos4dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4dv"); + dglRasterPos4f = (glRasterPos4f_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4f"); + dglRasterPos4fv = (glRasterPos4fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4fv"); + dglRasterPos4i = (glRasterPos4i_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4i"); + dglRasterPos4iv = (glRasterPos4iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4iv"); + dglRasterPos4s = (glRasterPos4s_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4s"); + dglRasterPos4sv = (glRasterPos4sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4sv"); + dglReadBuffer = (glReadBuffer_fp)dll_GetSymbol(OpenGLModuleHandle,"glReadBuffer"); + dglReadPixels = (glReadPixels_fp)dll_GetSymbol(OpenGLModuleHandle,"glReadPixels"); + dglRectd = (glRectd_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectd"); + dglRectdv = (glRectdv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectdv"); + dglRectf = (glRectf_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectf"); + dglRectfv = (glRectfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectfv"); + dglRecti = (glRecti_fp)dll_GetSymbol(OpenGLModuleHandle,"glRecti"); + dglRectiv = (glRectiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectiv"); + dglRects = (glRects_fp)dll_GetSymbol(OpenGLModuleHandle,"glRects"); + dglRectsv = (glRectsv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectsv"); + dglRenderMode = (glRenderMode_fp)dll_GetSymbol(OpenGLModuleHandle,"glRenderMode"); + dglRotated = (glRotated_fp)dll_GetSymbol(OpenGLModuleHandle,"glRotated"); + dglRotatef = (glRotatef_fp)dll_GetSymbol(OpenGLModuleHandle,"glRotatef"); + dglScaled = (glScaled_fp)dll_GetSymbol(OpenGLModuleHandle,"glScaled"); + dglScalef = (glScalef_fp)dll_GetSymbol(OpenGLModuleHandle,"glScalef"); + dglScissor = (glScissor_fp)dll_GetSymbol(OpenGLModuleHandle,"glScissor"); + dglSelectBuffer = (glSelectBuffer_fp)dll_GetSymbol(OpenGLModuleHandle,"glSelectBuffer"); + dglShadeModel = (glShadeModel_fp)dll_GetSymbol(OpenGLModuleHandle,"glShadeModel"); + dglStencilFunc = (glStencilFunc_fp)dll_GetSymbol(OpenGLModuleHandle,"glStencilFunc"); + dglStencilMask = (glStencilMask_fp)dll_GetSymbol(OpenGLModuleHandle,"glStencilMask"); + dglStencilOp = (glStencilOp_fp)dll_GetSymbol(OpenGLModuleHandle,"glStencilOp"); + dglTexCoord1d = (glTexCoord1d_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1d"); + dglTexCoord1dv = (glTexCoord1dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1dv"); + dglTexCoord1f = (glTexCoord1f_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1f"); + dglTexCoord1fv = (glTexCoord1fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1fv"); + dglTexCoord1i = (glTexCoord1i_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1i"); + dglTexCoord1iv = (glTexCoord1iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1iv"); + dglTexCoord1s = (glTexCoord1s_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1s"); + dglTexCoord1sv = (glTexCoord1sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1sv"); + dglTexCoord2d = (glTexCoord2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2d"); + dglTexCoord2dv = (glTexCoord2dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2dv"); + dglTexCoord2f = (glTexCoord2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2f"); + dglTexCoord2fv = (glTexCoord2fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2fv"); + dglTexCoord2i = (glTexCoord2i_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2i"); + dglTexCoord2iv = (glTexCoord2iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2iv"); + dglTexCoord2s = (glTexCoord2s_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2s"); + dglTexCoord2sv = (glTexCoord2sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2sv"); + dglTexCoord3d = (glTexCoord3d_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3d"); + dglTexCoord3dv = (glTexCoord3dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3dv"); + dglTexCoord3f = (glTexCoord3f_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3f"); + dglTexCoord3fv = (glTexCoord3fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3fv"); + dglTexCoord3i = (glTexCoord3i_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3i"); + dglTexCoord3iv = (glTexCoord3iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3iv"); + dglTexCoord3s = (glTexCoord3s_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3s"); + dglTexCoord3sv = (glTexCoord3sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3sv"); + dglTexCoord4d = (glTexCoord4d_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4d"); + dglTexCoord4dv = (glTexCoord4dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4dv"); + dglTexCoord4f = (glTexCoord4f_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4f"); + dglTexCoord4fv = (glTexCoord4fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4fv"); + dglTexCoord4i = (glTexCoord4i_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4i"); + dglTexCoord4iv = (glTexCoord4iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4iv"); + dglTexCoord4s = (glTexCoord4s_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4s"); + dglTexCoord4sv = (glTexCoord4sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4sv"); + dglTexCoordPointer = (glTexCoordPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoordPointer"); + dglTexEnvf = (glTexEnvf_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexEnvf"); + dglTexEnvfv = (glTexEnvfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexEnvfv"); + dglTexEnvi = (glTexEnvi_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexEnvi"); + dglTexEnviv = (glTexEnviv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexEnviv"); + dglTexGend = (glTexGend_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGend"); + dglTexGendv = (glTexGendv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGendv"); + dglTexGenf = (glTexGenf_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGenf"); + dglTexGenfv = (glTexGenfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGenfv"); + dglTexGeni = (glTexGeni_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGeni"); + dglTexGeniv = (glTexGeniv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGeniv"); + dglTexImage1D = (glTexImage1D_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexImage1D"); + dglTexImage2D = (glTexImage2D_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexImage2D"); + dglTexParameterf = (glTexParameterf_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexParameterf"); + dglTexParameterfv = (glTexParameterfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexParameterfv"); + dglTexParameteri = (glTexParameteri_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexParameteri"); + dglTexParameteriv = (glTexParameteriv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexParameteriv"); + dglTexSubImage1D = (glTexSubImage1D_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexSubImage1D"); + dglTexSubImage2D = (glTexSubImage2D_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexSubImage2D"); + dglTranslated = (glTranslated_fp)dll_GetSymbol(OpenGLModuleHandle,"glTranslated"); + dglTranslatef = (glTranslatef_fp)dll_GetSymbol(OpenGLModuleHandle,"glTranslatef"); + dglVertex2d = (glVertex2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2d"); + dglVertex2dv = (glVertex2dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2dv"); + dglVertex2f = (glVertex2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2f"); + dglVertex2fv = (glVertex2fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2fv"); + dglVertex2i = (glVertex2i_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2i"); + dglVertex2iv = (glVertex2iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2iv"); + dglVertex2s = (glVertex2s_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2s"); + dglVertex2sv = (glVertex2sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2sv"); + dglVertex3d = (glVertex3d_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3d"); + dglVertex3dv = (glVertex3dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3dv"); + dglVertex3f = (glVertex3f_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3f"); + dglVertex3fv = (glVertex3fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3fv"); + dglVertex3i = (glVertex3i_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3i"); + dglVertex3iv = (glVertex3iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3iv"); + dglVertex3s = (glVertex3s_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3s"); + dglVertex3sv = (glVertex3sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3sv"); + dglVertex4d = (glVertex4d_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4d"); + dglVertex4dv = (glVertex4dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4dv"); + dglVertex4f = (glVertex4f_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4f"); + dglVertex4fv = (glVertex4fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4fv"); + dglVertex4i = (glVertex4i_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4i"); + dglVertex4iv = (glVertex4iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4iv"); + dglVertex4s = (glVertex4s_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4s"); + dglVertex4sv = (glVertex4sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4sv"); + dglVertexPointer = (glVertexPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertexPointer"); + dglViewport = (glViewport_fp)dll_GetSymbol(OpenGLModuleHandle,"glViewport"); + +#ifdef WIN32 + dwglCopyContext = (wglCopyContext_fp)dll_GetSymbol(OpenGLModuleHandle,"wglCopyContext"); + dwglCreateContext = (wglCreateContext_fp)dll_GetSymbol(OpenGLModuleHandle,"wglCreateContext"); + dwglCreateLayerContext = (wglCreateLayerContext_fp)dll_GetSymbol(OpenGLModuleHandle,"wglCreateLayerContext"); + dwglDeleteContext = (wglDeleteContext_fp)dll_GetSymbol(OpenGLModuleHandle,"wglDeleteContext"); + dwglGetCurrentContext = (wglGetCurrentContext_fp)dll_GetSymbol(OpenGLModuleHandle,"wglGetCurrentContext"); + dwglGetCurrentDC = (wglGetCurrentDC_fp)dll_GetSymbol(OpenGLModuleHandle,"wglGetCurrentDC"); + dwglGetProcAddress = (wglGetProcAddress_fp)dll_GetSymbol(OpenGLModuleHandle,"wglGetProcAddress"); + dwglMakeCurrent = (wglMakeCurrent_fp)dll_GetSymbol(OpenGLModuleHandle,"wglMakeCurrent"); + dwglShareLists = (wglShareLists_fp)dll_GetSymbol(OpenGLModuleHandle,"wglShareLists"); + dwglUseFontBitmapsA = (wglUseFontBitmapsA_fp)dll_GetSymbol(OpenGLModuleHandle,"wglUseFontBitmapsA"); + dwglUseFontBitmapsW = (wglUseFontBitmapsW_fp)dll_GetSymbol(OpenGLModuleHandle,"wglUseFontBitmapsW"); + dwglUseFontOutlinesA = (wglUseFontOutlinesA_fp)dll_GetSymbol(OpenGLModuleHandle,"wglUseFontOutlinesA"); + dwglUseFontOutlinesW = (wglUseFontOutlinesW_fp)dll_GetSymbol(OpenGLModuleHandle,"wglUseFontOutlinesW"); + dwglDescribeLayerPlane = (wglDescribeLayerPlane_fp)dll_GetSymbol(OpenGLModuleHandle,"wglDescribeLayerPlane"); + dwglSetLayerPaletteEntries = (wglSetLayerPaletteEntries_fp)dll_GetSymbol(OpenGLModuleHandle,"wglSetLayerPaletteEntries"); + dwglGetLayerPaletteEntries = (wglGetLayerPaletteEntries_fp)dll_GetSymbol(OpenGLModuleHandle,"wglGetLayerPaletteEntries"); + dwglRealizeLayerPalette = (wglRealizeLayerPalette_fp)dll_GetSymbol(OpenGLModuleHandle,"wglRealizeLayerPalette"); + dwglSwapLayerBuffers = (wglSwapLayerBuffers_fp)dll_GetSymbol(OpenGLModuleHandle,"wglSwapLayerBuffers"); + #if (WINVER >= 0x0500) + dwglSwapMultipleBuffers = (wglSwapMultipleBuffers_fp)dll_GetSymbol(OpenGLModuleHandle,"wglSwapMultipleBuffers"); + #endif +#endif + + } + + return true; +} + +void OpenGL_SetFuncsToNull(void) +{ + dglAccum = NULL; + dglAlphaFunc = NULL; + dglAreTexturesResident = NULL; + dglArrayElement = NULL; + dglBegin = NULL; + dglBindTexture = NULL; + dglBitmap = NULL; + dglBlendFunc = NULL; + dglCallList = NULL; + dglCallLists = NULL; + dglClear = NULL; + dglClearAccum = NULL; + dglClearColor = NULL; + dglClearDepth = NULL; + dglClearIndex = NULL; + dglClearStencil = NULL; + dglClipPlane = NULL; + dglColor3b = NULL; + dglColor3bv = NULL; + dglColor3d = NULL; + dglColor3dv = NULL; + dglColor3f = NULL; + dglColor3fv = NULL; + dglColor3i = NULL; + dglColor3iv = NULL; + dglColor3s = NULL; + dglColor3sv = NULL; + dglColor3ub = NULL; + dglColor3ubv = NULL; + dglColor3ui = NULL; + dglColor3uiv = NULL; + dglColor3us = NULL; + dglColor3usv = NULL; + dglColor4b = NULL; + dglColor4bv = NULL; + dglColor4d = NULL; + dglColor4dv = NULL; + dglColor4f = NULL; + dglColor4fv = NULL; + dglColor4i = NULL; + dglColor4iv = NULL; + dglColor4s = NULL; + dglColor4sv = NULL; + dglColor4ub = NULL; + dglColor4ubv = NULL; + dglColor4ui = NULL; + dglColor4uiv = NULL; + dglColor4us = NULL; + dglColor4usv = NULL; + dglColorMask = NULL; + dglColorMaterial = NULL; + dglColorPointer = NULL; + dglCopyPixels = NULL; + dglCopyTexImage1D = NULL; + dglCopyTexImage2D = NULL; + dglCopyTexSubImage1D = NULL; + dglCopyTexSubImage2D = NULL; + dglCullFace = NULL; + dglDeleteLists = NULL; + dglDeleteTextures = NULL; + dglDepthFunc = NULL; + dglDepthMask = NULL; + dglDepthRange = NULL; + dglDisable = NULL; + dglDisableClientState = NULL; + dglDrawArrays = NULL; + dglDrawBuffer = NULL; + dglDrawElements = NULL; + dglDrawPixels = NULL; + dglEdgeFlag = NULL; + dglEdgeFlagPointer = NULL; + dglEdgeFlagv = NULL; + dglEnable = NULL; + dglEnableClientState = NULL; + dglEnd = NULL; + dglEndList = NULL; + dglEvalCoord1d = NULL; + dglEvalCoord1dv = NULL; + dglEvalCoord1f = NULL; + dglEvalCoord1fv = NULL; + dglEvalCoord2d = NULL; + dglEvalCoord2dv = NULL; + dglEvalCoord2f = NULL; + dglEvalCoord2fv = NULL; + dglEvalMesh1 = NULL; + dglEvalMesh2 = NULL; + dglEvalPoint1 = NULL; + dglEvalPoint2 = NULL; + dglFeedbackBuffer = NULL; + dglFinish = NULL; + dglFlush = NULL; + dglFogf = NULL; + dglFogfv = NULL; + dglFogi = NULL; + dglFogiv = NULL; + dglFrontFace = NULL; + dglFrustum = NULL; + dglGenLists = NULL; + dglGenTextures = NULL; + dglGetBooleanv = NULL; + dglGetClipPlane = NULL; + dglGetDoublev = NULL; + dglGetError = NULL; + dglGetFloatv = NULL; + dglGetIntegerv = NULL; + dglGetLightfv = NULL; + dglGetLightiv = NULL; + dglGetMapdv = NULL; + dglGetMapfv = NULL; + dglGetMapiv = NULL; + dglGetMaterialfv = NULL; + dglGetMaterialiv = NULL; + dglGetPixelMapfv = NULL; + dglGetPixelMapuiv = NULL; + dglGetPixelMapusv = NULL; + dglGetPointerv = NULL; + dglGetPolygonStipple = NULL; + dglGetString = NULL; + dglGetTexEnvfv = NULL; + dglGetTexEnviv = NULL; + dglGetTexGendv = NULL; + dglGetTexGenfv = NULL; + dglGetTexGeniv = NULL; + dglGetTexImage = NULL; + dglGetTexLevelParameterfv = NULL; + dglGetTexLevelParameteriv = NULL; + dglGetTexParameterfv = NULL; + dglGetTexParameteriv = NULL; + dglHint = NULL; + dglIndexMask = NULL; + dglIndexPointer = NULL; + dglIndexd = NULL; + dglIndexdv = NULL; + dglIndexf = NULL; + dglIndexfv = NULL; + dglIndexi = NULL; + dglIndexiv = NULL; + dglIndexs = NULL; + dglIndexsv = NULL; + dglIndexub = NULL; + dglIndexubv = NULL; + dglInitNames = NULL; + dglInterleavedArrays = NULL; + dglIsEnabled = NULL; + dglIsList = NULL; + dglIsTexture = NULL; + dglLightModelf = NULL; + dglLightModelfv = NULL; + dglLightModeli = NULL; + dglLightModeliv = NULL; + dglLightf = NULL; + dglLightfv = NULL; + dglLighti = NULL; + dglLightiv = NULL; + dglLineStipple = NULL; + dglLineWidth = NULL; + dglListBase = NULL; + dglLoadIdentity = NULL; + dglLoadMatrixd = NULL; + dglLoadMatrixf = NULL; + dglLoadName = NULL; + dglLogicOp = NULL; + dglMap1d = NULL; + dglMap1f = NULL; + dglMap2d = NULL; + dglMap2f = NULL; + dglMapGrid1d = NULL; + dglMapGrid1f = NULL; + dglMapGrid2d = NULL; + dglMapGrid2f = NULL; + dglMaterialf = NULL; + dglMaterialfv = NULL; + dglMateriali = NULL; + dglMaterialiv = NULL; + dglMatrixMode = NULL; + dglMultMatrixd = NULL; + dglMultMatrixf = NULL; + dglNewList = NULL; + dglNormal3b = NULL; + dglNormal3bv = NULL; + dglNormal3d = NULL; + dglNormal3dv = NULL; + dglNormal3f = NULL; + dglNormal3fv = NULL; + dglNormal3i = NULL; + dglNormal3iv = NULL; + dglNormal3s = NULL; + dglNormal3sv = NULL; + dglNormalPointer = NULL; + dglOrtho = NULL; + dglPassThrough = NULL; + dglPixelMapfv = NULL; + dglPixelMapuiv = NULL; + dglPixelMapusv = NULL; + dglPixelStoref = NULL; + dglPixelStorei = NULL; + dglPixelTransferf = NULL; + dglPixelTransferi = NULL; + dglPixelZoom = NULL; + dglPointSize = NULL; + dglPolygonMode = NULL; + dglPolygonOffset = NULL; + dglPolygonStipple = NULL; + dglPopAttrib = NULL; + dglPopClientAttrib = NULL; + dglPopMatrix = NULL; + dglPopName = NULL; + dglPrioritizeTextures = NULL; + dglPushAttrib = NULL; + dglPushClientAttrib = NULL; + dglPushMatrix = NULL; + dglPushName = NULL; + dglRasterPos2d = NULL; + dglRasterPos2dv = NULL; + dglRasterPos2f = NULL; + dglRasterPos2fv = NULL; + dglRasterPos2i = NULL; + dglRasterPos2iv = NULL; + dglRasterPos2s = NULL; + dglRasterPos2sv = NULL; + dglRasterPos3d = NULL; + dglRasterPos3dv = NULL; + dglRasterPos3f = NULL; + dglRasterPos3fv = NULL; + dglRasterPos3i = NULL; + dglRasterPos3iv = NULL; + dglRasterPos3s = NULL; + dglRasterPos3sv = NULL; + dglRasterPos4d = NULL; + dglRasterPos4dv = NULL; + dglRasterPos4f = NULL; + dglRasterPos4fv = NULL; + dglRasterPos4i = NULL; + dglRasterPos4iv = NULL; + dglRasterPos4s = NULL; + dglRasterPos4sv = NULL; + dglReadBuffer = NULL; + dglReadPixels = NULL; + dglRectd = NULL; + dglRectdv = NULL; + dglRectf = NULL; + dglRectfv = NULL; + dglRecti = NULL; + dglRectiv = NULL; + dglRects = NULL; + dglRectsv = NULL; + dglRenderMode = NULL; + dglRotated = NULL; + dglRotatef = NULL; + dglScaled = NULL; + dglScalef = NULL; + dglScissor = NULL; + dglSelectBuffer = NULL; + dglShadeModel = NULL; + dglStencilFunc = NULL; + dglStencilMask = NULL; + dglStencilOp = NULL; + dglTexCoord1d = NULL; + dglTexCoord1dv = NULL; + dglTexCoord1f = NULL; + dglTexCoord1fv = NULL; + dglTexCoord1i = NULL; + dglTexCoord1iv = NULL; + dglTexCoord1s = NULL; + dglTexCoord1sv = NULL; + dglTexCoord2d = NULL; + dglTexCoord2dv = NULL; + dglTexCoord2f = NULL; + dglTexCoord2fv = NULL; + dglTexCoord2i = NULL; + dglTexCoord2iv = NULL; + dglTexCoord2s = NULL; + dglTexCoord2sv = NULL; + dglTexCoord3d = NULL; + dglTexCoord3dv = NULL; + dglTexCoord3f = NULL; + dglTexCoord3fv = NULL; + dglTexCoord3i = NULL; + dglTexCoord3iv = NULL; + dglTexCoord3s = NULL; + dglTexCoord3sv = NULL; + dglTexCoord4d = NULL; + dglTexCoord4dv = NULL; + dglTexCoord4f = NULL; + dglTexCoord4fv = NULL; + dglTexCoord4i = NULL; + dglTexCoord4iv = NULL; + dglTexCoord4s = NULL; + dglTexCoord4sv = NULL; + dglTexCoordPointer = NULL; + dglTexEnvf = NULL; + dglTexEnvfv = NULL; + dglTexEnvi = NULL; + dglTexEnviv = NULL; + dglTexGend = NULL; + dglTexGendv = NULL; + dglTexGenf = NULL; + dglTexGenfv = NULL; + dglTexGeni = NULL; + dglTexGeniv = NULL; + dglTexImage1D = NULL; + dglTexImage2D = NULL; + dglTexParameterf = NULL; + dglTexParameterfv = NULL; + dglTexParameteri = NULL; + dglTexParameteriv = NULL; + dglTexSubImage1D = NULL; + dglTexSubImage2D = NULL; + dglTranslated = NULL; + dglTranslatef = NULL; + dglVertex2d = NULL; + dglVertex2dv = NULL; + dglVertex2f = NULL; + dglVertex2fv = NULL; + dglVertex2i = NULL; + dglVertex2iv = NULL; + dglVertex2s = NULL; + dglVertex2sv = NULL; + dglVertex3d = NULL; + dglVertex3dv = NULL; + dglVertex3f = NULL; + dglVertex3fv = NULL; + dglVertex3i = NULL; + dglVertex3iv = NULL; + dglVertex3s = NULL; + dglVertex3sv = NULL; + dglVertex4d = NULL; + dglVertex4dv = NULL; + dglVertex4f = NULL; + dglVertex4fv = NULL; + dglVertex4i = NULL; + dglVertex4iv = NULL; + dglVertex4s = NULL; + dglVertex4sv = NULL; + dglVertexPointer = NULL; + dglViewport = NULL; + +#ifdef WIN32 + dwglCopyContext = NULL; + dwglCreateContext = NULL; + dwglCreateLayerContext = NULL; + dwglDeleteContext = NULL; + dwglGetCurrentContext = NULL; + dwglGetCurrentDC = NULL; + dwglGetProcAddress = NULL; + dwglMakeCurrent = NULL; + dwglShareLists = NULL; + dwglUseFontBitmapsA = NULL; + dwglUseFontBitmapsW = NULL; + dwglUseFontOutlinesA = NULL; + dwglUseFontOutlinesW = NULL; + dwglDescribeLayerPlane = NULL; + dwglSetLayerPaletteEntries = NULL; + dwglGetLayerPaletteEntries = NULL; + dwglRealizeLayerPalette = NULL; + dwglSwapLayerBuffers = NULL; + #if (WINVER >= 0x0500) + dwglSwapMultipleBuffers = NULL; + #endif +#endif + +} +#endif + + +#endif //!__LOADGL_H__ diff --git a/include/lst.bat b/include/lst.bat new file mode 100644 index 00000000..f9ed4f9f --- /dev/null +++ b/include/lst.bat @@ -0,0 +1 @@ +ml /c /W3 /Zd /nologo /Fo.\obj\mactest.obj /Fl mactest.asm diff --git a/include/m.bat b/include/m.bat new file mode 100644 index 00000000..9d6b2cc3 --- /dev/null +++ b/include/m.bat @@ -0,0 +1 @@ +make test diff --git a/include/maths.h b/include/maths.h new file mode 100644 index 00000000..9d641069 --- /dev/null +++ b/include/maths.h @@ -0,0 +1,208 @@ +/* Maths.h library header file */ + +#ifndef _MATHS_H +#define _MATHS_H + +#define NO_FIX_INLINE 1 + +#include +#include "pstypes.h" + + + +#define D_RAND_MAX 32767 + +void d_srand (unsigned int seed); +int d_rand (); // Random number function which returns in the range 0-0x7FFF + + +//=============================== FIXED POINT =============================== + +typedef int32_t fix; //16 bits int, 16 bits frac +typedef int16_t fixang; //angles + +typedef struct quad + { + u_int32_t low; + int32_t high; + } +quad; + + +//Convert an int to a fix +#define i2f(i) ((i)<<16) + +//Get the int part of a fix +#define f2i(f) ((f)>>16) + +//Get the int part of a fix, with rounding +#define f2ir(f) (((f)+f0_5)>>16) + +//Convert fix to float and float to fix +#define f2fl(f) (((float) (f)) / 65536.0) +#define f2db(f) (((double) (f)) / 65536.0) +#define fl2f(f) ((fix) ((f) * 65536)) + +//Some handy constants +#define f0_0 0 +#define f1_0 0x10000 +#define f2_0 0x20000 +#define f3_0 0x30000 +#define f10_0 0xa0000 + +#define f0_5 0x8000 +#define f0_1 0x199a + +#define F0_0 f0_0 +#define F1_0 f1_0 +#define F2_0 f2_0 +#define F3_0 f3_0 +#define F10_0 f10_0 + +#define F0_5 f0_5 +#define F0_1 f0_1 + +//#if defined(NO_FIX_INLINE) || (!defined(__GNUC__) && !defined(__WATCOMC__)) +//multiply two fixes, return a fix +fix fixmul (fix a, fix b); + +//divide two fixes, return a fix +fix fixdiv (fix a, fix b); + +//multiply two fixes, then divide by a third, return a fix +fix fixmuldiv (fix a, fix b, fix c); +#if 0 + +//#else + +//#ifdef __WATCOMC__ +fix fixmul (fix a, fix b); + +#pragma aux fixmul parm [eax] [edx] = \ +"imul edx" \ +"shrd eax,edx,16"; + + + +fix fixdiv (fix a, fix b); + +#pragma aux fixdiv parm [eax] [ebx] modify exact [eax edx] = \ +"mov edx,eax" \ +"sar edx,16" \ +"shl eax,16" \ +"idiv ebx"; + + +fix fixmuldiv (fix a, fix b, fix c); + +#pragma aux fixmuldiv parm [eax] [edx] [ebx] modify exact [eax edx] = \ +"imul edx" \ +"idiv ebx"; + +//#elif defined (__GNUC__) +/* +static inline fix +fixmul (fix a, fix b) +{ + + fix __retval; + + asm (" imul %2;" + " shrd $16,%%edx,%%eax" +: "=a" (__retval): "a" (a), "d" (b):"%edx"); + + return __retval; + +} */ + +//multiply two fixes, return a fix +fix fixmul (fix a, fix b); + + +//divide two fixes, return a fix +fix fixdiv (fix a, fix b); + +//multiply two fixes, then divide by a third, return a fix +fix fixmuldiv (fix a, fix b, fix c); + +//#if 0 +static inline fix +fixdiv (fix a, fix b) +{ + + register fix __retval; + + asm (" mov %%eax,%%edx;" + " sar $16,%%edx;" + " shl $16,%%eax;" + " idiv %%ecx" /* adb: how to make this %0 w/o chance of edx? */ +: "=a" (__retval): "a" (a), "c" (b):"%edx"); + + return __retval; + +} + +static inline fix +fixmuldiv (fix a, fix b, fix c) +{ + + register fix __retval; + + asm (" imul %0;" + " idiv %%ecx" /* adb: how to make this %0 w/o chance of edx? */ +: "=a" (__retval): "a" (a), "r" (b), "c" (c):"%edx"); + + return __retval; + +} +//#endif + +//#endif // __GNUC__ / __WATCOMC__ +//#endif /* defined NO_FIX_INLINE || (!defined __GNUC__ && !defined __WATCOMC__) */ + +#endif + +//multiply two fixes, and add 64-bit product to a quad +void fixmulaccum (quad * q, fix a, fix b); + +//extract a fix from a quad product +fix fixquadadjust (quad * q); + +//divide a quad by a long +int32_t fixdivquadlong (u_int32_t qlow, u_int32_t qhigh, u_int32_t d); + +//negate a quad +void fixquadnegate (quad * q); + +//computes the square root of a long, returning a short +ushort long_sqrt (int32_t a); + +//computes the square root of a quad, returning a long +u_int32_t quad_sqrt (u_int32_t low, int32_t high); +//ulong quad_sqrt (long low, long high); + +//computes the square root of a fix, returning a fix +fix fix_sqrt (fix a); + +//compute sine and cosine of an angle, filling in the variables +//either of the pointers can be NULL +void fix_sincos (fix a, fix * s, fix * c); //with interpolation + +void fix_fastsincos (fix a, fix * s, fix * c); //no interpolation + +//compute inverse sine & cosine +fixang fix_asin (fix v); + +fixang fix_acos (fix v); + +//given cos & sin of an angle, return that angle. +//parms need not be normalized, that is, the ratio of the parms cos/sin must +//equal the ratio of the actual cos & sin for the result angle, but the parms +//need not be the actual cos & sin. +//NOTE: this is different from the standard C atan2, since it is left-handed. +fixang fix_atan2 (fix cos, fix sin); + +//for passed value a, returns 1/sqrt(a) +fix fix_isqrt (fix a); + +#endif diff --git a/include/modex.h b/include/modex.h new file mode 100644 index 00000000..4327e376 --- /dev/null +++ b/include/modex.h @@ -0,0 +1,17 @@ +#ifndef _MODEX_H +#define _MODEX_H +extern int gr_modex_setmode(short mode); +extern void gr_modex_setplane(short plane); +extern void gr_modex_setstart(short x, short y, int wait_for_retrace); +extern void gr_modex_uscanline( short x1, short x2, short y, unsigned char color ); +extern void gr_modex_line(); + +extern int modex_line_vertincr; +extern int modex_line_incr1; +extern int modex_line_incr2; +extern int modex_line_x1; +extern int modex_line_y1; +extern int modex_line_x2; +extern int modex_line_y2; +extern ubyte modex_line_Color; +#endif diff --git a/include/mono.h b/include/mono.h new file mode 100644 index 00000000..33d12d96 --- /dev/null +++ b/include/mono.h @@ -0,0 +1,48 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifndef _MONO_H +#define _MONO_H + +#include +#include "console.h" + +static inline void _do_mprintf(int n, char *fmt, ...) +{ + char buffer[1024]; + va_list arglist; + + va_start (arglist, fmt); + vsprintf (buffer, fmt, arglist); + va_end (arglist); + + con_printf (CON_DEBUG, buffer); +} + +#define mprintf(args) _do_mprintf args + +#define minit() +#define mclose(n) +#define mopen( n, row, col, width, height, title ) +#define mDumpD(window, int_var) +#define mDumpX(window, int_var) +#define mclear( n ) +#define mprintf_at(args) +#define mputc( n, c ) +#define mputc_at( n, row, col, c ) +#define msetcursor( row, col ) +#define mrefresh(n) + +#endif + + diff --git a/include/ogl_init.h b/include/ogl_init.h new file mode 100644 index 00000000..5d7cf37a --- /dev/null +++ b/include/ogl_init.h @@ -0,0 +1,160 @@ +//prototypes opengl functions - Added 9/15/99 Matthew Mueller +#ifndef _OGL_INIT_H_ +#define _OGL_INIT_H_ + +#ifdef __WINDOWS__ +#include +#include +#endif + +//#ifdef __WINDOWS__ +//#define OGL_RUNTIME_LOAD +//#endif + +#ifdef OGL_RUNTIME_LOAD +#include "loadgl.h" +int ogl_init_load_library(void); +#else +#include +#endif + +#ifndef GL_VERSION_1_1 +#ifdef GL_EXT_texture +#define GL_INTENSITY4 GL_INTENSITY4_EXT +#define GL_INTENSITY8 GL_INTENSITY8_EXT +#endif +#endif + + +#include "gr.h" +#include "palette.h" +#include "pstypes.h" + + +#define OGL_TEXTURE_LIST_SIZE 2000 + +typedef struct _ogl_texture { + int handle; + GLint internalformat; + GLenum format; + int w,h,tw,th,lw; + int bytesu; + int bytes; + GLfloat u,v; + GLfloat prio; + int wrapstate; + fix lastrend; + ulong numrend; + char wantmip; +} ogl_texture; + +extern ogl_texture ogl_texture_list[OGL_TEXTURE_LIST_SIZE]; + +extern int ogl_mem_target; +ogl_texture* ogl_get_free_texture(void); +void ogl_init_texture(ogl_texture* t); +void ogl_init_texture_list_internal(void); +void ogl_smash_texture_list_internal(void); +void ogl_vivify_texture_list_internal(void); + +extern int ogl_fullscreen; +void ogl_do_fullscreen_internal(void); + +extern int ogl_voodoohack; + +extern int ogl_alttexmerge;//merge textures by just printing the seperate textures? +extern int ogl_rgba_format; +extern int ogl_intensity4_ok; +extern int ogl_luminance4_alpha4_ok; +extern int ogl_rgba2_ok; +extern int ogl_readpixels_ok; + +extern int gl_initialized; +extern int GL_texmagfilt,GL_texminfilt,GL_needmipmaps; +extern int gl_reticle; + +extern int GL_TEXTURE_2D_enabled; +//extern int GL_texclamp_enabled; +//extern int GL_TEXTURE_ENV_MODE_state,GL_TEXTURE_MAG_FILTER_state,GL_TEXTURE_MIN_FILTER_state; +#define OGL_ENABLE2(a,f) {if (a ## _enabled!=1) {f;a ## _enabled=1;}} +#define OGL_DISABLE2(a,f) {if (a ## _enabled!=0) {f;a ## _enabled=0;}} + +//#define OGL_ENABLE(a) OGL_ENABLE2(a,glEnable(a)) +//#define OGL_DISABLE(a) OGL_DISABLE2(a,glDisable(a)) +#define OGL_ENABLE(a) OGL_ENABLE2(GL_ ## a,glEnable(GL_ ## a)) +#define OGL_DISABLE(a) OGL_DISABLE2(GL_ ## a,glDisable(GL_ ## a)) + +//#define OGL_TEXCLAMP() OGL_ENABLE2(GL_texclamp,glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);) +//#define OGL_TEXREPEAT() OGL_DISABLE2(GL_texclamp,glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);) + +//#define OGL_SETSTATE(a,s,f) {if (a ## _state!=s) {f;a ## _state=s;}} + +//#define OGL_TEXENV(p,m) OGL_SETSTATE(p,m,glTexEnvi(GL_TEXTURE_ENV, p,m)); +//#define OGL_TEXPARAM(p,m) OGL_SETSTATE(p,m,glTexParameteri(GL_TEXTURE_2D,p,m)); + +extern int last_width,last_height; +#define OGL_VIEWPORT(x,y,w,h){if (w!=last_width || h!=last_height){glViewport(x,grd_curscreen->sc_canvas.cv_bitmap.bm_h-y-h,w,h);last_width=w;last_height=h;}} + +//platform specific funcs +//MSVC seems to have problems with inline funcs not being found during linking +#ifndef _MSC_VER +inline +#endif +void ogl_swap_buffers_internal(void); +int ogl_init_window(int x, int y);//create a window/switch modes/etc +void ogl_destroy_window(void);//destroy window/etc +void ogl_init(void);//one time initialization +void ogl_close(void);//one time shutdown + +//generic funcs +#define OGLTEXBUFSIZE (1024*1024*4) +extern GLubyte texbuf[OGLTEXBUFSIZE]; +//void ogl_filltexbuf(unsigned char *data,GLubyte *texp,int width,int height,int twidth,int theight); +void ogl_filltexbuf(unsigned char *data,GLubyte *texp,int truewidth,int width,int height,int dxo,int dyo,int twidth,int theight,int type); +void ogl_loadbmtexture_m(grs_bitmap *bm,int domipmap); +void ogl_loadbmtexture(grs_bitmap *bm); +//void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,int dyo, int *texid,float *u,float *v,char domipmap,float prio); +void ogl_loadtexture(unsigned char * data, int dxo,int dyo, ogl_texture *tex); +void ogl_freetexture(ogl_texture *gltexture); +void ogl_freebmtexture(grs_bitmap *bm); +void ogl_do_palfx(void); +void ogl_start_frame(void); +void ogl_end_frame(void); +void ogl_swap_buffers(void); +void ogl_set_screen_mode(void); +void ogl_cache_level_textures(void); + +void ogl_urect(int left,int top,int right,int bot); +bool ogl_ubitmapm_c(int x, int y,grs_bitmap *bm,int c); +bool ogl_ubitmapm(int x, int y,grs_bitmap *bm); +bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); +bool ogl_ubitblt_tolinear(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); +bool ogl_ubitblt_copy(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); +void ogl_upixelc(int x, int y, int c); +void ogl_ulinec(int left,int top,int right,int bot,int c); + +extern unsigned char *ogl_pal; + +#include "3d.h" +bool g3_draw_tmap_2(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bmbot,grs_bitmap *bm,int orient); + +void ogl_draw_reticle(int cross,int primary,int secondary); + +//whee +//#define PAL2Tr(c) ((gr_palette[c*3]+gr_palette_gamma)/63.0) +//#define PAL2Tg(c) ((gr_palette[c*3+1]+gr_palette_gamma)/63.0) +//#define PAL2Tb(c) ((gr_palette[c*3+2]+gr_palette_gamma)/63.0) +//#define PAL2Tr(c) ((gr_palette[c*3])/63.0) +//#define PAL2Tg(c) ((gr_palette[c*3+1])/63.0) +//#define PAL2Tb(c) ((gr_palette[c*3+2])/63.0) +#define CPAL2Tr(c) ((gr_current_pal[c*3])/63.0) +#define CPAL2Tg(c) ((gr_current_pal[c*3+1])/63.0) +#define CPAL2Tb(c) ((gr_current_pal[c*3+2])/63.0) +#define PAL2Tr(c) ((ogl_pal[c*3])/63.0) +#define PAL2Tg(c) ((ogl_pal[c*3+1])/63.0) +#define PAL2Tb(c) ((ogl_pal[c*3+2])/63.0) +//inline GLfloat PAL2Tr(int c); +//inline GLfloat PAL2Tg(int c); +//inline GLfloat PAL2Tb(int c); + +#endif diff --git a/include/pa_enabl.h b/include/pa_enabl.h new file mode 100644 index 00000000..d34c0d9c --- /dev/null +++ b/include/pa_enabl.h @@ -0,0 +1,35 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#if !defined(PA_ENABL_H) +#define PA_ENABL_H + +//#define POLY_ACC // define this if poly support wanted. + +#if defined(POLY_ACC) + +// uncomment only ONE of the following. +//#define PA_S3_VIRGE +//#define PA_DIAMOND_S3_VIRGE + +#endif + +#ifdef PA_3DFX_VOODOO + #define PA_DFX(x) x + #define NO_DFX(x) +#else + #define PA_DFX(x) + #define NO_DFX(x) x +#endif + +#endif diff --git a/include/palette.h b/include/palette.h new file mode 100644 index 00000000..9af0aa26 --- /dev/null +++ b/include/palette.h @@ -0,0 +1,88 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/include/palette.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:16 $ + * + * Protoypes for palette functions + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:19 donut + * Import of d1x 1.37 source. + * + * Revision 1.11 1994/11/15 17:55:10 john + * Made text palette fade in when game over. + * + * Revision 1.10 1994/11/07 13:53:42 john + * Added better gamma stufff. + * + * Revision 1.9 1994/11/07 13:38:03 john + * Added gamma correction stuff. + * + * Revision 1.8 1994/11/05 13:05:59 john + * Added back in code to allow keys during fade. + * + * Revision 1.7 1994/11/05 12:46:37 john + * Changed palette stuff a bit. + * + * Revision 1.6 1994/09/22 16:08:37 john + * Fixed some palette stuff. + * + * Revision 1.5 1994/08/09 11:27:04 john + * Add cthru stuff. + * + * Revision 1.4 1994/06/09 10:39:33 john + * In fade out.in functions, returned 1 if key was pressed... + * + * Revision 1.3 1994/05/31 19:04:24 john + * Added key to stop fade if desired. + * + * Revision 1.2 1994/05/06 12:50:42 john + * Added supertransparency; neatend things up; took out warnings. + * + * Revision 1.1 1994/05/04 14:59:57 john + * Initial revision + * + * + */ + + + +#ifndef _PALETTE_H +#define _PALETTE_H + +extern void gr_palette_set_gamma( int gamma ); +extern int gr_palette_get_gamma(); +extern ubyte gr_palette_faded_out; +extern void gr_palette_clear(); +extern int gr_palette_fade_out(ubyte *pal, int nsteps, int allow_keys ); +extern int gr_palette_fade_in(ubyte *pal,int nsteps, int allow_keys ); +extern void gr_palette_load( ubyte * pal ); +extern void gr_make_cthru_table(ubyte * table, ubyte r, ubyte g, ubyte b ); +extern int gr_find_closest_color_current( int r, int g, int b ); +extern void gr_palette_read(ubyte * palette); +extern void init_computed_colors(void); + + + +extern ubyte gr_palette_gamma; +extern ubyte gr_current_pal[256*3]; + +#ifdef D1XD3D +typedef ubyte PALETTE [256 * 3]; +extern void DoSetPalette (PALETTE *pPal); +#endif + +#endif diff --git a/include/pcx.h b/include/pcx.h new file mode 100644 index 00000000..4679bc6f --- /dev/null +++ b/include/pcx.h @@ -0,0 +1,72 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/include/pcx.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:16 $ + * + * Routines to read/write pcx images. + * + * $Log: not supported by cvs2svn $ + * Revision 1.2 1999/11/20 10:05:16 donut + * variable size menu patch from Jan Bobrowski. Variable menu font size support and a bunch of fixes for menus that didn't work quite right, by me (MPM). + * + * Revision 1.1.1.1 1999/06/14 22:02:19 donut + * Import of d1x 1.37 source. + * + * Revision 1.4 1995/01/21 17:07:34 john + * Added out of memory error. + * + * Revision 1.3 1994/11/29 02:53:10 john + * Added error messages; made call be more similiar to iff. + * + * Revision 1.2 1994/11/28 20:03:48 john + * Added PCX functions. + * + * Revision 1.1 1994/11/28 19:57:45 john + * Initial revision + * + * + */ + + + +#ifndef _PCX_H +#define _PCX_H + +#define PCX_ERROR_NONE 0 +#define PCX_ERROR_OPENING 1 +#define PCX_ERROR_NO_HEADER 2 +#define PCX_ERROR_WRONG_VERSION 3 +#define PCX_ERROR_READING 4 +#define PCX_ERROR_NO_PALETTE 5 +#define PCX_ERROR_WRITING 6 +#define PCX_ERROR_MEMORY 7 + +// Reads filename into bitmap bmp, and fills in palette. If bmp->bm_data==NULL, +// then bmp->bm_data is allocated and the w,h are filled. +// If palette==NULL the palette isn't read in. Returns error code. + +extern int pcx_read_bitmap( char * filename, grs_bitmap * bmp, int bitmap_type, ubyte * palette ); + +// Writes the bitmap bmp to filename, using palette. Returns error code. + +extern int pcx_write_bitmap( char * filename, grs_bitmap * bmp, ubyte * palette ); + +extern char *pcx_errormsg(int error_number); + +int pcx_read_fullscr(char * filename, ubyte * palette); + +#endif + diff --git a/include/psmacros.inc b/include/psmacros.inc new file mode 100644 index 00000000..0f2ce81e --- /dev/null +++ b/include/psmacros.inc @@ -0,0 +1,330 @@ +; THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +; SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +; END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +; ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +; IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +; SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +; FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +; CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +; AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +; COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +;Shortcuts for casting + +w equ word ptr +b equ byte ptr + + +;The macros @ArgCount() & @ArgRev() are from the file MACROS.INC, provided +;with MASM. I have included them here because MACROS.INC has bugs, so I +;couldn't just include it. + +; Utility Macros - Version 1.0 - for Microsoft Macro Assembler 6.0 +; (C) Copyright Microsoft Corporation, 1987,1988,1989,1990 + +;* @ArgCount - Macro function returns the number of arguments in a +;* VARARG list. +;* +;* Params: arglist - arguments to be counted + +@ArgCount MACRO arglist:VARARG + LOCAL count + count = 0 + FOR arg, + count = count + 1 + ENDM + EXITM %count +ENDM + +;* @ArgRev - Macro function returns a reversed order version of a +;* VARARG list. +;* +;* Shows: Operators - <> ! % +;* String directive - SUBSTR +;* Predefined function - @SizeStr +;* +;* Params: arglist - arguments to be reversed + +@ArgRev MACRO arglist:vararg + LOCAL txt, arg + txt TEXTEQU <> +% FOR arg, + txt CATSTR , , txt + ENDM + + txt SUBSTR txt, 1, @SizeStr( %txt ) - 1 + txt CATSTR , txt, > + EXITM txt +ENDM + +;These macros are used for decalaring external vars and functions + +;this macro is used to declare several symbols of the same type +;usage is: extdef type,sym0,sym1,... +extdef macro type,syms:vararg + for sym, + externdef sym:type + endm + endm + +;this macro is used to generate ext macros +extgen macro type,id +ext&id macro syms:vararg + extdef type,syms + endm + endm + +;macros for common types, such as word (extw), byte (extb), & near (extn) + + extgen word,w + extgen byte,b + extgen dword,d + extgen near,n + + +;compute the absolute value of eax. afterwards, edx=sign (0 or -1) +abs_eax macro + cdq + xor eax,edx + sub eax,edx + endm + +;PUSHM & POPM are used for multiple registers. Note that POPM pops in the +;reverse order from PUSHM, so the list of regs shouls be the same for both. +;You can also define a constant which is a register list, and use it as the +;argument to both macros. + +;push multiple registers +pushm macro args:vararg + local arg + for arg, + push arg + endm + endm + +;pop multiple registers +popm macro args:vararg + local arg +% for arg,@ArgRev(args) + pop arg + endm + endm + +;PUSHLONG pushes a long, zero extending the argument if necessary +;it trashes no registers +pushlong macro arg + local s +s = TYPE arg + if s EQ 0 ;constant, I think + push arg + elseif s LT 4 + push eax + movzx eax,arg + xchg eax,[esp] + else + push arg + endif + + endm + +;PUSHML is pushm using pushlong +pushml macro args:vararg + local arg + for arg, + pushlong arg + endm + endm + + +;DBSTR stores a string with occurances of \n converted to newlines +;this macro expects quotes around the string +; +;note the 'fudge' variable. This fixes an odd problem with the way +;the string macros deal with backslashes - @InStr() treats them like +;any other character, but @SubStr() ignores them +dbstr macro str + local pos,oldpos,len,fudge + + oldpos = 2 ;skip initial quote + fudge = 0 + len = @SizeStr(str) + + pos = @InStr(oldpos,str,<\n>) + + while pos GE oldpos + + if pos GT oldpos + %db '&@SubStr(<&str>,&oldpos-&fudge,&pos-&oldpos)' + endif + db 10 + oldpos = pos+2 + fudge = fudge+1 + + pos = @InStr(oldpos,,<\n>) + + endm + + if oldpos LT len +;;; %db '&@SubStr(&str,&oldpos-&fudge,&len-&oldpos-1)' + %db '&@SubStr(&str,&oldpos-&fudge,&len-&oldpos)' + endif + + endm + + +;MPRINTF is a macro interface to the mprintf funcion. It puts the format +;string in the code segment at the current location, pushes the args, and +;calls mprintf. If window is not specified, zero is assumed +mprintf macro window:=<0>,format:req,args:vararg + local string,skip + ifndef NDEBUG + ifndef NMONO + extn mprintf_ + jmp skip +string label byte + dbstr format + db 0 +skip: + ifnb +% pushml @ArgRev(args) + endif + pushml offset string,window + call mprintf_ + add esp,(@ArgCount(args)+2)*4 ;fix stack + endif + endif + endm + + +;MPRINTF_AT - version of mprintf with coordinates +mprintf_at macro window:=<0>,row,col,format:req,args:vararg + local string,skip + ifndef NDEBUG + ifndef NMONO + extn mprintf_at_ + jmp skip +string label byte + dbstr format + db 0 +skip: + ifnb +% pushml @ArgRev(args) + endif + pushml offset string,col,row,window + call mprintf_at_ + add esp,(@ArgCount(args)+4)*4 ;fix stack + endif + endif + endm + + +;DEBUG calls mprintf with window 0, preserving all registers and flags +;is is conditionall assembled based on the DEBUG_ON flags +debug macro format:req,args:vararg + ifndef NDEBUG + pushf ;save flags + push eax ;mprintf trashes eax + mprintf ,format,args + pop eax + popf + endif + endm + +;DEBUG_AT - version of debug with coordinates +debug_at macro row,col,format:req,args:vararg + ifndef NDEBUG + pushf ;save flags + push eax ;mprintf trashes eax + mprintf_at ,row,col,format,args + pop eax + popf + endif + endm + +;Debugging breakpoint macros + +;print a message, and do an int3 to pop into the debugger +debug_brk macro str + ifndef NDEBUG + debug str + int 3 + endif + endm + +break_if macro cc,str + local skip,yes_break + ifndef NDEBUG + j&cc yes_break + jmp skip +yes_break: debug_brk str +skip: + endif + endm + +;returns the bit number of the highest bit +@HighBit macro n + local t,c + if n EQ 0 + exitm <-1> ;error! + else + t = n + c = 0 + while t GT 1 + t = t SHR 1 + c = c+1 + endm + exitm + endif + endm + +;returns the bit number of the lowest bit +@LowBit macro n + ;local t,c + local c + if n EQ 0 + exitm <-1> ;error! + else + t = n + c = 0 + while (t and 1) EQ 0 + t = t SHR 1 + c = c+1 + endm + exitm + endif + endm + + +;"multiply" the given register by a constant, using whatever method is +;best for the given constant +imulc macro reg,c + local low,high + + if c EQ 0 + xor reg,reg + elseif c EQ 1 + elseif c EQ 3 + lea reg,[reg*2+reg] + elseif c EQ 5 + lea reg,[reg*4+reg] + elseif c EQ 6 + lea reg,[reg*2+reg] ;*3 + shl reg,1 ;*6 + elseif c EQ 9 + lea reg,[reg*8+reg] + elseif c EQ 36 + lea reg,[reg*8+reg] + sal reg,2 + else + low = @LowBit(c) + high = @HighBit(c) + if low EQ high + shl reg,@LowBit(c) + else + imul reg,c + echo Warning: Using imul, to perform multiply by &c + ;; .err + endif + endif + + endm + diff --git a/include/pstypes.h b/include/pstypes.h new file mode 100644 index 00000000..f5494e94 --- /dev/null +++ b/include/pstypes.h @@ -0,0 +1,51 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifndef _TYPES_H +#define _TYPES_H + +// define a dboolean +typedef int dboolean; + +//define a byte +typedef signed char byte; + +//define unsigned types; +typedef unsigned char ubyte; +#ifdef __ENV_LINUX__ +# include +# define _MAX_PATH 1024 +# define _MAX_DIR 256 +#define min(a,b) (((a)>(b))?(b):(a)) +#define max(a,b) (((a)<(b))?(b):(a)) +#else +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; +#endif + +//define a boolean +typedef ubyte bool; + +#ifndef NULL +#define NULL 0 +#endif + +#ifdef __GNUC__ +#define __pack__ __attribute__((packed)) +#else +#define __pack__ +#endif + +#endif + diff --git a/include/pstypes.inc b/include/pstypes.inc new file mode 100644 index 00000000..4e7fd9e7 --- /dev/null +++ b/include/pstypes.inc @@ -0,0 +1,25 @@ +; THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +; SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +; END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +; ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +; IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +; SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +; FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +; CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +; AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +; COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +option expr32 + +IFNDEF types_inc +types_inc EQU 1 + +ubyte typedef byte +ushort typedef word +long typedef dword +uint typedef dword +ulong typedef dword + +bool typedef ubyte + +ENDIF + diff --git a/include/rle.h b/include/rle.h new file mode 100644 index 00000000..3bc9212a --- /dev/null +++ b/include/rle.h @@ -0,0 +1,64 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/include/rle.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:16 $ + * + * Protypes for rle functions. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:19 donut + * Import of d1x 1.37 source. + * + * Revision 1.5 1995/01/14 11:32:20 john + * Added rle_cache_flush function. + * + * Revision 1.4 1994/11/10 13:16:01 matt + * Added includes + * + * Revision 1.3 1994/11/09 19:53:51 john + * Added texture rle caching. + * + * Revision 1.2 1994/11/09 16:35:18 john + * First version with working RLE bitmaps. + * + * Revision 1.1 1994/11/09 12:40:17 john + * Initial revision + * + * + */ + + + +#ifndef _RLE_H +#define _RLE_H + +#include "pstypes.h" +#include "gr.h" + +void gr_rle_decode( ubyte * src, ubyte * dest ); +int gr_rle_encode( int org_size, ubyte *src, ubyte *dest ); +int gr_rle_getsize( int org_size, ubyte *src ); +ubyte * gr_rle_find_xth_pixel( ubyte *src, int x,int * count, ubyte color ); +int gr_bitmap_rle_compress( grs_bitmap * bmp ); +void gr_rle_expand_scanline_masked( ubyte *dest, ubyte *src, int x1, int x2 ); +void gr_rle_expand_scanline( ubyte *dest, ubyte *src, int x1, int x2 ); + +grs_bitmap * rle_expand_texture( grs_bitmap * bmp ); + +void rle_cache_flush(); + +#endif + diff --git a/include/strio.h b/include/strio.h new file mode 100644 index 00000000..d2a662eb --- /dev/null +++ b/include/strio.h @@ -0,0 +1,8 @@ +/* fileio.c in /misc for d1x file reading */ +#ifndef _STRIO_H +#define _STRIO_H + +char *fsplitword(FILE *f, char splitchar); +char *splitword(char *s, char splitchar); + +#endif diff --git a/include/strutil.h b/include/strutil.h new file mode 100644 index 00000000..87a089ba --- /dev/null +++ b/include/strutil.h @@ -0,0 +1,33 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifndef _STRUTILS_ +#define _STRUTILS_ + +char *d_strdup(char *str); + +#ifdef __ENV_LINUX__ +#define stricmp(a,b) strcasecmp(a,b) +#define strnicmp(a,b,c) strncasecmp(a,b,c) +#else +extern int stricmp(char *str1, char *str2); +extern int strnicmp(char *str1, char *str2, int n); +#endif + +void strupr( char *s1 ); +void strlwr( char *s1 ); +void strrev( char *s1 ); + +void _splitpath(char *name, char *drive, char *path, char *base, char *ext); + +#endif diff --git a/include/test.c b/include/test.c new file mode 100644 index 00000000..e95f8755 --- /dev/null +++ b/include/test.c @@ -0,0 +1,15 @@ + +#include "mono.h" + +void macro_test(void); + +main() +{ + minit(); + mclear(0); + + macro_test(); + +} + +ÿ \ No newline at end of file diff --git a/include/test.lnk b/include/test.lnk new file mode 100644 index 00000000..d84706c9 --- /dev/null +++ b/include/test.lnk @@ -0,0 +1,5 @@ +system dos4g option quiet debug all +file .\obj\test.obj, + .\obj\mactest.obj +library c:\project\miner\source\lib\io.lib +name test diff --git a/include/texmap.h b/include/texmap.h new file mode 100644 index 00000000..26f518ee --- /dev/null +++ b/include/texmap.h @@ -0,0 +1,181 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/include/texmap.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:16 $ + * + * Include file for entities using texture mapper library. + * + * $Log: not supported by cvs2svn $ + * Revision 1.2 1999/07/07 21:21:56 donut + * increased recip table size to better accommodate 640 res + * + * Revision 1.1.1.1 1999/06/14 22:02:20 donut + * Import of d1x 1.37 source. + * + * Revision 1.2 1995/09/04 14:22:10 allender + * #defines for fixed point limits on render buffer + * + * Revision 1.1 1995/05/04 20:14:50 allender + * Initial revision + * + * Revision 1.17 1994/11/10 11:09:16 mike + * detail level stuff. + * + * Revision 1.16 1994/11/09 22:55:32 matt + * Added variable Current_seg_depth for detail level optimization + * + * Revision 1.15 1994/06/09 16:10:04 mike + * Add prototype for SC2000 + * + * Revision 1.14 1994/05/25 18:46:16 matt + * Added gr_upoly_tmap_ylr(), which generates ylr's for a polygon + * + * Revision 1.13 1994/05/25 09:47:12 mike + * Added interface support for linear texture mapper (Mike change, Matt commnet) + * + * Revision 1.12 1994/05/24 17:30:43 mike + * Prototype a bunch of linear, vertical scanning functions. + * + * Revision 1.11 1994/05/19 23:26:14 mike + * Add constants NUM_LIGHTING_VALUES, MAX_LIGHTING_VALUE, MIN_LIGHTING_VALUE, + * all part of new lighting_values_in_0_to_1 system. + * + * Revision 1.10 1994/05/14 17:19:21 matt + * Added externs + * + * Revision 1.9 1994/04/13 23:55:44 matt + * Increased max_tmap_verts from 16 to 25 + * + * Revision 1.8 1994/03/31 08:35:43 mike + * Prototype for gr_upoly_tmap. + * + * Revision 1.7 1994/02/08 15:17:54 mike + * define label for MAX_TMAP_VERTS + * + * Revision 1.6 1994/01/31 15:41:51 mike + * Add texture_map_lin_lin_sky_v + * + * Revision 1.5 1994/01/18 10:49:40 mike + * prototype for texture_map_lin_lin_sky + * + * Revision 1.4 1993/11/30 17:09:46 mike + * prototype for compute_lighting_value. + * + * Revision 1.3 1993/11/22 10:50:38 matt + * Add ifndef around body of file + * + * Revision 1.2 1993/10/06 12:41:25 mike + * Change prototype for draw_tmap. + * + * Revision 1.1 1993/09/08 17:29:11 mike + * Initial revision + * + * + */ + +#ifndef _TEXMAP_H +#define _TEXMAP_H + +#include "fix.h" +#include "3d.h" +#include "gr.h" + +#define NUM_LIGHTING_LEVELS 32 +#define MAX_TMAP_VERTS 25 +#define MAX_LIGHTING_VALUE ((NUM_LIGHTING_LEVELS-1)*F1_0/NUM_LIGHTING_LEVELS) +#define MIN_LIGHTING_VALUE (F1_0/NUM_LIGHTING_LEVELS) + +#define FIX_RECIP_TABLE_SIZE 641 //increased from 321 to 641, since this res is now quite achievable.. slight fps boost -MM +// ------------------------------------------------------------------------------------------------------- +extern fix compute_lighting_value(g3s_point *vertptr); + +// ------------------------------------------------------------------------------------------------------- +// This is the main texture mapper call. +// tmap_num references a texture map defined in Texmap_ptrs. +// nverts = number of vertices +// vertbuf is a pointer to an array of vertex pointers +extern void draw_tmap(grs_bitmap *bp, int nverts, g3s_point **vertbuf); + +// ------------------------------------------------------------------------------------------------------- +// Texture map vertex. +// The fields r,g,b and l are mutually exclusive. r,g,b are used for rgb lighting. +// l is used for intensity based lighting. +typedef struct g3ds_vertex { + fix x,y,z; + fix u,v; + fix x2d,y2d; + fix l; + fix r,g,b; +} g3ds_vertex; + +// A texture map is defined as a polygon with u,v coordinates associated with +// one point in the polygon, and a pair of vectors describing the orientation +// of the texture map in the world, from which the deltas Du_dx, Dv_dy, etc. +// are computed. +typedef struct g3ds_tmap { + int nv; // number of vertices + g3ds_vertex verts[MAX_TMAP_VERTS]; // up to 8 vertices, this is inefficient, change +} g3ds_tmap; + +// ------------------------------------------------------------------------------------------------------- + +// Note: Not all interpolation method and lighting combinations are supported. +// Set Interpolation_method to 0/1/2 for linear/linear, perspective/linear, perspective/perspective +extern int Interpolation_method; + +// Set Lighting_on to 0/1/2 for no lighting/intensity lighting/rgb lighting +extern int Lighting_on; + +// HACK INTERFACE: how far away the current segment (& thus texture) is +extern int Current_seg_depth; +extern int Max_perspective_depth; // Deepest segment at which perspective interpolation will be used. +extern int Max_linear_depth; // Deepest segment at which linear interpolation will be used. +extern int Max_flat_depth; // Deepest segment at which flat shading will be used. (If not flat shading, then what?) + +// These are pointers to texture maps. If you want to render texture map #7, then you will render +// the texture map defined by Texmap_ptrs[7]. +extern grs_bitmap Texmap_ptrs[]; +extern grs_bitmap Texmap4_ptrs[]; + +// Interface for sky renderer +extern void texture_map_lin_lin_sky(grs_bitmap *srcb, g3ds_tmap *t); +extern void texture_map_lin_lin_sky_v(grs_bitmap *srcb, g3ds_tmap *t); +extern void texture_map_hyp_lin_v(grs_bitmap *srcb, g3ds_tmap *t); + +extern void ntexture_map_lighted_linear(grs_bitmap *srcb, g3ds_tmap *t); + +// This is the gr_upoly-like interface to the texture mapper which uses texture-mapper compatible +// (ie, avoids cracking) edge/delta computation. +void gr_upoly_tmap(int nverts, int *vert ); + +//This is like gr_upoly_tmap() but instead of drawing, it calls the specified +//function with ylr values +void gr_upoly_tmap_ylr(int nverts, int *vert, void (*ylr_func)(int, fix, fix) ); + +extern int Transparency_on,per2_flag; + +// Set to !0 to enable Sim City 2000 (or Eric's Drive Through, or Eric's Game) specific code. +extern int SC2000; + +extern int Window_clip_left, Window_clip_bot, Window_clip_right, Window_clip_top; + +// for ugly hack put in to be sure we don't overflow render buffer + +#define FIX_XLIMIT (639 * F1_0) +#define FIX_YLIMIT (479 * F1_0) + +#endif + diff --git a/include/timer.h b/include/timer.h new file mode 100644 index 00000000..6d74051a --- /dev/null +++ b/include/timer.h @@ -0,0 +1,127 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/include/timer.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:16 $ + * + * Header for timer functions + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:21 donut + * Import of d1x 1.37 source. + * + * Revision 1.8 1994/12/10 12:27:23 john + * Added timer_get_approx_seconds. + * + * Revision 1.7 1994/12/10 12:10:25 john + * Added types.h. + * + * + * + * + * Revision 1.6 1994/12/10 12:07:06 john + * Added tick counter variable. + * + * Revision 1.5 1994/11/15 12:04:15 john + * Cleaned up timer code a bit... took out unused functions + * like timer_get_milliseconds, etc. + * + * Revision 1.4 1994/04/28 23:50:08 john + * Changed calling for init_timer. Made the function that the + * timer calls be a far function. All of this was done to make + * our timer system compatible with the HMI sound stuff. + * + * Revision 1.3 1994/02/17 15:57:12 john + * Changed key libary to C. + * + * Revision 1.2 1994/01/18 10:58:34 john + * Added timer_get_fixed_seconds + * + * Revision 1.1 1993/07/10 13:10:41 matt + * Initial revision + * + * + */ + + +#ifndef _TIMER_H +#define _TIMER_H + +#include "pstypes.h" +#include "fix.h" + +//========================================================================== +// This installs the timer services and interrupts at the rate specified by +// count_val. If 'function' isn't 0, the function pointed to by function will +// be called 'freq' times per second. Should be > 19 and anything around +// 2-3000 is gonna start slowing down the system. Count_val should be +// 1,193,180 divided by your target frequency. Use 0 for the normal 18.2 Hz +// interrupt rate. + +#define TIMER_FREQUENCY 1193180 +#if !defined (__MSDOS__) || defined(__GNUC__) +#define _far +#define __far +#define __interrupt +#endif + +extern void timer_init(); +extern void timer_close(); +extern void timer_set_rate(int count_val); +extern void timer_set_function( void _far * function ); + +//========================================================================== +// These functions return the time since the timer was initialized in +// some various units. The total length of reading time varies for each +// one. They will roll around after they read 2^32. +// There are milliseconds, milliseconds times 10, milliseconds times 100, +// and microseconds. They time out after 1000 hrs, 100 hrs, 10 hrs, and +// 1 hr, respectively. + +extern fix timer_get_fixed_seconds(); // Rolls about every 9 hours... +#ifdef __MSDOS__ +extern fix timer_get_fixed_secondsX(); // Assume interrupts already disabled +extern fix timer_get_approx_seconds(); // Returns time since program started... accurate to 1/120th of a second +extern void timer_set_joyhandler( void (*joy_handler)() ); +#else +#define timer_get_fixed_secondsX timer_get_fixed_seconds +#define timer_get_approx_seconds timer_get_fixed_seconds +#endif + +//NOT_USED extern unsigned int timer_get_microseconds(); +//NOT_USED extern unsigned int timer_get_milliseconds100(); +//NOT_USED extern unsigned int timer_get_milliseconds10(); +//NOT_USED extern unsigned int timer_get_milliseconds(); +//NOT_USED extern unsigned int timer_get_millisecondsX(); // Assume interrupts disabled + +//========================================================================== +// Use to access the BIOS ticker... ie... i = TICKER +#ifdef __LINUX__ +#define TICKER (timer_get_fixed_seconds()) +#endif + +#ifdef __MSDOS__ + +#ifndef __GNUC__ +#define TICKER (*(volatile int *)0x46C) +#else +#include +#include +#define TICKER _farpeekl(_dos_ds, 0x46c) +#endif +#define USECS_PER_READING( start, stop, frames ) (((stop-start)*54945)/frames) +#endif + +#endif diff --git a/include/u_dpmi.h b/include/u_dpmi.h new file mode 100644 index 00000000..820343be --- /dev/null +++ b/include/u_dpmi.h @@ -0,0 +1,131 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/include/u_dpmi.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:16 $ + * + * Prototypes for DPMI services. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:25 donut + * Import of d1x 1.37 source. + * + * Revision 1.9 1995/01/14 19:20:14 john + * Added function to set a selector's base address. + * + * Revision 1.8 1994/11/28 20:22:03 john + * Added some variables that return the amount of available + * memory. + * + * Revision 1.7 1994/11/15 18:26:38 john + * Added verbose flag. + * + * Revision 1.6 1994/11/07 11:35:05 john + * Added prototype for real_free + * + * Revision 1.5 1994/10/27 19:54:48 john + * Added unlock region function,. + * + * Revision 1.4 1994/09/27 18:27:56 john + * Added pragma to make inp,outp,enable,disable intrinsic + * + * Revision 1.3 1994/09/27 11:54:45 john + * Added DPMI init function. + * + * Revision 1.2 1994/08/24 18:53:51 john + * Made Cyberman read like normal mouse; added dpmi module; moved + * mouse from assembly to c. Made mouse buttons return time_down. + * + * Revision 1.1 1994/08/24 10:22:48 john + * Initial revision + * + * + */ + +#ifndef _DPMI_H +#define _DPMI_H + +#include "pstypes.h" + +typedef struct dpmi_real_regs { + uint edi; + uint esi; + uint ebp; + uint reserved_by_system; + uint ebx; + uint edx; + uint ecx; + uint eax; + ushort flags; + ushort es,ds,fs,gs,ip,cs,sp,ss; +} dpmi_real_regs; + +#ifdef __WATCOMC__ +#pragma intrinsic( inp ); +#pragma intrinsic( outp ); +#pragma intrinsic( _enable ); +#pragma intrinsic( _disable ); +#endif +#ifdef __DJGPP__ +/* inp & outp are functions in DJGPP, while inportb & outportb are inlined */ +#define inp(port) inportb(port) +#define outp(port,value) outportb(port,value) +#if 0 /* only causes problems */ +#undef _enable() +#undef _disable() +#define _enable() __asm__ __volatile__ ("sti") +#define _disable() __asm__ __volatile__ ("cli") +#endif +#endif + +#ifdef __DJGPP__ +#include "sys/nearptr.h" +#define DPMI_real_segment(P) ((((uint)(P)-(uint)(__djgpp_conventional_base)) >> 4) & 0xffff) +#define DPMI_real_offset(P) (((uint)(P)-(uint)(__djgpp_conventional_base)) & 0xf) +#else +#define DPMI_real_segment(P) ((((uint) (P)) >> 4) & 0xFFFF) +#define DPMI_real_offset(P) (((uint) (P)) & 0xF) +#endif + +// Initializes dpmi. Returns zero if failed. +extern int dpmi_init(int verbose); +// Returns a pointer to a temporary dos memory block. Size must be < 1024 bytes. +extern void *dpmi_get_temp_low_buffer( int size ); +extern void *dpmi_real_malloc( int size, ushort *selector ); +extern void dpmi_real_free( ushort selector ); +extern void dpmi_real_int386x( ubyte intno, dpmi_real_regs * rregs ); +extern void dpmi_real_call(dpmi_real_regs * rregs); +extern int dpmi_lock_region(void *address, unsigned length); +extern int dpmi_unlock_region(void *address, unsigned length); +// returns 0 if failed... +extern int dpmi_allocate_selector( void * address, int size, ushort * selector ); +extern int dpmi_modify_selector_base( ushort selector, void * address ); +extern int dpmi_modify_selector_limit( ushort selector, int size ); + + +#ifndef __GNUC__ +// Sets the PM handler. Returns 0 if succssful +extern int dpmi_set_pm_handler(unsigned intnum, void far * isr ); +#else +extern int dpmi_set_pm_handler(unsigned intnum, void * isr ); +#endif + +extern unsigned int dpmi_virtual_memory; +extern unsigned int dpmi_available_memory; +extern unsigned int dpmi_physical_memory; +extern unsigned int dpmi_dos_memory; + +#endif + diff --git a/include/u_mem.h b/include/u_mem.h new file mode 100644 index 00000000..8fe1606c --- /dev/null +++ b/include/u_mem.h @@ -0,0 +1,44 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifdef MACINTOSH +extern ubyte virtual_memory_on; +#endif + +#if !defined(NDEBUG) || defined(MACINTOSH) // mac always gets this stuff. + +extern int show_mem_info; + +void * mem_display_blocks(); +extern void * mem_malloc( unsigned int size, char * var, char * file, int line, int fill_zero ); +extern void mem_free( void * buffer ); + +/* DPH: Changed malloc, etc. to d_malloc. Overloading system calls is very evil and error prone */ +#define d_malloc(size) mem_malloc((size),"Unknown", __FILE__,__LINE__, 0 ) +#define d_calloc(n,size) mem_malloc((n*size),"Unknown", __FILE__,__LINE__, 1 ) +#define d_free(ptr) do{ mem_free(ptr); ptr=NULL; } while(0) + +#define MALLOC( var, type, count ) (var=(type *)mem_malloc((count)*sizeof(type),#var, __FILE__,__LINE__,0 )) + +// Checks to see if any blocks are overwritten +void mem_validate_heap(); + +#else + +#define free(ptr) do{ free(ptr); ptr=NULL; } while(0) + +#define MALLOC( var, type, count ) (var=(type *)malloc((count)*sizeof(type))) + +#endif + + diff --git a/include/vecmat.h b/include/vecmat.h new file mode 100644 index 00000000..4158025a --- /dev/null +++ b/include/vecmat.h @@ -0,0 +1,585 @@ + +/* + THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX + SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO + END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A + ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS + IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS + SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE + FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE + CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS + AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. + COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. + */ +/* + * $Source: /cvs/cvsroot/d2x/include/vecmat.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:30:16 $ + * + * Header file for vector/matrix library + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:28 donut + * Import of d1x 1.37 source. + * + * Revision 1.1 1995/04/17 16:18:05 allender + * Initial revision + * + * + * --- PC RCS Information --- + * Revision 1.37 1995/02/22 13:23:22 john + * Added the vms_vector_array structure, to access a vms_vector + * with an array. + * + * Revision 1.36 1995/02/22 12:34:33 john + * Took out anonymous unions. + * + * Revision 1.35 1994/12/13 14:44:20 matt + * Added vm_vector_2_matrix_norm() + * + * Revision 1.34 1994/09/11 19:22:55 matt + * Added vm_vec_normalized_dir_quick() + * + * Revision 1.33 1994/08/04 19:45:38 matt + * Added option to make a bunch of functions (add, sub, dotprod) inline + * + * Revision 1.32 1994/07/19 18:52:36 matt + * Added vm_vec_normalize_quick() and vm_vec_copy_normalize_quick() + * + * Revision 1.31 1994/06/16 18:24:30 matt + * Added vm_vec_mag_quick() + * + * Revision 1.30 1994/06/10 23:19:00 matt + * New register usage for vm_vec_ang_2_matrix() + * + * Revision 1.29 1994/06/01 17:32:06 matt + * Fixed modify list for vm_vec_normalized_dir() + * + * Revision 1.28 1994/05/19 12:07:20 matt + * Fixed globals and macros and added a constant + * + * Revision 1.27 1994/05/19 09:19:15 matt + * Made vm_vec_normalized_dir() return mag of vector + * + * Revision 1.26 1994/05/18 22:28:57 matt + * Added function vm_vec_normalized_dir() + * Added C macros IS_ZERO_VEC(), vm_vec_zero(), and vm_set_identity() + * Added C global static vars vmd_zero_vector & vmd_identity_matrix + * + * Revision 1.25 1994/05/18 21:45:06 matt + * Added functions: + * vm_extract_angles_vector() + * vm_extract_angles_vector_normalized() + * vm_vec_copy_normalize() + * + * Revision 1.24 1994/05/13 12:42:16 matt + * Added new function, vm_vec_dist_quick(), which does an approximation. + * + * Revision 1.23 1994/03/30 13:37:34 matt + * Added prototype for vm_vec_scale_add(), and fixed typos + * + * Revision 1.22 1994/03/30 13:29:42 matt + * Header for vm_vec_scale_add2() + * + * Revision 1.21 1994/01/31 19:45:13 matt + * Added function vm_extract_angles_matrix() + * + * Revision 1.20 1993/12/21 19:46:14 matt + * Added function vm_dist_to_plane() + * + * Revision 1.19 1993/12/13 17:26:41 matt + * Added vm_vec_dist() + * + * Revision 1.18 1993/12/02 12:45:11 matt + * New functions: vm_vec_copy_scale(), vm_vec_scale2() + * Aliases: vm_transpose(), vm_vec_dot(), vm_vec_cross(), vm_copy_transpose() + * + * Revision 1.17 1993/10/29 22:38:36 matt + * Changed matrix order, making direction vectors the rows + * + * Revision 1.16 1993/10/25 11:49:57 matt + * Made vm_vec_delta_ang() take optional forward vector to return signed delta + * + * Revision 1.15 1993/10/20 01:10:05 matt + * Added vm_vec_delta_ang(), vm_vec_delta_ang_norm(), and vm_vec_ang_2_matrix() + * + * Revision 1.14 1993/10/17 17:02:52 matt + * vm_vector_2_matrix() now takes optional right vector + * + * Revision 1.13 1993/10/12 19:31:39 matt + * Added IDENTITY_MATRIX constant + * + * Revision 1.12 1993/10/08 18:10:16 matt + * Changed vm_vec_make() and vm_angvec_make() to be inline assembly + * functions, to get rid of compiler warnings. Did not change vm_mat_make(), + * which could still get warnings if the return value is unused. + * + * Revision 1.11 1993/09/29 12:10:07 matt + * Changed modified regs in pragmas to include return register + * + * Revision 1.10 1993/09/28 12:15:41 matt + * Added func vm_vector_2_matrix() + * + * Revision 1.9 1993/09/24 21:18:38 matt + * Added vm_vec_avg(), vm_vec_avg4(), and vm_angvec_make(). + * Documented which functions could have dest==source + * + * Revision 1.8 1993/09/20 14:56:11 matt + * Added new function, vm_vec_perp() + * + * Revision 1.7 1993/09/20 14:27:42 mike + * unfix last fix which introduced a bug + * + * Revision 1.6 1993/09/20 10:11:53 mike + * no changes + * + * Revision 1.5 1993/09/20 09:58:58 mike + * Re-fix vm_vec_make + * + * Revision 1.4 1993/09/20 09:41:21 mike + * Correct vm_vec_make and vm_mat_make macros to return the destination + * as the value of the macro. + * + * Revision 1.3 1993/09/17 11:23:47 matt + * Added row access (via xrow,yrow,zrow) to vms_matrix + * Added macro vm_mat_make(), like vm_vec_make() + * + * Revision 1.2 1993/09/17 11:10:32 matt + * Added vm_vec_add2() and vm_vec_sub2(), which take 2 args (dest==src0) + * + * Revision 1.1 1993/09/16 20:10:01 matt + * Initial revision + * + * + */ + +#ifndef _VECMAT_H +#define _VECMAT_H + +#include "maths.h" + +//#define INLINE 1 //are some of these functions inline? + +//The basic fixed-point vector. Access elements by name or position +typedef struct vms_vector + { + + fix x, y, z; + + } +__pack__ vms_vector; + + +typedef struct vms_vector_array + { + + fix xyz[3]; + + } +__pack__ vms_vector_array; + + +//Short vector, used for pre-rotation points. +//Access elements by name or position +typedef struct vms_svec + { + + short sv_x, sv_y, sv_z; + + } +__pack__ vms_svec; + + +//Angle vector. Used to store orientations +typedef struct vms_angvec + { + + fixang p, b, h; + + } +__pack__ vms_angvec; + + +//A 3x3 rotation matrix. Sorry about the numbering starting with one. +//Ordering is across then down, so is the first row +typedef struct vms_matrix + { + + vms_vector rvec, uvec, fvec; + + } +__pack__ vms_matrix; + + +//Macros/functions to fill in fields of structures + +//macro to check if vector is zero +#define IS_VEC_NULL(v) (v->x == 0 && v->y == 0 && v->z == 0) + +//macro to set a vector to zero. we could do this with an in-line assembly +//macro, but it's probably better to let the compiler optimize it. +//Note: NO RETURN VALUE +#define vm_vec_zero(v) (v)->x=(v)->y=(v)->z=0 + +//macro set set a matrix to the identity. Note: NO RETURN VALUE + +// DPH (18/9/98): Begin mod to fix linefeed problem under linux. Uses an +// inline function instead of a multi-line macro to fix CR/LF problems. + +#ifdef __LINUX__ +static inline void vm_set_identity(vms_matrix *m) +{ + m->rvec.x = m->uvec.y = m->fvec.z = f1_0; + m->rvec.y = m->rvec.z = m->uvec.x = m->uvec.z = m->fvec.x = m->fvec.y = 0; +} +#else +#define vm_set_identity(m) do {m->rvec.x = m->uvec.y = m->fvec.z = f1_0; \ + m->rvec.y = m->rvec.z = \ + m->uvec.x = m->uvec.z = \ + m->fvec.x = m->fvec.y = 0;} while (0) +#endif + +// DPH (19/8/98): End changes. + +vms_vector * vm_vec_make (vms_vector * v, fix x, fix y, fix z); + + +#ifdef __WATCOMC__ +#pragma aux vm_vec_make "*_" parm [eax] [edx] [ebx] [ecx] value [eax] modify exact [] = \ +"mov 0[eax],edx" \ +"mov 4[eax],ebx" \ +"mov 8[eax],ecx"; + +#endif + +vms_angvec * vm_angvec_make (vms_angvec * v, fixang p, fixang b, fixang h); + + +#ifdef __WATCOMC__ +#pragma aux vm_angvec_make "*_" parm [eax] [dx] [bx] [cx] value [eax] modify exact [] = \ +"mov 0[eax],dx" \ +"mov 2[eax],bx" \ +"mov 4[eax],cx"; + +#endif + +//Global constants + +extern vms_vector vmd_zero_vector; + +extern vms_matrix vmd_identity_matrix; + + +//Here's a handy constant + +#define ZERO_VECTOR {0,0,0} +#define IDENTITY_MATRIX { {f1_0,0,0}, {0,f1_0,0}, {0,0,f1_0} } + +//#define vm_vec_make(v,_x,_y,_z) (((v)->x=(_x), (v)->y=(_y), (v)->z=(_z)), (v)) + +//#pragma off (unreferenced) +////make this local, so compiler can in-line it +//static vms_vector *vm_vec_make(vms_vector *v,fix x,fix y,fix z) +//{ +// v->x = x; +// v->y = y; +// v->z = z; +// +// return v; +//} +//#pragma on (unreferenced) + + +////macro to fill in elements of a matrix, also for Mike +/* + #define vm_mat_make(m,_m1,_m2,_m3,_m4,_m5,_m6,_m7,_m8,_m9) \ + do { (m)->m1=(_m1); (m)->m2=(_m2); (m)->m3=(_m3); \ + (m)->m4=(_m4); (m)->m5=(_m5); (m)->m6=(_m6); \ + (m)->m7=(_m7); (m)->m8=(_m8); (m)->m9=(_m9);} while (0) + */ + +#if 0 //kill this, since bogus with new matrix ordering + +//macro to fill in elements of a matrix, also for Mike +#define vm_mat_make(m,_m1,_m2,_m3,_m4,_m5,_m6,_m7,_m8,_m9) \ +(((m)->m1 = (_m1), (m)->m2 = (_m2), (m)->m3 = (_m3), \ + (m)->m4 = (_m4), (m)->m5 = (_m5), (m)->m6 = (_m6), \ + (m)->m7 = (_m7), (m)->m8 = (_m8), (m)->m9 = (_m9)), (m)) + +#endif /* + */ + +////fills in fields of an angle vector +//#define vm_angvec_make(v,_p,_b,_h) (((v)->p=(_p), (v)->b=(_b), (v)->h=(_h)), (v)) + +//negate a vector +#define vm_vec_negate(v) do {(v)->x = - (v)->x; (v)->y = - (v)->y; (v)->z = - (v)->z;} while (0); + +//Functions in library + +#ifndef INLINE + +//adds two vectors, fills in dest, returns ptr to dest +//ok for dest to equal either source, but should use vm_vec_add2() if so +vms_vector * vm_vec_add (vms_vector * dest, vms_vector * src0, vms_vector * src1); + + +//subs two vectors, fills in dest, returns ptr to dest +//ok for dest to equal either source, but should use vm_vec_sub2() if so +vms_vector * vm_vec_sub (vms_vector * dest, vms_vector * src0, vms_vector * src1); + + +//adds one vector to another. returns ptr to dest +//dest can equal source +vms_vector * vm_vec_add2 (vms_vector * dest, vms_vector * src); + + +//subs one vector from another, returns ptr to dest +//dest can equal source +vms_vector * vm_vec_sub2 (vms_vector * dest, vms_vector * src); + + +#else /* + */ + +#define vm_vec_add(dest,src0,src1) do { \ +(dest)->x = (src0)->x + (src1)->x; +\ +(dest)->y = (src0)->y + (src1)->y; +\ +(dest)->z = (src0)->z + (src1)->z; +\ +} +while (0); + + +#define vm_vec_sub(dest,src0,src1) do { \ +(dest)->x = (src0)->x - (src1)->x; +\ +(dest)->y = (src0)->y - (src1)->y; +\ +(dest)->z = (src0)->z - (src1)->z; +\ +} +while (0); + + +#define vm_vec_add2(dest,src) do { \ +(dest)->x += (src)->x; +\ +(dest)->y += (src)->y; +\ +(dest)->z += (src)->z; +\ +} +while (0); + + +#define vm_vec_sub2(dest,src) do { \ +(dest)->x -= (src)->x; +\ +(dest)->y -= (src)->y; +\ +(dest)->z -= (src)->z; +\ +} +while (0); + + +#endif /* + */ + +//averages two vectors. returns ptr to dest +//dest can equal either source +vms_vector * vm_vec_avg (vms_vector * dest, vms_vector * src0, vms_vector * src1); + + +//averages four vectors. returns ptr to dest +//dest can equal any source +vms_vector * vm_vec_avg4 (vms_vector * dest, vms_vector * src0, vms_vector * src1, vms_vector * src2, vms_vector * src3); + + +//scales a vector in place. returns ptr to vector +vms_vector * vm_vec_scale (vms_vector * dest, fix s); + + +//scales and copies a vector. returns ptr to dest +vms_vector * vm_vec_copy_scale (vms_vector * dest, vms_vector * src, fix s); + + +//scales a vector, adds it to another, and stores in a 3rd vector +//dest = src1 + k * src2 +vms_vector * vm_vec_scale_add (vms_vector * dest, vms_vector * src1, vms_vector * src2, fix k); + + +//scales a vector and adds it to another +//dest += k * src +vms_vector * vm_vec_scale_add2 (vms_vector * dest, vms_vector * src, fix k); + + +//scales a vector in place, taking n/d for scale. returns ptr to vector +//dest *= n/d +vms_vector * vm_vec_scale2 (vms_vector * dest, fix n, fix d); + + +//returns magnitude of a vector +fix vm_vec_mag (vms_vector * v); + + +//computes the distance between two points. (does sub and mag) +fix vm_vec_dist (vms_vector * v0, vms_vector * v1); + + +//computes an approximation of the magnitude of the vector +//uses dist = largest + next_largest*3/8 + smallest*3/16 +fix vm_vec_mag_quick (vms_vector * v); + + +//computes an approximation of the distance between two points. +//uses dist = largest + next_largest*3/8 + smallest*3/16 +fix vm_vec_dist_quick (vms_vector * v0, vms_vector * v1); + + + +//normalize a vector. returns mag of source vec +fix vm_vec_copy_normalize (vms_vector * dest, vms_vector * src); + +fix vm_vec_normalize (vms_vector * v); + + +//normalize a vector. returns mag of source vec. uses approx mag +fix vm_vec_copy_normalize_quick (vms_vector * dest, vms_vector * src); + +fix vm_vec_normalize_quick (vms_vector * v); + + +//return the normalized direction vector between two points +//dest = normalized(end - start). Returns mag of direction vector +//NOTE: the order of the parameters matches the vector subtraction +fix vm_vec_normalized_dir (vms_vector * dest, vms_vector * end, vms_vector * start); + +fix vm_vec_normalized_dir_quick (vms_vector * dest, vms_vector * end, vms_vector * start); + + +////returns dot product of two vectors +fix vm_vec_dotprod (vms_vector * v0, vms_vector * v1); + +#define vm_vec_dot(v0,v1) vm_vec_dotprod((v0),(v1)) + +#ifdef INLINE +#ifdef __WATCOMC__ +#pragma aux vm_vec_dotprod parm [esi] [edi] value [eax] modify exact [eax ebx ecx edx] = \ +"mov eax,[esi]" \ +"imul dword ptr [edi]" \ +"mov ebx,eax" \ +"mov ecx,edx" \ +\ +"mov eax,4[esi]" \ +"imul dword ptr 4[edi]" \ +"add ebx,eax" \ +"adc ecx,edx" \ +\ +"mov eax,8[esi]" \ +"imul dword ptr 8[edi]" \ +"add eax,ebx" \ +"adc edx,ecx" \ +\ +"shrd eax,edx,16"; + +#endif +#endif /* + */ + +//computes cross product of two vectors. returns ptr to dest +//dest CANNOT equal either source +vms_vector * vm_vec_crossprod (vms_vector * dest, vms_vector * src0, vms_vector * src1); + +#define vm_vec_cross(dest,src0,src1) vm_vec_crossprod((dest),(src0),(src1)) + +//computes surface normal from three points. result is normalized +//returns ptr to dest +//dest CANNOT equal either source +vms_vector * vm_vec_normal (vms_vector * dest, vms_vector * p0, vms_vector * p1, vms_vector * p2); + + +//computes non-normalized surface normal from three points. +//returns ptr to dest +//dest CANNOT equal either source +vms_vector * vm_vec_perp (vms_vector * dest, vms_vector * p0, vms_vector * p1, vms_vector * p2); + + +//computes the delta angle between two vectors. +//vectors need not be normalized. if they are, call vm_vec_delta_ang_norm() +//the forward vector (third parameter) can be NULL, in which case the absolute +//value of the angle in returned. Otherwise the angle around that vector is +//returned. +fixang vm_vec_delta_ang (vms_vector * v0, vms_vector * v1, vms_vector * fvec); + + +//computes the delta angle between two normalized vectors. +fixang vm_vec_delta_ang_norm (vms_vector * v0, vms_vector * v1, vms_vector * fvec); + + +//computes a matrix from a set of three angles. returns ptr to matrix +vms_matrix * vm_angles_2_matrix (vms_matrix * m, vms_angvec * a); + + +//computes a matrix from a forward vector and an angle +vms_matrix * vm_vec_ang_2_matrix (vms_matrix * m, vms_vector * v, fixang a); + + +//computes a matrix from one or more vectors. The forward vector is required, +//with the other two being optional. If both up & right vectors are passed, +//the up vector is used. If only the forward vector is passed, a bank of +//zero is assumed +//returns ptr to matrix +vms_matrix * vm_vector_2_matrix (vms_matrix * m, vms_vector * fvec, vms_vector * uvec, vms_vector * rvec); + + +//this version of vector_2_matrix requires that the vectors be more-or-less +//normalized and close to perpendicular +vms_matrix * vm_vector_2_matrix_norm (vms_matrix * m, vms_vector * fvec, vms_vector * uvec, vms_vector * rvec); + + +//rotates a vector through a matrix. returns ptr to dest vector +//dest CANNOT equal either source +vms_vector * vm_vec_rotate (vms_vector * dest, vms_vector * src, vms_matrix * m); + + +//transpose a matrix in place. returns ptr to matrix +vms_matrix * vm_transpose_matrix (vms_matrix * m); + +#define vm_transpose(m) vm_transpose_matrix(m) + +//copy and transpose a matrix. returns ptr to matrix +//dest CANNOT equal source. use vm_transpose_matrix() if this is the case +vms_matrix * vm_copy_transpose_matrix (vms_matrix * dest, vms_matrix * src); + +#define vm_copy_transpose(dest,src) vm_copy_transpose_matrix((dest),(src)) + +//mulitply 2 matrices, fill in dest. returns ptr to dest +//dest CANNOT equal either source +vms_matrix * vm_matrix_x_matrix (vms_matrix * dest, vms_matrix * src0, vms_matrix * src1); + + +//extract angles from a matrix +vms_angvec * vm_extract_angles_matrix (vms_angvec * a, vms_matrix * m); + + +//extract heading and pitch from a vector, assuming bank==0 +vms_angvec * vm_extract_angles_vector (vms_angvec * a, vms_vector * v); + + +//compute the distance from a point to a plane. takes the normalized normal +//of the plane (ebx), a point on the plane (edi), and the point to check (esi). +//returns distance in eax +//distance is signed, so negative dist is on the back of the plane +fix vm_dist_to_plane (vms_vector * checkp, vms_vector * norm, vms_vector * planep); + + +//fills in fields of an angle vector +#define vm_angvec_make(v,_p,_b,_h) (((v)->p=(_p), (v)->b=(_b), (v)->h=(_h)), (v)) +#endif /* + */ + diff --git a/include/vesa.h b/include/vesa.h new file mode 100644 index 00000000..1fc3356a --- /dev/null +++ b/include/vesa.h @@ -0,0 +1,12 @@ +#ifndef _VESA_H +#define _VESA_H +extern int gr_vesa_setmode(int mode); +extern int gr_vesa_checkmode(int mode); +extern void gr_vesa_setstart(int x, int y ); +extern void gr_vesa_setpage(int page); +extern void gr_vesa_incpage(); +extern int gr_vesa_setlogical(int pixels_per_scanline); +extern void gr_vesa_scanline(int x1, int x2, int y, unsigned char color ); +extern void gr_vesa_bitblt( unsigned char * source_ptr, unsigned int vesa_address, int height, int width ); +extern void gr_vesa_pixel( unsigned char color, unsigned int offset ); +#endif diff --git a/input/Makefile.am b/input/Makefile.am new file mode 100644 index 00000000..5551342b --- /dev/null +++ b/input/Makefile.am @@ -0,0 +1,17 @@ +SUBDIRS = linux +if USE_OPENGL + SUBDIRS += ggi +else + SUBDIRS += sdl +endif + +noinst_LIBRARIES = libinput.a + +libinput_a_SOURCES = + +if USE_OPENGL +libinput_a_LIBADD = ggi/event.o ggi/key.o ggi/mouse.o linux/joydefs.o linux/joystick.o +else +libinput_a_LIBADD = sdl/event.o sdl/key.o sdl/mouse.o linux/joydefs.o linux/joystick.o +endif + diff --git a/input/Makefile.in b/input/Makefile.in new file mode 100644 index 00000000..be8ee9de --- /dev/null +++ b/input/Makefile.in @@ -0,0 +1,344 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +CFLAGS = @CFLAGS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +NASM = @NASM@ +NASMFLAGS = @NASMFLAGS@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_LIBS = @SDL_LIBS@ +VERSION = @VERSION@ + +SUBDIRS = linux + +noinst_LIBRARIES = libinput.a + +libinput_a_SOURCES = +@USE_OPENGL_TRUE@libinput_a_LIBADD = ggi/event.o ggi/key.o ggi/mouse.o linux/joydefs.o linux/joystick.o +@USE_OPENGL_FALSE@libinput_a_LIBADD = sdl/event.o sdl/key.o sdl/mouse.o linux/joydefs.o linux/joystick.o +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../conf.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +@USE_OPENGL_TRUE@libinput_a_DEPENDENCIES = ggi/event.o ggi/key.o \ +@USE_OPENGL_TRUE@ggi/mouse.o linux/joydefs.o linux/joystick.o +@USE_OPENGL_FALSE@libinput_a_DEPENDENCIES = sdl/event.o sdl/key.o \ +@USE_OPENGL_FALSE@sdl/mouse.o linux/joydefs.o linux/joystick.o +libinput_a_OBJECTS = +AR = ar +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +SOURCES = $(libinput_a_SOURCES) +OBJECTS = $(libinput_a_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu input/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +libinput.a: $(libinput_a_OBJECTS) $(libinput_a_DEPENDENCIES) + -rm -f libinput.a + $(AR) cru libinput.a $(libinput_a_OBJECTS) $(libinput_a_LIBADD) + $(RANLIB) libinput.a + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + +@SET_MAKE@ + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + test "$$subdir" = "." && dot_seen=yes; \ + done; \ + test "$$dot_seen" = "no" && rev=". $$rev"; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = input + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu input/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + fi; \ + done +info-am: +info: info-recursive +dvi-am: +dvi: dvi-recursive +check-am: all-am +check: check-recursive +installcheck-am: +installcheck: installcheck-recursive +install-exec-am: +install-exec: install-exec-recursive + +install-data-am: +install-data: install-data-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-recursive +uninstall-am: +uninstall: uninstall-recursive +all-am: Makefile $(LIBRARIES) +all-redirect: all-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: installdirs-recursive +installdirs-am: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ + mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-recursive + +clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \ + mostlyclean-am + +clean: clean-recursive + +distclean-am: distclean-noinstLIBRARIES distclean-compile \ + distclean-tags distclean-generic clean-am + +distclean: distclean-recursive + +maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-recursive + +.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile install-data-recursive \ +uninstall-data-recursive install-exec-recursive \ +uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \ +all-recursive check-recursive installcheck-recursive info-recursive \ +dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs-am \ +installdirs mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + +@USE_OPENGL_TRUE@ SUBDIRS += ggi +@USE_OPENGL_FALSE@ SUBDIRS += sdl + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/input/ggi/Makefile.am b/input/ggi/Makefile.am new file mode 100644 index 00000000..cce89685 --- /dev/null +++ b/input/ggi/Makefile.am @@ -0,0 +1,5 @@ +noinst_LIBRARIES = libinputggi.a +INCLUDES = -I$(top_srcdir)/includes -I$(top_srcdir)/main -Iinclude + +libinputggi_a_SOURCES = \ +event.c key.c mouse.c diff --git a/input/ggi/Makefile.in b/input/ggi/Makefile.in new file mode 100644 index 00000000..6af61789 --- /dev/null +++ b/input/ggi/Makefile.in @@ -0,0 +1,300 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +CFLAGS = @CFLAGS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +NASM = @NASM@ +NASMFLAGS = @NASMFLAGS@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_LIBS = @SDL_LIBS@ +VERSION = @VERSION@ + +noinst_LIBRARIES = libinputggi.a +INCLUDES = -I$(top_srcdir)/includes -I$(top_srcdir)/main -Iinclude + +libinputggi_a_SOURCES = event.c key.c mouse.c + +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../../conf.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I../.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +libinputggi_a_LIBADD = +libinputggi_a_OBJECTS = event.o key.o mouse.o +AR = ar +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +DEP_FILES = .deps/event.P .deps/key.P .deps/mouse.P +SOURCES = $(libinputggi_a_SOURCES) +OBJECTS = $(libinputggi_a_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu input/ggi/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +libinputggi.a: $(libinputggi_a_OBJECTS) $(libinputggi_a_DEPENDENCIES) + -rm -f libinputggi.a + $(AR) cru libinputggi.a $(libinputggi_a_OBJECTS) $(libinputggi_a_LIBADD) + $(RANLIB) libinputggi.a + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = input/ggi + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu input/ggi/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile $(LIBRARIES) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ + mostlyclean-tags mostlyclean-depend mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \ + clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-noinstLIBRARIES distclean-compile \ + distclean-tags distclean-depend distclean-generic \ + clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/input/ggi/event.c b/input/ggi/event.c new file mode 100644 index 00000000..3ba2697c --- /dev/null +++ b/input/ggi/event.c @@ -0,0 +1,127 @@ +#include +#include +#include +#include +#include +#include "event.h" +#include "error.h" +#include "fix.h" + +static int initialised=0; + +#ifdef GGI_VIDEO +#include +extern ggi_visual_t *screenvis; +#endif +gii_input_t inputs; + +extern void keyboard_handler(int key, ubyte state); +extern void mouse_handler_button(int button, ubyte state); +extern void mouse_handler_relative(int x, int y); +extern void mouse_handler_absolute(int x, int y); + +void event_poll() +{ + int n; + struct timeval tv; + gii_event event; + + if (!initialised) + event_init(); + if (inputs==NULL) + return; +// Error("GII error: no inputs (perhaps you need to set GII_INPUT env var)\n"); + + tv.tv_sec = 0; + tv.tv_usec = 0; + + giiEventPoll(inputs, emAll, &tv); + + n = giiEventsQueued(inputs, emAll); + + while (n-- > 0) + { + giiEventRead(inputs, &event, emAll); + switch (event.any.type) + { + case evKeyPress: + keyboard_handler(event.key.label, 1); + break; + case evKeyRelease: + keyboard_handler(event.key.label, 0); + break; + case evPtrAbsolute: + mouse_handler_absolute(event.pmove.x, event.pmove.y); + break; + case evPtrRelative: + mouse_handler_relative(event.pmove.x, event.pmove.y); + break; + case evPtrButtonPress: + mouse_handler_button(event.pbutton.button, 1); + break; + case evPtrButtonRelease: + mouse_handler_button(event.pbutton.button, 0); + break; + } + } +} + +void event_close() +{ + if (inputs) + giiClose(inputs); + giiExit(); +} + +#ifdef GII_XWIN +int gii_xwin_initialized=0; +#include +//void lock_nothing(void){return;} +void init_gii_xwin(Display *disp,Window win){ + printf("gii xwin %i %i\n",initialised,gii_xwin_initialized); + if (!initialised) + event_init(); + if (gii_xwin_initialized){ + gii_event ev; + gii_xwin_cmddata_setparam *giiargs=(gii_xwin_cmddata_setparam *) &ev.cmd.data; + memset(&ev,0,sizeof(gii_cmd_nodata_event)+sizeof(gii_xwin_cmddata_setparam)); + ev.cmd.code=GII_CMDCODE_XWINSETPARAM; + ev.any.type = evCommand; + ev.any.size=sizeof(gii_cmd_nodata_event)+sizeof(gii_xwin_cmddata_setparam); + giiargs->win=win; + giiargs->ptralwaysrel=1; + giiEventSend(inputs,&ev); + }else{ + gii_input_t inputs2; + gii_inputxwin_arg giiargs; + memset(&giiargs,0,sizeof(giiargs)); + giiargs.disp=disp; + giiargs.win=win; + giiargs.ptralwaysrel=1; + //giiargs.gglock=lock_nothing; + inputs2=giiOpen("xwin",&giiargs,NULL); + if (inputs2){ + gii_xwin_initialized=1; + if (inputs) + inputs=giiJoinInputs(inputs,inputs2); + else + inputs=inputs2; + } + } +} +#endif + +int event_init() +{ + if (!initialised){ + giiInit(); +#ifdef GGI_VIDEO + inputs = ggiJoinInputs(screenvis, NULL); +#else + inputs=giiOpen(NULL); +#endif + initialised = 1; + atexit(event_close); + } + return 0; +} diff --git a/input/ggi/include/event.h b/input/ggi/include/event.h new file mode 100644 index 00000000..35bfd62f --- /dev/null +++ b/input/ggi/include/event.h @@ -0,0 +1,14 @@ +// Event header file + +#ifndef _EVENT_H +#define _EVENT_H + +int event_init(); +void event_poll(); + +#ifdef GII_XWIN +#include +void init_gii_xwin(Display *disp,Window win); +#endif + +#endif diff --git a/input/ggi/include/key.h b/input/ggi/include/key.h new file mode 100644 index 00000000..82545713 --- /dev/null +++ b/input/ggi/include/key.h @@ -0,0 +1,273 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/input/ggi/include/key.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:29:59 $ + * + * Header for keyboard functions + * + * $Log: not supported by cvs2svn $ + * Revision 1.2 1999/07/10 02:59:06 donut + * more from orulz + * + * Revision 1.19 1994/10/24 13:58:12 john + * Hacked in support for pause key onto code 0x61. + * + * Revision 1.18 1994/10/21 15:17:10 john + * Added KEY_PRINT_SCREEN + * + * Revision 1.17 1994/08/31 12:22:13 john + * Added KEY_DEBUGGED + * + * Revision 1.16 1994/08/24 18:53:50 john + * Made Cyberman read like normal mouse; added dpmi module; moved + * mouse from assembly to c. Made mouse buttons return time_down. + * + * Revision 1.15 1994/08/18 14:56:16 john + * *** empty log message *** + * + * Revision 1.14 1994/08/08 10:43:24 john + * Recorded when a key was pressed for key_inkey_time. + * + * Revision 1.13 1994/06/17 17:17:28 john + * Added keyd_time_last_key_was_pressed or something like that. + * + * Revision 1.12 1994/04/29 12:14:19 john + * Locked all memory used during interrupts so that program + * won't hang when using virtual memory. + * + * Revision 1.11 1994/02/17 15:57:14 john + * Changed key libary to C. + * + * Revision 1.10 1994/01/31 08:34:09 john + * Fixed reversed lshift/rshift keys. + * + * Revision 1.9 1994/01/18 10:58:17 john + * *** empty log message *** + * + * Revision 1.8 1993/10/16 19:24:43 matt + * Added new function key_clear_times() & key_clear_counts() + * + * Revision 1.7 1993/10/15 10:17:09 john + * added keyd_last_key_pressed and released for use with recorder. + * + * Revision 1.6 1993/10/06 16:20:37 john + * fixed down arrow bug + * + * Revision 1.5 1993/10/04 13:26:42 john + * changed the #defines for scan codes. + * + * Revision 1.4 1993/09/28 11:35:20 john + * added key_peekkey + * + * Revision 1.3 1993/09/20 18:36:43 john + * *** empty log message *** + * + * Revision 1.1 1993/07/10 13:10:39 matt + * Initial revision + * + * + */ + +#ifndef _KEY_H +#define _KEY_H + +#include "fix.h" +#include "pstypes.h" +#include // For 'toupper' + +extern int giiKeyTranslate (int keylabel); + +//========================================================================== +// This installs the int9 vector and initializes the keyboard in buffered +// ASCII mode. key_close simply undoes that. +extern void key_init(); +extern void key_close(); + +//========================================================================== +// These are configuration parameters to setup how the buffer works. +// set keyd_buffer_type to 0 for no key buffering. +// set it to 1 and it will buffer scancodes. +extern unsigned char keyd_buffer_type; +extern unsigned char keyd_repeat; // 1=allow repeating, 0=dont allow repeat + +// keyd_editor_mode... 0=game mode, 1=editor mode. +// Editor mode makes key_down_time always return 0 if modifiers are down. +extern unsigned char keyd_editor_mode; + +// Time in seconds when last key was pressed... +extern volatile int keyd_time_when_last_pressed; + +//========================================================================== +// These are the "buffered" keypress routines. Use them by setting the +// "keyd_buffer_type" variable. + +extern void key_flush(); // Clears the 256 char buffer +extern int key_checkch(); // Returns 1 if a char is waiting +extern int key_getch(); // Gets key if one waiting other waits for one. +extern int key_inkey(); // Gets key if one, other returns 0. +extern int key_inkey_time(fix *time); // Same as inkey, but returns the time the key was pressed down. +extern int key_peekkey(); // Same as inkey, but doesn't remove key from buffer. + +extern unsigned char key_to_ascii(int keycode ); +extern char *key_name(int keycode); // Convert keycode to the name of the key + +extern void key_debug(); // Does an INT3 + +//========================================================================== +// These are the unbuffered routines. Index by the keyboard scancode. + +// Set to 1 if the key is currently down, else 0 +extern volatile unsigned char keyd_pressed[]; +extern volatile unsigned char keyd_last_pressed; +extern volatile unsigned char keyd_last_released; + +// Returns the seconds this key has been down since last call. +extern fix key_down_time(int scancode); + +// Returns number of times key has went from up to down since last call. +extern unsigned int key_down_count(int scancode); + +// Returns number of times key has went from down to up since last call. +extern unsigned int key_up_count(int scancode); + +// Clears the times & counts used by the above functions +// Took out... use key_flush(); +//void key_clear_times(); +//void key_clear_counts(); + +extern char * key_text[256]; + +#define KEY_SHIFTED 0x100 +#define KEY_ALTED 0x200 +#define KEY_CTRLED 0x400 +#define KEY_DEBUGGED 0x800 + +#define KEY_0 0x0B +#define KEY_1 0x02 +#define KEY_2 0x03 +#define KEY_3 0x04 +#define KEY_4 0x05 +#define KEY_5 0x06 +#define KEY_6 0x07 +#define KEY_7 0x08 +#define KEY_8 0x09 +#define KEY_9 0x0A + +#define KEY_A 0x1E +#define KEY_B 0x30 +#define KEY_C 0x2E +#define KEY_D 0x20 +#define KEY_E 0x12 +#define KEY_F 0x21 +#define KEY_G 0x22 +#define KEY_H 0x23 +#define KEY_I 0x17 +#define KEY_J 0x24 +#define KEY_K 0x25 +#define KEY_L 0x26 +#define KEY_M 0x32 +#define KEY_N 0x31 +#define KEY_O 0x18 +#define KEY_P 0x19 +#define KEY_Q 0x10 +#define KEY_R 0x13 +#define KEY_S 0x1F +#define KEY_T 0x14 +#define KEY_U 0x16 +#define KEY_V 0x2F +#define KEY_W 0x11 +#define KEY_X 0x2D +#define KEY_Y 0x15 +#define KEY_Z 0x2C + +#define KEY_MINUS 0x0C +#define KEY_EQUAL 0x0D +#define KEY_DIVIDE 0x35 +#define KEY_SLASH 0x2B +#define KEY_COMMA 0x33 +#define KEY_PERIOD 0x34 +#define KEY_SEMICOL 0x27 + +#define KEY_LBRACKET 0x1A +#define KEY_RBRACKET 0x1B + +#define KEY_RAPOSTRO 0x28 +#define KEY_LAPOSTRO 0x29 + +#define KEY_ESC 0x01 +#define KEY_ENTER 0x1C +#define KEY_BACKSP 0x0E +#define KEY_TAB 0x0F +#define KEY_SPACEBAR 0x39 + +#define KEY_NUMLOCK 0x45 +#define KEY_SCROLLOCK 0x46 +#define KEY_CAPSLOCK 0x3A + +#define KEY_LSHIFT 0x2A +#define KEY_RSHIFT 0x36 + +#define KEY_LALT 0x38 +#define KEY_RALT 0xB8 + +#define KEY_LCTRL 0x1D +#define KEY_RCTRL 0x9D + +#define KEY_F1 0x3B +#define KEY_F2 0x3C +#define KEY_F3 0x3D +#define KEY_F4 0x3E +#define KEY_F5 0x3F +#define KEY_F6 0x40 +#define KEY_F7 0x41 +#define KEY_F8 0x42 +#define KEY_F9 0x43 +#define KEY_F10 0x44 +#define KEY_F11 0x57 +#define KEY_F12 0x58 + +#define KEY_PAD0 0x52 +#define KEY_PAD1 0x4F +#define KEY_PAD2 0x50 +#define KEY_PAD3 0x51 +#define KEY_PAD4 0x4B +#define KEY_PAD5 0x4C +#define KEY_PAD6 0x4D +#define KEY_PAD7 0x47 +#define KEY_PAD8 0x48 +#define KEY_PAD9 0x49 +#define KEY_PADMINUS 0x4A +#define KEY_PADPLUS 0x4E +#define KEY_PADPERIOD 0x53 +#define KEY_PADDIVIDE 0xB5 +#define KEY_PADMULTIPLY 0x37 +#define KEY_PADENTER 0x9C + +#define KEY_INSERT 0xD2 +#define KEY_HOME 0xC7 +#define KEY_PAGEUP 0xC9 +#define KEY_DELETE 0xD3 +#define KEY_END 0xCF +#define KEY_PAGEDOWN 0xD1 +#define KEY_UP 0xC8 +#define KEY_DOWN 0xD0 +#define KEY_LEFT 0xCB +#define KEY_RIGHT 0xCD + +#define KEY_PRINT_SCREEN 0xB7 +#define KEY_PAUSE 0x61 + +#endif diff --git a/input/ggi/include/mouse.h b/input/ggi/include/mouse.h new file mode 100644 index 00000000..6f44c665 --- /dev/null +++ b/input/ggi/include/mouse.h @@ -0,0 +1,127 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/input/ggi/include/mouse.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:29:59 $ + * + * Header for mouse functions + * + * $Log: not supported by cvs2svn $ + * Revision 1.1 1999/06/15 05:38:08 donut + * Orulz' ggi patches. + * + * Revision 1.10 1995/02/02 10:22:29 john + * Added cyberman init parameter. + * + * Revision 1.9 1994/11/18 23:18:09 john + * Changed some shorts to ints. + * + * Revision 1.8 1994/09/13 12:33:49 john + * Added functions to get down count and state. + * + * Revision 1.7 1994/08/29 20:52:20 john + * Added better cyberman support; also, joystick calibration + * value return funcctiionn, + * + * Revision 1.6 1994/08/24 17:54:35 john + * *** empty log message *** + * + * Revision 1.5 1994/08/24 17:51:43 john + * Added transparent cyberman support + * + * Revision 1.4 1993/07/27 09:32:22 john + * *** empty log message *** + * + * Revision 1.3 1993/07/26 10:46:44 john + * added definition for mouse_set_pos + * + * Revision 1.2 1993/07/22 13:07:59 john + * added header for mousesetlimts + * + * Revision 1.1 1993/07/10 13:10:40 matt + * Initial revision + * + * + */ + +#ifndef MOUSE_H +#define MOUSE_H + +#include "pstypes.h" +#include "fix.h" + +#define MOUSE_MAX_BUTTONS 3 + +#define MB_LEFT 0 +#define MB_RIGHT 1 +#define MB_MIDDLE 2 +#define MB_Z_UP 3 +#define MB_Z_DOWN 4 +#define MB_PITCH_BACKWARD 5 +#define MB_PITCH_FORWARD 6 +#define MB_BANK_LEFT 7 +#define MB_BANK_RIGHT 8 +#define MB_HEAD_LEFT 9 +#define MB_HEAD_RIGHT 10 + +#define MOUSE_LBTN 1 +#define MOUSE_RBTN 2 +#define MOUSE_MBTN 4 + +#undef NOMOUSE +#ifndef NOMOUSE + +//======================================================================== +// Check for mouse driver, reset driver if installed. returns number of +// buttons if driver is present. + +extern int mouse_set_limits( int x1, int y1, int x2, int y2 ); +extern void mouse_flush(); // clears all mice events... + +//======================================================================== +extern void mouse_get_pos( int *x, int *y); +extern void mouse_get_delta( int *dx, int *dy ); +extern int mouse_get_btns(); +extern void mouse_set_pos( int x, int y); +extern void mouse_get_cyberman_pos( int *x, int *y ); + +// Returns how long this button has been down since last call. +extern fix mouse_button_down_time(int button); + +// Returns how many times this button has went down since last call. +extern int mouse_button_down_count(int button); + +// Returns 1 if this button is currently down +extern int mouse_button_state(int button); + +#else +// 'Neutered' functions... :-) +#define mouse_init(a) -1 +#define mouse_set_limits(a,b,c,d) -1 +#define mouse_flush() +#define mouse_close() +#define mouse_get_pos(a,b) +#define mouse_get_delta(a,b) +#define mouse_get_btns() 0 +#define mouse_set_pos(a,b) +#define mouse_get_cyberman_pos(a,b) +#define mouse_button_down_time(a) 0 +#define mouse_button_down_count(a) 0 +#define mouse_button_state(a) 0 + +#endif + +#endif + diff --git a/input/ggi/init.c b/input/ggi/init.c new file mode 100644 index 00000000..80ccebc5 --- /dev/null +++ b/input/ggi/init.c @@ -0,0 +1,11 @@ +#include +#include +#include +#include "text.h" +#include "event.h" +#include "error.h" +#include "args.h" + +void arch_ggi_init() +{ +} diff --git a/input/ggi/key.c b/input/ggi/key.c new file mode 100644 index 00000000..8d4cb074 --- /dev/null +++ b/input/ggi/key.c @@ -0,0 +1,495 @@ +#include +#include +#include + +#include + +#include "event.h" +#include "error.h" +#include "key.h" +#include "timer.h" +#include "mono.h" + +//added on 9/3/98 by Matt Mueller to free some cpu instead of hogging during menus and such +#include "d_delay.h" +//end this section addition - Matt Mueller + +#define KEY_BUFFER_SIZE 16 + +static unsigned char Installed = 0; + +//-------- Variable accessed by outside functions --------- +unsigned char keyd_buffer_type; // 0=No buffer, 1=buffer ASCII, 2=buffer scans +unsigned char keyd_repeat; +unsigned char keyd_editor_mode; +volatile unsigned char keyd_last_pressed; +volatile unsigned char keyd_last_released; +volatile unsigned char keyd_pressed[256]; +volatile int keyd_time_when_last_pressed; + +typedef struct Key_info { + ubyte state; // state of key 1 == down, 0 == up + ubyte last_state; // previous state of key + int counter; // incremented each time key is down in handler + fix timewentdown; // simple counter incremented each time in interrupt and key is down + fix timehelddown; // counter to tell how long key is down -- gets reset to 0 by key routines + ubyte downcount; // number of key counts key was down + ubyte upcount; // number of times key was released +} Key_info; + +typedef struct keyboard { + unsigned short keybuffer[KEY_BUFFER_SIZE]; + Key_info keys[256]; + fix time_pressed[KEY_BUFFER_SIZE]; + unsigned int keyhead, keytail; +} keyboard; + +static /*volatile*/ keyboard key_data; + +char * key_text[256] = { +"","ESC","1","2","3","4","5","6","7","8","9","0","-", +"=","BSPC","TAB","Q","W","E","R","T","Y","U","I","O", +"P","[","]","ƒ","LCTRL","A","S","D","F", +"G","H","J","K","L",";","'","`", +"LSHFT","\\","Z","X","C","V","B","N","M",",", +".","/","RSHFT","PAD*","LALT","SPC", +"CPSLK","F1","F2","F3","F4","F5","F6","F7","F8","F9", +"F10","NMLCK","SCLK","PAD7","PAD8","PAD9","PAD-", +"PAD4","PAD5","PAD6","PAD+","PAD1","PAD2","PAD3","PAD0", +"PAD.","","","","F11","F12","","","","","","","","","", +"","","","","","","","","","","","","","","","","","","","", +"","","","","","","","","","","","","","","","","","","","", +"","","","","","","","","","","","","","","","","","", +"PADƒ","RCTRL","","","","","","","","","","","","","", +"","","","","","","","","","","PAD/","","","RALT","", +"","","","","","","","","","","","","","HOME","‚","PGUP", +"","","","","","END","€","PGDN","INS", +"DEL","","","","","","","","","","","","","","","","","", +"","","","","","","","","","","","","","","","","","","","", +"","","","","","","" }; + +unsigned char ascii_table[128] = +{ 255, 255, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=',255,255, + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 255, 255, + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', 39, '`', + 255, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 255,'*', + 255, ' ', 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255,255, + 255, 255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255 }; + +unsigned char shifted_ascii_table[128] = +{ 255, 255, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+',255,255, + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 255, 255, + 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', + 255, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 255,255, + 255, ' ', 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255,255, + 255, 255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255 }; + +int giiKeyTranslate (int keylabel) { + switch (keylabel) + { + case GIIUC_0: return KEY_0; + case GIIUC_1: return KEY_1; + case GIIUC_2: return KEY_2; + case GIIUC_3: return KEY_3; + case GIIUC_4: return KEY_4; + case GIIUC_5: return KEY_5; + case GIIUC_6: return KEY_6; + case GIIUC_7: return KEY_7; + case GIIUC_8: return KEY_8; + case GIIUC_9: return KEY_9; + + case GIIUC_A: return KEY_A; + case GIIUC_B: return KEY_B; + case GIIUC_C: return KEY_C; + case GIIUC_D: return KEY_D; + case GIIUC_E: return KEY_E; + case GIIUC_F: return KEY_F; + case GIIUC_G: return KEY_G; + case GIIUC_H: return KEY_H; + case GIIUC_I: return KEY_I; + case GIIUC_J: return KEY_J; + case GIIUC_K: return KEY_K; + case GIIUC_L: return KEY_L; + case GIIUC_M: return KEY_M; + case GIIUC_N: return KEY_N; + case GIIUC_O: return KEY_O; + case GIIUC_P: return KEY_P; + case GIIUC_Q: return KEY_Q; + case GIIUC_R: return KEY_R; + case GIIUC_S: return KEY_S; + case GIIUC_T: return KEY_T; + case GIIUC_U: return KEY_U; + case GIIUC_V: return KEY_V; + case GIIUC_W: return KEY_W; + case GIIUC_X: return KEY_X; + case GIIUC_Y: return KEY_Y; + case GIIUC_Z: return KEY_Z; + + case GIIUC_Minus: return KEY_MINUS; + case GIIUC_Equal: return KEY_EQUAL; + case GIIUC_Slash: return KEY_DIVIDE; + case GIIUC_BackSlash: return KEY_SLASH; + case GIIUC_Comma: return KEY_COMMA; + case GIIUC_Period: return KEY_PERIOD; + case GIIUC_Semicolon: return KEY_SEMICOL; + + case GIIUC_BracketLeft: return KEY_LBRACKET; + case GIIUC_BracketRight: return KEY_RBRACKET; + + case GIIUC_Apostrophe: return KEY_RAPOSTRO; + case GIIUC_Grave: return KEY_LAPOSTRO; + + case GIIUC_Escape: return KEY_ESC; + case GIIK_Enter: return KEY_ENTER; + case GIIUC_BackSpace: return KEY_BACKSP; + case GIIUC_Tab: return KEY_TAB; + case GIIUC_Space: return KEY_SPACEBAR; + + case GIIK_NumLock: return KEY_NUMLOCK; + case GIIK_ScrollLock: return KEY_SCROLLOCK; + case GIIK_CapsLock: return KEY_CAPSLOCK; + + case GIIK_ShiftL: return KEY_LSHIFT; + case GIIK_ShiftR: return KEY_RSHIFT; + + case GIIK_AltL: return KEY_LALT; + case GIIK_AltR: return KEY_RALT; + + case GIIK_CtrlL: return KEY_LCTRL; + case GIIK_CtrlR: return KEY_RCTRL; + + case GIIK_F1: return KEY_F1; + case GIIK_F2: return KEY_F2; + case GIIK_F3: return KEY_F3; + case GIIK_F4: return KEY_F4; + case GIIK_F5: return KEY_F5; + case GIIK_F6: return KEY_F6; + case GIIK_F7: return KEY_F7; + case GIIK_F8: return KEY_F8; + case GIIK_F9: return KEY_F9; + case GIIK_F10: return KEY_F10; + case GIIK_F11: return KEY_F11; + case GIIK_F12: return KEY_F12; + + case GIIK_P0: return KEY_PAD0; + case GIIK_P1: return KEY_PAD1; + case GIIK_P2: return KEY_PAD2; + case GIIK_P3: return KEY_PAD3; + case GIIK_P4: return KEY_PAD4; + case GIIK_P5: return KEY_PAD5; + case GIIK_P6: return KEY_PAD6; + case GIIK_P7: return KEY_PAD7; + case GIIK_P8: return KEY_PAD8; + case GIIK_P9: return KEY_PAD9; + case GIIK_PMinus: return KEY_PADMINUS; + case GIIK_PPlus: return KEY_PADPLUS; + case GIIK_PDecimal: return KEY_PADPERIOD; + case GIIK_PSlash: return KEY_PADDIVIDE; + case GIIK_PAsterisk: return KEY_PADMULTIPLY; + case GIIK_PEnter: return KEY_PADENTER; + + case GIIK_Insert: return KEY_INSERT; + case GIIK_Home: return KEY_HOME; + case GIIK_PageUp: return KEY_PAGEUP; + case GIIK_Delete: return KEY_DELETE; + case GIIK_End: return KEY_END; + case GIIK_PageDown: return KEY_PAGEDOWN; + case GIIK_Up: return KEY_UP; + case GIIK_Down: return KEY_DOWN; + case GIIK_Left: return KEY_LEFT; + case GIIK_Right: return KEY_RIGHT; + + case GIIK_PrintScreen: return KEY_PRINT_SCREEN; + case GIIK_Pause: return KEY_PAUSE; + } + return 0; +} + +//killed on 10/03/98 by Matt Mueller +//unsigned char key_to_ascii(int a) +//{ +// if (!isprint(a)) return 255; +// if (a & KEY_SHIFTED) { +// return (toupper((unsigned char) a)); +// } else { +// return ((unsigned char) a); +// } +//} +//end kill -MM + +//added on 10/03/98 by Matt Mueller to fix shifted keys (copied from dos/key.c) +unsigned char key_to_ascii(int keycode) +{ + int shifted; + + shifted = keycode & KEY_SHIFTED; + keycode &= 0xFF; + + if ( keycode>=127 ) + return 255; + + if (shifted) + return shifted_ascii_table[keycode]; + else + return ascii_table[keycode]; +} +//end addition -MM + +void keyboard_handler(int button, ubyte state) +{ + ubyte key_state; + int i, keycode; + unsigned short event_key; + Key_info *key; + unsigned char temp; + + key_state = state; + event_key = giiKeyTranslate(button); + //mprintf((0,"keyboard_handler(%i,%i):%i\n",button,state,event_key)); + + //===================================================== + //Here a translation from win keycodes to mac keycodes! + //===================================================== + + for (i = 255; i >= 0; i--) { + + keycode = i; + key = &(key_data.keys[keycode]); + if (i == event_key) + state = key_state; + else + state = key->last_state; + + if ( key->last_state == state ) { + if (state) { + key->counter++; + keyd_last_pressed = keycode; + keyd_time_when_last_pressed = timer_get_fixed_seconds(); + } + } else { + if (state) { + keyd_last_pressed = keycode; + keyd_pressed[keycode] = 1; + key->downcount += state; + key->state = 1; + key->timewentdown = keyd_time_when_last_pressed = timer_get_fixed_seconds(); + key->counter++; + } else { + keyd_pressed[keycode] = 0; + keyd_last_released = keycode; + key->upcount += key->state; + key->state = 0; + key->counter = 0; + key->timehelddown += timer_get_fixed_seconds() - key->timewentdown; + } + } + if ( (state && !key->last_state) || (state && key->last_state && (key->counter > 30) && (key->counter & 0x01)) ) { + if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT]) + keycode |= KEY_SHIFTED; + if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT]) + keycode |= KEY_ALTED; + if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL]) + keycode |= KEY_CTRLED; + if ( keyd_pressed[KEY_DELETE] ) + keycode |= KEY_DEBUGGED; + temp = key_data.keytail+1; + if ( temp >= KEY_BUFFER_SIZE ) temp=0; + if (temp!=key_data.keyhead) { + key_data.keybuffer[key_data.keytail] = keycode; + key_data.time_pressed[key_data.keytail] = keyd_time_when_last_pressed; + key_data.keytail = temp; + } + } + key->last_state = state; + } +} + +void key_close() +{ + Installed = 0; +} + +void key_init() +{ + Installed=1; + + keyd_time_when_last_pressed = timer_get_fixed_seconds(); + keyd_buffer_type = 1; + keyd_repeat = 1; + +// Clear the keyboard array + key_flush(); + atexit(key_close); +} + +void key_flush() +{ + int i; + fix curtime; + + if (!Installed) + key_init(); + + key_data.keyhead = key_data.keytail = 0; + + //Clear the keyboard buffer + for (i=0; i= KEY_BUFFER_SIZE ) n=0; + return n; +} + +int key_checkch() +{ + int is_one_waiting = 0; + event_poll(); + if (key_data.keytail!=key_data.keyhead) + is_one_waiting = 1; + return is_one_waiting; +} + +int key_inkey() +{ + int key = 0; + if (!Installed) + key_init(); + event_poll(); + if (key_data.keytail!=key_data.keyhead) { + key = key_data.keybuffer[key_data.keyhead]; + key_data.keyhead = add_one(key_data.keyhead); + } +//added 9/3/98 by Matt Mueller to free cpu time instead of hogging during menus and such +// else d_delay(1); +//end addition - Matt Mueller + return key; +} + +int key_inkey_time(fix * time) +{ + int key = 0; + + if (!Installed) + key_init(); + event_poll(); + if (key_data.keytail!=key_data.keyhead) { + key = key_data.keybuffer[key_data.keyhead]; + *time = key_data.time_pressed[key_data.keyhead]; + key_data.keyhead = add_one(key_data.keyhead); + } + return key; +} + +int key_peekkey() +{ + int key = 0; + event_poll(); + if (key_data.keytail!=key_data.keyhead) + key = key_data.keybuffer[key_data.keyhead]; + + return key; +} + +int key_getch() +{ + int dummy=0; + + if (!Installed) + return 0; +// return getch(); + + while (!key_checkch()) + dummy++; + return key_inkey(); +} + +unsigned int key_get_shift_status() +{ + unsigned int shift_status = 0; + + if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT] ) + shift_status |= KEY_SHIFTED; + + if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT] ) + shift_status |= KEY_ALTED; + + if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL] ) + shift_status |= KEY_CTRLED; + +#ifndef NDEBUG + if (keyd_pressed[KEY_DELETE]) + shift_status |=KEY_DEBUGGED; +#endif + + return shift_status; +} + +// Returns the number of seconds this key has been down since last call. +fix key_down_time(int scancode) +{ + fix time_down, time; + + event_poll(); + if ((scancode<0)|| (scancode>255)) return 0; + + if (!keyd_pressed[scancode]) { + time_down = key_data.keys[scancode].timehelddown; + key_data.keys[scancode].timehelddown = 0; + } else { + time = timer_get_fixed_seconds(); + time_down = time - key_data.keys[scancode].timewentdown; + key_data.keys[scancode].timewentdown = time; + } + + return time_down; +} + +unsigned int key_down_count(int scancode) +{ + int n; + event_poll(); + if ((scancode<0)|| (scancode>255)) return 0; + + n = key_data.keys[scancode].downcount; + key_data.keys[scancode].downcount = 0; + + return n; +} + +unsigned int key_up_count(int scancode) +{ + int n; + event_poll(); + if ((scancode<0)|| (scancode>255)) return 0; + + n = key_data.keys[scancode].upcount; + key_data.keys[scancode].upcount = 0; + + return n; +} + diff --git a/input/ggi/mouse.c b/input/ggi/mouse.c new file mode 100644 index 00000000..7bf97316 --- /dev/null +++ b/input/ggi/mouse.c @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include "fix.h" +#include "timer.h" +#include "event.h" +#include "mouse.h" + +struct mousebutton { + ubyte pressed; + fix time_went_down; + fix time_held_down; + uint num_downs; + uint num_ups; +}; + +#define MOUSE_MAX_BUTTONS 3 + +static struct mouseinfo { + struct mousebutton buttons[MOUSE_MAX_BUTTONS]; +//added on 10/17/98 by Hans de Goede for mouse functionality + int min_x, min_y; + int max_x, max_y; + int delta_x, delta_y; + int x,y; +} Mouse; + +void mouse_correct() +{ + if (Mouse.x < Mouse.min_x) + Mouse.x = Mouse.min_x; + else if (Mouse.x > Mouse.max_x) + Mouse.x = Mouse.max_x; + if (Mouse.y < Mouse.min_y) + Mouse.y = Mouse.min_y; + else if (Mouse.y > Mouse.max_y) + Mouse.y = Mouse.max_y; +} + +void mouse_handler_absolute(int x, int y) +{ + Mouse.delta_x += (x - Mouse.x); + Mouse.delta_y += (y - Mouse.y); + Mouse.x = x; + Mouse.y = y; +// mouse_correct(); +} + +void mouse_handler_relative(int x, int y) +{ + Mouse.delta_x += x; + Mouse.delta_y += y; + Mouse.x += x; + Mouse.y += y; +// mouse_correct(); +} + +void mouse_handler_button(int button, ubyte state) +{ + if (!Mouse.buttons[button].pressed && state) + { + Mouse.buttons[button].time_went_down = timer_get_fixed_seconds(); + Mouse.buttons[button].num_downs++; + } + else if (Mouse.buttons[button].pressed && !state) + { + Mouse.buttons[button].num_ups++; + } + + Mouse.buttons[button].pressed = state; +} + +void Mouse_close(void) +{ +} + +void Mouse_init(void) +{ + memset(&Mouse, 0, sizeof(Mouse)); +} + +int mouse_set_limits( int x1, int y1, int x2, int y2 ) +{ + Mouse.min_x = x1; + Mouse.max_x = x2; + Mouse.min_y = y1; + Mouse.max_y = y2; + return MOUSE_MAX_BUTTONS; +} + +void mouse_flush() // clears all mice events... +{ + Mouse.x = 0; + Mouse.y = 0; + Mouse.delta_x = 0; + Mouse.delta_y = 0; +} + +//======================================================================== +void mouse_get_pos( int *x, int *y) +{ + event_poll(); + *x = Mouse.x; + *y = Mouse.y; +} + +void mouse_get_delta( int *dx, int *dy ) +{ + event_poll(); + *dx = Mouse.delta_x; + *dy = Mouse.delta_y; + Mouse.delta_x = 0; + Mouse.delta_y = 0; +} + +int mouse_get_btns() +{ + ubyte buttons = 0; + int i; + event_poll(); + for (i = 0; i < MOUSE_MAX_BUTTONS; i++) + buttons |= (Mouse.buttons[i].pressed << i); + return buttons; +} + +void mouse_set_pos( int x, int y) +{ + Mouse.x = x; + Mouse.y = y; +} + +void mouse_get_cyberman_pos( int *x, int *y ) +{ +} + +// Returns how long this button has been down since last call. +fix mouse_button_down_time(int button) +{ + if (Mouse.buttons[button].pressed) + return (timer_get_fixed_seconds() - Mouse.buttons[button].time_went_down); + else + return 0; +} + +// Returns how many times this button has went down since last call +int mouse_button_down_count(int button) +{ + int count = Mouse.buttons[button].num_downs; + Mouse.buttons[button].num_downs = 0; + return count; +} + +// Returns 1 if this button is currently down +int mouse_button_state(int button) +{ + return Mouse.buttons[button].pressed; +} diff --git a/input/linux/Makefile.am b/input/linux/Makefile.am new file mode 100644 index 00000000..711a38d9 --- /dev/null +++ b/input/linux/Makefile.am @@ -0,0 +1,4 @@ +noinst_LIBRARIES = libinputlinux.a +INCLUDES = -I$(top_srcdir)/includes -I$(top_srcdir)/main -Iinclude -I../sdl/include +libinputlinux_a_SOURCES = \ +joystick.c joydefs.c diff --git a/input/linux/Makefile.in b/input/linux/Makefile.in new file mode 100644 index 00000000..ba3cea69 --- /dev/null +++ b/input/linux/Makefile.in @@ -0,0 +1,299 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +CFLAGS = @CFLAGS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +NASM = @NASM@ +NASMFLAGS = @NASMFLAGS@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_LIBS = @SDL_LIBS@ +VERSION = @VERSION@ + +noinst_LIBRARIES = libinputlinux.a +INCLUDES = -I$(top_srcdir)/includes -I$(top_srcdir)/main -Iinclude -I../sdl/include +libinputlinux_a_SOURCES = joystick.c joydefs.c + +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../../conf.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I../.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +libinputlinux_a_LIBADD = +libinputlinux_a_OBJECTS = joystick.o joydefs.o +AR = ar +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +DEP_FILES = .deps/joydefs.P .deps/joystick.P +SOURCES = $(libinputlinux_a_SOURCES) +OBJECTS = $(libinputlinux_a_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu input/linux/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +libinputlinux.a: $(libinputlinux_a_OBJECTS) $(libinputlinux_a_DEPENDENCIES) + -rm -f libinputlinux.a + $(AR) cru libinputlinux.a $(libinputlinux_a_OBJECTS) $(libinputlinux_a_LIBADD) + $(RANLIB) libinputlinux.a + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = input/linux + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu input/linux/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile $(LIBRARIES) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ + mostlyclean-tags mostlyclean-depend mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \ + clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-noinstLIBRARIES distclean-compile \ + distclean-tags distclean-depend distclean-generic \ + clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/input/linux/include/joy.h b/input/linux/include/joy.h new file mode 100644 index 00000000..0db36753 --- /dev/null +++ b/input/linux/include/joy.h @@ -0,0 +1,150 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifndef _JOY_H +#define _JOY_H + +#include "pstypes.h" +#include "fix.h" + +#define JOY_1_BUTTON_A 1 +#define JOY_1_BUTTON_B 2 +#define JOY_2_BUTTON_A 4 +#define JOY_2_BUTTON_B 8 +#define JOY_ALL_BUTTONS (1+2+4+8) + +#define JOY_1_X_AXIS 1 +#define JOY_1_Y_AXIS 2 +#define JOY_2_X_AXIS 4 +#define JOY_2_Y_AXIS 8 +#define JOY_ALL_AXIS (1+2+4+8) + +#define JOY_SLOW_READINGS 1 +#define JOY_POLLED_READINGS 2 +#define JOY_BIOS_READINGS 4 +#define JOY_FRIENDLY_READINGS 8 + +#define MAX_AXES 32 +#define MAX_BUTTONS 64 + +#define JOY_NUM_AXES 4 + +typedef struct joystick_device { + int device_number; + int version; + int buffer; + char num_buttons; + char num_axes; +} joystick_device; + +typedef struct joystick_axis { + int value; + int min_val; + int center_val; + int max_val; + int joydev; +} joystick_axis; + +typedef struct joystick_button { + ubyte state; + ubyte last_state; +//changed 6/24/1999 to finally squish the timedown bug - Owen Evans + fix timedown; +//end changed - OE + ubyte downcount; + int num; + int joydev; +} joystick_button; + +//========================================================================== +// This initializes the joy and does a "quick" calibration which +// assumes the stick is centered and sets the minimum value to 0 and +// the maximum value to 2 times the centered reading. Returns 0 if no +// joystick was detected, 1 if everything is ok. +// joy_init() is called. + +extern int joy_init(); +extern void joy_close(); + +extern char joy_installed; +extern char joy_present; + +extern int j_num_axes; +extern int j_num_buttons; + +extern int joy_deadzone; + +extern joystick_device j_joystick[4]; +extern joystick_axis j_axis[MAX_AXES]; +extern joystick_button j_button[MAX_BUTTONS]; + +//========================================================================== +// The following 3 routines can be used to zero in on better joy +// calibration factors. To use them, ask the user to hold the stick +// in either the upper left, lower right, or center and then have them +// press a key or button and then call the appropriate one of these +// routines, and it will read the stick and update the calibration factors. +// Usually, assuming that the stick was centered when joy_init was +// called, you really only need to call joy_set_lr, since the upper +// left position is usually always 0,0 on most joys. But, the safest +// bet is to do all three, or let the user choose which ones to set. + +extern void joy_set_cen(); + +//========================================================================== +// This reads the joystick. X and Y will be between -128 and 127. +// Takes about 1 millisecond in the worst case when the stick +// is in the lower right hand corner. Always returns 0,0 if no stick +// is present. + +extern void joy_get_pos( int *x, int *y ); + +//========================================================================== +// This just reads the buttons and returns their status. When bit 0 +// is 1, button 1 is pressed, when bit 1 is 1, button 2 is pressed. +extern int joy_get_btns(); + +//========================================================================== +// This returns the number of times a button went either down or up since +// the last call to this function. +extern int joy_get_button_up_cnt( int btn ); +extern int joy_get_button_down_cnt( int btn ); + +//========================================================================== +// This returns how long (in approximate milliseconds) that each of the +// buttons has been held down since the last call to this function. +// It is the total time... say you pressed it down for 3 ticks, released +// it, and held it down for 6 more ticks. The time returned would be 9. +extern fix joy_get_button_down_time( int btn ); + +extern int j_Update_state (); +extern int j_Get_joydev_axis_number (int all_axis_number); +extern int j_Get_joydev_button_number (int all_button_number); + +extern ubyte joystick_read_raw_axis( ubyte mask, int * axis ); +extern void joy_flush(); +extern ubyte joy_get_present_mask(); +extern void joy_set_timer_rate(int max_value ); +extern int joy_get_timer_rate(); + +extern int joy_get_button_state( int btn ); +extern void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max); +extern void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max); +extern int joy_get_scaled_reading( int raw, int axn ); +extern void joy_set_slow_reading( int flag ); + +extern void joy_set_min (int axis_number, int value); +extern void joy_set_center (int axis_number, int value); +extern void joy_set_max (int axis_number, int value); + +#endif diff --git a/input/linux/include/joystick.h b/input/linux/include/joystick.h new file mode 100644 index 00000000..e201d454 --- /dev/null +++ b/input/linux/include/joystick.h @@ -0,0 +1,266 @@ +#ifndef _LINUX_JOYSTICK_H +#define _LINUX_JOYSTICK_H + +/* + * /usr/include/linux/joystick.h Version 1.2 + * + * Copyright (C) 1996-1998 Vojtech Pavlik + */ + +#include +#include + +/* + * Version + */ + +#define JS_VERSION 0x01020a + +/* + * Types and constants for reading from /dev/js + */ + +#define JS_EVENT_BUTTON 0x01 /* button pressed/released */ +#define JS_EVENT_AXIS 0x02 /* joystick moved */ +#define JS_EVENT_INIT 0x80 /* initial state of device */ + +struct js_event { + __u32 time; /* event timestamp in miliseconds */ + __s16 value; /* value */ + __u8 type; /* event type */ + __u8 number; /* axis/button number */ +}; + +/* + * IOCTL commands for joystick driver + */ + +#define JSIOCGVERSION _IOR('j', 0x01, __u32) /* get driver version */ + +#define JSIOCGAXES _IOR('j', 0x11, __u8) /* get number of axes */ +#define JSIOCGBUTTONS _IOR('j', 0x12, __u8) /* get number of buttons */ +#define JSIOCGNAME(len) _IOC(_IOC_READ, 'j', 0x13, len) /* get identifier string */ + +#define JSIOCSCORR _IOW('j', 0x21, struct js_corr) /* set correction values */ +#define JSIOCGCORR _IOR('j', 0x22, struct js_corr) /* get correction values */ + +/* + * Types and constants for get/set correction + */ + +#define JS_CORR_NONE 0x00 /* returns raw values */ +#define JS_CORR_BROKEN 0x01 /* broken line */ + +struct js_corr { + __s32 coef[8]; + __s16 prec; + __u16 type; +}; + +/* + * v0.x compatibility definitions + */ + +#define JS_RETURN sizeof(struct JS_DATA_TYPE) +#define JS_TRUE 1 +#define JS_FALSE 0 +#define JS_X_0 0x01 +#define JS_Y_0 0x02 +#define JS_X_1 0x04 +#define JS_Y_1 0x08 +#define JS_MAX 2 + +#define JS_DEF_TIMEOUT 0x1300 +#define JS_DEF_CORR 0 +#define JS_DEF_TIMELIMIT 10L + +#define JS_SET_CAL 1 +#define JS_GET_CAL 2 +#define JS_SET_TIMEOUT 3 +#define JS_GET_TIMEOUT 4 +#define JS_SET_TIMELIMIT 5 +#define JS_GET_TIMELIMIT 6 +#define JS_GET_ALL 7 +#define JS_SET_ALL 8 + +struct JS_DATA_TYPE { + int buttons; + int x; + int y; +}; + +struct JS_DATA_SAVE_TYPE { + int JS_TIMEOUT; + int BUSY; + long JS_EXPIRETIME; + long JS_TIMELIMIT; + struct JS_DATA_TYPE JS_SAVE; + struct JS_DATA_TYPE JS_CORR; +}; + +/* + * Internal definitions + */ + +#ifdef __KERNEL__ + +#define JS_BUFF_SIZE 64 /* output buffer size */ + +#include + +#ifndef KERNEL_VERSION +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif + +#ifndef LINUX_VERSION_CODE +#error "You need to use at least 2.0 Linux kernel." +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,0,0) +#error "You need to use at least 2.0 Linux kernel." +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) +#define JS_HAS_RDTSC (current_cpu_data.x86_capability & 0x10) +#include +#else +#ifdef MODULE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,35) +#define JS_HAS_RDTSC (x86_capability & 0x10) +#else +#define JS_HAS_RDTSC 0 +#endif +#else +#define JS_HAS_RDTSC (x86_capability & 0x10) +#endif +#define __initdata +#define __init +#define MODULE_AUTHOR(x) +#define MODULE_PARM(x,y) +#define MODULE_SUPPORTED_DEVICE(x) +#define signal_pending(x) (((x)->signal) & ~((x)->blocked)) +#endif + +/* + * Parport stuff + */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) +#define USE_PARPORT +#endif + +#ifdef USE_PARPORT +#include +#define JS_PAR_STATUS(y) parport_read_status(y->port) +#define JS_PAR_DATA_IN(y) parport_read_data(y->port) +#define JS_PAR_DATA_OUT(x,y) parport_write_data(y->port, x) +#define JS_PAR_CTRL_OUT(x,y) parport_write_control(y->port, x) +#else +#define JS_PAR_STATUS(y) inb(y+1) +#define JS_PAR_DATA_IN(y) inb(y) +#define JS_PAR_DATA_OUT(x,y) outb(x,y) +#define JS_PAR_CTRL_OUT(x,y) outb(x,y+2) +#endif + +#define JS_PAR_STATUS_INVERT (0x80) + +/* + * Internal types + */ + +struct js_dev; + +typedef int (*js_read_func)(void *info, int **axes, int **buttons); +typedef unsigned int (*js_time_func)(void); +typedef int (*js_delta_func)(unsigned int x, unsigned int y); +typedef int (*js_ops_func)(struct js_dev *dev); + +struct js_data { + int *axes; + int *buttons; +}; + +struct js_dev { + struct js_dev *next; + struct js_list *list; + struct js_port *port; + struct wait_queue *wait; + struct js_data cur; + struct js_data new; + struct js_corr *corr; + struct js_event buff[JS_BUFF_SIZE]; + js_ops_func open; + js_ops_func close; + int ahead; + int bhead; + int tail; + int num_axes; + int num_buttons; + char *name; +}; + +struct js_list { + struct js_list *next; + struct js_dev *dev; + int tail; + int startup; +}; + +struct js_port { + struct js_port *next; + struct js_port *prev; + js_read_func read; + struct js_dev **devs; + int **axes; + int **buttons; + struct js_corr **corr; + void *info; + int ndevs; +}; + +/* + * Sub-module interface + */ + +extern unsigned int js_time_speed; +extern js_time_func js_get_time; +extern js_delta_func js_delta; + +extern unsigned int js_time_speed_a; +extern js_time_func js_get_time_a; +extern js_delta_func js_delta_a; + +extern struct js_port *js_register_port(struct js_port *port, void *info, + int devs, int infos, js_read_func read); +extern struct js_port *js_unregister_port(struct js_port *port); + +extern int js_register_device(struct js_port *port, int number, int axes, + int buttons, char *name, js_ops_func open, js_ops_func close); +extern void js_unregister_device(struct js_dev *dev); + +/* + * Kernel interface + */ + +extern int js_init(void); +extern int js_am_init(void); +extern int js_an_init(void); +extern int js_as_init(void); +extern int js_console_init(void); +extern int js_db9_init(void); +extern int js_gr_init(void); +extern int js_l4_init(void); +extern int js_lt_init(void); +extern int js_sw_init(void); +extern int js_tm_init(void); + +extern void js_am_setup(char *str, int *ints); +extern void js_an_setup(char *str, int *ints); +extern void js_as_setup(char *str, int *ints); +extern void js_console_setup(char *str, int *ints); +extern void js_db9_setup(char *str, int *ints); +extern void js_l4_setup(char *str, int *ints); + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_JOYSTICK_H */ diff --git a/input/linux/joydefs.c b/input/linux/joydefs.c new file mode 100644 index 00000000..8e072e0d --- /dev/null +++ b/input/linux/joydefs.c @@ -0,0 +1,237 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#include +#include +#include +#include + +#include "pstypes.h" +#include "mono.h" +#include "key.h" +#include "joy.h" +#include "timer.h" +#include "error.h" + +#include "inferno.h" +#include "game.h" +#include "object.h" +#include "player.h" + +#include "controls.h" +#include "joydefs.h" +//#include "victor.h" +#include "render.h" +#include "palette.h" +#include "newmenu.h" +#include "args.h" +#include "text.h" +#include "kconfig.h" +#include "digi.h" +#include "playsave.h" + +int joydefs_calibrate_flag = 0; + +//added 9/6/98 Matt Mueller - not needed at all in linux code but bunches +int Joy_is_Sidewinder=0;// of main/* stuff uses it +//end addition + +void joy_delay() +{ + //int t1 = TICKER + 19/4; // Wait 1/4 second... + //stop_time(); + //while( TICKER < t1 ); + //joy_flush(); + //start_time(); +} + + +int joycal_message( char * title, char * text ) +{ + int i; + newmenu_item m[2]; + m[0].type = NM_TYPE_TEXT; m[0].text = text; + m[1].type = NM_TYPE_MENU; m[1].text = TXT_OK; + i = newmenu_do( title, NULL, 2, m, NULL ); + if ( i < 0 ) + return 1; + return 0; +} + +extern int WriteConfigFile(); + +extern joystick_device j_joystick[4]; +extern joystick_axis j_axis[MAX_AXES]; +extern joystick_button j_button[MAX_BUTTONS]; + +void joydefs_calibrate() +{ + + int i; + int temp_values[MAX_AXES]; + char title[50]; + char text[256]; +//added/killed on 10/17/98 by Hans de Goede for joystick/mouse # fix +//-killed- int nsticks = 0; +//end this section kill - Hans + + joydefs_calibrate_flag = 0; + + if (!joy_present) { + nm_messagebox( NULL, 1, TXT_OK, TXT_NO_JOYSTICK ); + return; + } + + if (j_joystick[0].version) { + joycal_message ("No Calibration", "calibration not required for\njoystick v1.x"); + return; + } + + for (i = 0; i < j_num_axes; i += 2) { + sprintf (title, "js%d Calibration", j_axis[i].joydev); + + sprintf (text, "center joystick %d", j_axis[i].joydev); + joycal_message (title, text); + joystick_read_raw_axis (JOY_ALL_AXIS, temp_values); + j_axis[i].center_val = temp_values[i]; + j_axis[i + 1].center_val = temp_values[i + 1]; + + sprintf (text, "move joystick %d to the upper left", j_axis[i].joydev); + joycal_message (title, text); + joystick_read_raw_axis (JOY_ALL_AXIS, temp_values); + j_axis[i].min_val = temp_values[i]; + j_axis[i + 1].min_val = temp_values[i + 1]; + + sprintf (text, "move joystick %d to the lower right", j_axis[i].joydev); + joycal_message (title, text); + joystick_read_raw_axis (JOY_ALL_AXIS, temp_values); + j_axis[i].max_val = temp_values[i]; + j_axis[i + 1].max_val = temp_values[i + 1]; + + } + + WriteConfigFile (); +} + + +//char *control_text[CONTROL_MAX_TYPES] = { "Keyboard only", "Joystick", "Flightstick Pro", "Thrustmaster FCS", "Gravis Gamepad", "Mouse", "Cyberman" }; + +void joydef_menuset_1(int nitems, newmenu_item * items, int *last_key, int citem ) +{ + int i; + int oc_type = Config_control_type; + + nitems = nitems; + last_key = last_key; + citem = citem; + + for (i=0; i<3; i++ ) + if (items[i].value) Config_control_type = i; + +//added on 10/17/98 by Hans de Goede for joystick/mouse # fix + // remap mouse, since "Flightstick Pro", "Thrustmaster FCS" + // and "Gravis Gamepad" where removed from the options + if (Config_control_type == 2) Config_control_type = CONTROL_MOUSE; +//end this section addition - Hans + + if ( (oc_type != Config_control_type) && (Config_control_type == CONTROL_THRUSTMASTER_FCS ) ) { + nm_messagebox( TXT_IMPORTANT_NOTE, 1, TXT_OK, TXT_FCS ); + } + + if (oc_type != Config_control_type) { + switch (Config_control_type) { + // case CONTROL_NONE: + case CONTROL_JOYSTICK: + case CONTROL_FLIGHTSTICK_PRO: + case CONTROL_THRUSTMASTER_FCS: + case CONTROL_GRAVIS_GAMEPAD: + // case CONTROL_MOUSE: + // case CONTROL_CYBERMAN: + joydefs_calibrate_flag = 1; + } + kc_set_controls(); + } + +} + +extern ubyte kc_use_external_control; +extern ubyte kc_enable_external_control; +extern ubyte *kc_external_name; + +void joydefs_config() +{ +//added/changed/killed on 10/17/98 by Hans de Goede for joystick/mouse # fix +//-killed- char xtext[128]; +//-killed- int i, old_masks, masks; + newmenu_item m[13]; +//-killed- int i1=5; +//-killed- int nitems; +//-killed- +//-killed- do { +//-killed- nitems = 6; + int i, i1=5, j, nitems=7; +//end this section kill/change - Hans + + m[0].type = NM_TYPE_RADIO; m[0].text = "KEYBOARD"; m[0].value = 0; m[0].group = 0; + m[1].type = NM_TYPE_RADIO; m[1].text = "JOYSTICK"; m[1].value = 0; m[1].group = 0; + m[2].type = NM_TYPE_RADIO; m[2].text = "MOUSE"; m[2].value = 0; m[2].group = 0; + m[3].type = NM_TYPE_TEXT; m[3].text=""; + m[4].type = NM_TYPE_MENU; m[4].text="CUSTOMIZE ABOVE"; + m[5].type = NM_TYPE_MENU; m[5].text="CUSTOMIZE KEYBOARD"; +//added on 2/5/99 by Victor Rachels for D1X keys menu + m[6].type = NM_TYPE_MENU; m[6].text="CUSTOMIZE D1X KEYS"; +//end this section addition - VR + +//added/changed/killed on 10/17/98 by Hans de Goede for joystick/mouse # fix +//-killed- m[Config_control_type].value = 1; + + do { + + + i = Config_control_type; + if(i==CONTROL_MOUSE) i = 2; + m[i].value=1; +//end section - OE +//end this section change/addition - Hans + + i1 = newmenu_do1( NULL, TXT_CONTROLS, nitems, m, joydef_menuset_1, i1 ); + +//added 6-15-99 Owen Evans + for (j = 0; j <= 2; j++) + if (m[j].value) + Config_control_type = j; + i = Config_control_type; + if (Config_control_type == 2) + Config_control_type = CONTROL_MOUSE; +//end added - OE + + switch(i1) { + case 4: +//added/changed on 10/17/98 by Hans de Goede for joystick/mouse # fix +//-killed- kconfig(Config_control_type, m[Config_control_type].text); + kconfig (i, m[i].text); +//end this section change - Hans + break; + case 5: + kconfig(0, "KEYBOARD"); + break; +//added on 2/5/99 by Victor Rachels for D1X keys menu + case 6: + kconfig(3, "D1X KEYS"); + break; +//end this section addition - VR + } + + } while(i1>-1); + +} diff --git a/input/linux/joystick.c b/input/linux/joystick.c new file mode 100644 index 00000000..6c9a1ee0 --- /dev/null +++ b/input/linux/joystick.c @@ -0,0 +1,376 @@ +#include +#include +#include +//#include "joystick.h" +#include +#include +#include + +#include "timer.h" +#include "pstypes.h" +#include "mono.h" +#include "joy.h" + +char joy_installed = 0; +char joy_present = 0; + +joystick_device j_joystick[4]; +joystick_axis j_axis[MAX_AXES]; +joystick_button j_button[MAX_BUTTONS]; + +int j_num_axes = 0, j_num_buttons = 0; +int timer_rate; + +int j_axes_in_sticks[4]; /* number of axes in the first [x] sticks */ +int j_buttons_in_sticks[4]; /* number of buttons in the first [x] sticks */ + +int joy_deadzone = 0; + +int j_Get_joydev_axis_number (int all_axis_number) { + int i, joy_axis_number = all_axis_number; + + for (i = 0; i < j_axis[all_axis_number].joydev; i++) { + joy_axis_number -= j_joystick[i].num_axes; + } + + return joy_axis_number; +} + + +int j_Get_joydev_button_number (int all_button_number) { + int i, joy_button_number = all_button_number; + + for (i = 0; i < j_button[all_button_number].joydev; i++) { + joy_button_number -= j_joystick[i].num_buttons; + } + + return joy_button_number; +} + + +int j_Update_state () { +/* int num_processed = 0, i; + struct js_event current_event; + struct JS_DATA_TYPE joy_data; + + for (i = 0; i < j_num_buttons; i++) { + //changed 6/24/1999 to finally squish the timedown bug - Owen Evans + if (j_button[i].state != j_button[i].last_state) { + if (j_button[i].state) { + j_button[i].downcount++; + j_button[i].timedown = timer_get_fixed_seconds(); + } + } + //end changed - OE + j_button[i].last_state = j_button[i].state; + } + + for (i = 0; i < 4; i++) { + if (j_joystick[i].buffer >= 0) { + if (j_joystick[i].version) { + while (read (j_joystick[i].buffer, ¤t_event, sizeof (struct js_event)) > 0) { + num_processed++; + switch (current_event.type & ~JS_EVENT_INIT) { + case JS_EVENT_AXIS: + j_axis[j_axes_in_sticks[i] + current_event.number].value = current_event.value; + break; + case JS_EVENT_BUTTON: + j_button[j_buttons_in_sticks[i] + current_event.number].state = current_event.value; + break; + } + } + } else { + read (j_joystick[i].buffer, &joy_data, JS_RETURN); + j_axis[j_axes_in_sticks[i] + 0].value = joy_data.x; + j_axis[j_axes_in_sticks[i] + 1].value = joy_data.y; + j_button[j_buttons_in_sticks[i] + 0].state = (joy_data.buttons & 0x01); + j_button[j_buttons_in_sticks[i] + 1].state = (joy_data.buttons & 0x02) >> 1; + } + } + } + + return num_processed;*/ + return 0; +} + + +void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max) { + int i; + + for (i = 0; i < 4; i++) { + j_axis[i].center_val = axis_center[i]; + j_axis[i].min_val = axis_min[i]; + j_axis[i].max_val = axis_max[i]; + } +} + + +void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max) { + int i; + + //edited 05/18/99 Matt Mueller - we should return all axes instead of j_num_axes, since they are all given to us in joy_set_cal_vals ( and because checker complains :) + for (i = 0; i < 4; i++) { + //end edit -MM + axis_center[i] = j_axis[i].center_val; + axis_min[i] = j_axis[i].min_val; + axis_max[i] = j_axis[i].max_val; + } +} + + +void joy_set_min (int axis_number, int value) { + j_axis[axis_number].min_val = value; +} + + +void joy_set_center (int axis_number, int value) { + j_axis[axis_number].center_val = value; +} + + +void joy_set_max (int axis_number, int value) { + j_axis[axis_number].max_val = value; +} + + +ubyte joy_get_present_mask () { + return 1; +} + + +void joy_set_timer_rate (int max_value) { + timer_rate = max_value; +} + + +int joy_get_timer_rate () { + return timer_rate; +} + + +void joy_flush () { + int i; + + if (!joy_installed) return; + + for (i = 0; i < j_num_buttons; i++) { + j_button[i].timedown = 0; + j_button[i].downcount = 0; + } + +} + + +ubyte joystick_read_raw_axis (ubyte mask, int *axes) { + int i; + + j_Update_state(); + + for (i = 0; i <= j_num_axes; i++) { + axes[i] = j_axis[i].value; + } + + return 0; +} + + +/* joy_init () is pretty huge, a bit klunky, and by no means pretty. But who cares? It does the job and it's only run once. */ + + +int joy_init () { + int i, j; + + if (joy_installed) return 0; + joy_flush (); + + if (!joy_installed) { + +// printf ("Initializing joystick... "); + + j_joystick[0].buffer = open ("/dev/js0", O_NONBLOCK); + j_joystick[1].buffer = open ("/dev/js1", O_NONBLOCK); + j_joystick[2].buffer = open ("/dev/js2", O_NONBLOCK); + j_joystick[3].buffer = open ("/dev/js3", O_NONBLOCK); + + if (j_joystick[0].buffer >= 0 || j_joystick[1].buffer >= 0 || j_joystick[2].buffer >= 0 || j_joystick[3].buffer >= 0) { +// printf ("found: "); + + for (i = 0; i < 4; i++) { + if (j_joystick[i].buffer >= 0) { + /* + ioctl (j_joystick[i].buffer, JSIOCGAXES, &j_joystick[i].num_axes); + ioctl (j_joystick[i].buffer, JSIOCGBUTTONS, &j_joystick[i].num_buttons); + ioctl (j_joystick[i].buffer, JSIOCGVERSION, &j_joystick[i].version); +*/ + if (!j_joystick[i].version) { + j_joystick[i].num_axes = 2; + j_joystick[i].num_buttons = 2; +// printf ("js%d (v0.x) " , i); + } else { +// printf ("js%d (v%d.%d.%d) ", i, (j_joystick[i].version & 0xff0000) >> 16, (j_joystick[i].version & 0xff00) >> 8, j_joystick[i].version & 0xff); + } + + for (j = j_num_axes; j < (j_num_axes + j_joystick[i].num_axes); j++) { + j_axis[j].joydev = i; + if (j_joystick[i].version) { + j_axis[j].center_val = 0; + j_axis[j].max_val = 32767; + j_axis[j].min_val = -32767; + } + } + for (j = j_num_buttons; j < (j_num_buttons + j_joystick[i].num_buttons); j++) { + j_button[j].joydev = i; + } + + j_num_axes += j_joystick[i].num_axes; + j_num_buttons += j_joystick[i].num_buttons; + + } else { + j_joystick[i].num_buttons = 0; + j_joystick[i].num_axes = 0; + } + + for (j = 0; j < i; j++) { + j_axes_in_sticks[i] += j_joystick[j].num_axes; + j_buttons_in_sticks[i] += j_joystick[j].num_buttons; + } + } + } else { +// printf ("no joysticks found\n"); + return 0; + } + +// printf ("\n"); + + if (j_num_axes > MAX_AXES) + j_num_axes = MAX_AXES; + if (j_num_buttons > MAX_BUTTONS) + j_num_buttons = MAX_BUTTONS; + + joy_present = 1; + joy_installed = 1; + return 1; + } + + return 1; +} + + +void joy_close() { + int i; + + if (!joy_installed) return; + + for (i = 0; i < 4; i++) { + if (j_joystick[i].buffer>=0) { + printf ("closing js%d\n", i); + close (j_joystick[i].buffer); + } + j_joystick[i].buffer=-1; + } + + joy_present=0; + joy_installed=0; +} + + +void joy_set_cen() { +} + + +int joy_get_scaled_reading(int raw, int axis_num) +{ + int d, x; + + raw -= j_axis[axis_num].center_val; + + if (raw < 0) + d = j_axis[axis_num].center_val - j_axis[axis_num].min_val; + else if (raw > 0) + d = j_axis[axis_num].max_val - j_axis[axis_num].center_val; + else + d = 0; + + if (d) + x = ((raw << 7) / d); + else + x = 0; + + if ( x < -128 ) + x = -128; + if ( x > 127 ) + x = 127; + +//added on 4/13/99 by Victor Rachels to add deadzone control + d = (joy_deadzone) * 6; + if ((x > (-1*d)) && (x < d)) + x = 0; +//end this section addition -VR + + return x; +} + + +void joy_get_pos(int *x, int *y) { + int axis[MAX_AXES]; + + if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; } + + joystick_read_raw_axis (JOY_ALL_AXIS, axis); + + *x = joy_get_scaled_reading( axis[0], 0 ); + *y = joy_get_scaled_reading( axis[1], 1 ); +} + + +int joy_get_btns () { + return 0; +} + + +int joy_get_button_state (int btn) { + if(btn >= j_num_buttons) + return 0; + j_Update_state (); + + return j_button[btn].state; +} + + +int joy_get_button_down_cnt (int btn) { + int downcount; + + j_Update_state (); + + downcount = j_button[btn].downcount; + j_button[btn].downcount = 0; + + return downcount; +} + + +//changed 6/24/99 to finally squish the timedown bug - Owen Evans +fix joy_get_button_down_time(int btn) { + fix downtime; + j_Update_state (); + + if (j_button[btn].state) { + downtime = timer_get_fixed_seconds() - j_button[btn].timedown; + j_button[btn].timedown = timer_get_fixed_seconds(); + } else { + downtime = 0; + } + + return downtime; +} +//end changed - OE + +void joy_poll() { + +} + + +void joy_set_slow_reading(int flag) { + +} + diff --git a/input/sdl/Makefile.am b/input/sdl/Makefile.am new file mode 100644 index 00000000..4e64b952 --- /dev/null +++ b/input/sdl/Makefile.am @@ -0,0 +1,4 @@ +noinst_LIBRARIES = libinputsdl.a +INCLUDES = -I$(top_srcdir)/includes -I$(top_srcdir)/main -Iinclude +libinputsdl_a_SOURCES = \ +event.c key.c mouse.c diff --git a/input/sdl/Makefile.in b/input/sdl/Makefile.in new file mode 100644 index 00000000..5961801a --- /dev/null +++ b/input/sdl/Makefile.in @@ -0,0 +1,299 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +CFLAGS = @CFLAGS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +NASM = @NASM@ +NASMFLAGS = @NASMFLAGS@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_LIBS = @SDL_LIBS@ +VERSION = @VERSION@ + +noinst_LIBRARIES = libinputsdl.a +INCLUDES = -I$(top_srcdir)/includes -I$(top_srcdir)/main -Iinclude +libinputsdl_a_SOURCES = event.c key.c mouse.c + +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../../conf.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I../.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +libinputsdl_a_LIBADD = +libinputsdl_a_OBJECTS = event.o key.o mouse.o +AR = ar +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +DEP_FILES = .deps/event.P .deps/key.P .deps/mouse.P +SOURCES = $(libinputsdl_a_SOURCES) +OBJECTS = $(libinputsdl_a_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu input/sdl/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +libinputsdl.a: $(libinputsdl_a_OBJECTS) $(libinputsdl_a_DEPENDENCIES) + -rm -f libinputsdl.a + $(AR) cru libinputsdl.a $(libinputsdl_a_OBJECTS) $(libinputsdl_a_LIBADD) + $(RANLIB) libinputsdl.a + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = input/sdl + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu input/sdl/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile $(LIBRARIES) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ + mostlyclean-tags mostlyclean-depend mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \ + clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-noinstLIBRARIES distclean-compile \ + distclean-tags distclean-depend distclean-generic \ + clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/input/sdl/event.c b/input/sdl/event.c new file mode 100644 index 00000000..15c72690 --- /dev/null +++ b/input/sdl/event.c @@ -0,0 +1,54 @@ +// SDL Event related stuff + +#include +#include +#include + +#include + +extern void key_handler(SDL_KeyboardEvent *event); +//added on 10/17/98 by Hans de Goede for mouse functionality +extern void mouse_button_handler(SDL_MouseButtonEvent *mbe); +extern void mouse_motion_handler(SDL_MouseMotionEvent *mme); +//end this section addition - Hans + +static int initialised=0; + +void event_poll() +{ + SDL_Event event; + while (SDL_PollEvent(&event)) + { +// if( (event.type == SDL_KEYEVENT) { +//added/changed on 10/17/98 by Hans de Goede for mouse functionality +//-killed- if( (event.type == SDL_KEYDOWN) || (event.type == SDL_KEYUP) ) { + switch(event.type) + { + case SDL_KEYDOWN: + case SDL_KEYUP: + key_handler((SDL_KeyboardEvent *)&event); + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + mouse_button_handler((SDL_MouseButtonEvent *)&event); + break; + case SDL_MOUSEMOTION: + mouse_motion_handler((SDL_MouseMotionEvent *)&event); + break; +//-killed- return; +//end this section addition/change - Hans + case SDL_QUIT: { +// void quit_request(); +// quit_request(); + } break; + } + } +} + +int event_init() +{ + // We should now be active and responding to events. + initialised = 1; + + return 0; +} diff --git a/input/sdl/include/event.h b/input/sdl/include/event.h new file mode 100644 index 00000000..1aeaedbd --- /dev/null +++ b/input/sdl/include/event.h @@ -0,0 +1,9 @@ +// Event header file + +#ifndef _EVENT_H +#define _EVENT_H + +int event_init(); +void event_poll(); + +#endif diff --git a/input/sdl/include/key.h b/input/sdl/include/key.h new file mode 100644 index 00000000..8974cc84 --- /dev/null +++ b/input/sdl/include/key.h @@ -0,0 +1,271 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/input/sdl/include/key.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:29:59 $ + * + * Header for keyboard functions + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:01 donut + * Import of d1x 1.37 source. + * + * Revision 1.19 1994/10/24 13:58:12 john + * Hacked in support for pause key onto code 0x61. + * + * Revision 1.18 1994/10/21 15:17:10 john + * Added KEY_PRINT_SCREEN + * + * Revision 1.17 1994/08/31 12:22:13 john + * Added KEY_DEBUGGED + * + * Revision 1.16 1994/08/24 18:53:50 john + * Made Cyberman read like normal mouse; added dpmi module; moved + * mouse from assembly to c. Made mouse buttons return time_down. + * + * Revision 1.15 1994/08/18 14:56:16 john + * *** empty log message *** + * + * Revision 1.14 1994/08/08 10:43:24 john + * Recorded when a key was pressed for key_inkey_time. + * + * Revision 1.13 1994/06/17 17:17:28 john + * Added keyd_time_last_key_was_pressed or something like that. + * + * Revision 1.12 1994/04/29 12:14:19 john + * Locked all memory used during interrupts so that program + * won't hang when using virtual memory. + * + * Revision 1.11 1994/02/17 15:57:14 john + * Changed key libary to C. + * + * Revision 1.10 1994/01/31 08:34:09 john + * Fixed reversed lshift/rshift keys. + * + * Revision 1.9 1994/01/18 10:58:17 john + * *** empty log message *** + * + * Revision 1.8 1993/10/16 19:24:43 matt + * Added new function key_clear_times() & key_clear_counts() + * + * Revision 1.7 1993/10/15 10:17:09 john + * added keyd_last_key_pressed and released for use with recorder. + * + * Revision 1.6 1993/10/06 16:20:37 john + * fixed down arrow bug + * + * Revision 1.5 1993/10/04 13:26:42 john + * changed the #defines for scan codes. + * + * Revision 1.4 1993/09/28 11:35:20 john + * added key_peekkey + * + * Revision 1.3 1993/09/20 18:36:43 john + * *** empty log message *** + * + * Revision 1.1 1993/07/10 13:10:39 matt + * Initial revision + * + * + */ + +#ifndef _KEY_H +#define _KEY_H + +#include "fix.h" +#include "pstypes.h" +#include // For 'toupper' + +//========================================================================== +// This installs the int9 vector and initializes the keyboard in buffered +// ASCII mode. key_close simply undoes that. +extern void key_init(); +extern void key_close(); + +//========================================================================== +// These are configuration parameters to setup how the buffer works. +// set keyd_buffer_type to 0 for no key buffering. +// set it to 1 and it will buffer scancodes. +extern unsigned char keyd_buffer_type; +extern unsigned char keyd_repeat; // 1=allow repeating, 0=dont allow repeat + +// keyd_editor_mode... 0=game mode, 1=editor mode. +// Editor mode makes key_down_time always return 0 if modifiers are down. +extern unsigned char keyd_editor_mode; + +// Time in seconds when last key was pressed... +extern volatile int keyd_time_when_last_pressed; + +//========================================================================== +// These are the "buffered" keypress routines. Use them by setting the +// "keyd_buffer_type" variable. + +extern void key_flush(); // Clears the 256 char buffer +extern int key_checkch(); // Returns 1 if a char is waiting +extern int key_getch(); // Gets key if one waiting other waits for one. +extern int key_inkey(); // Gets key if one, other returns 0. +extern int key_inkey_time(fix *time); // Same as inkey, but returns the time the key was pressed down. +extern int key_peekkey(); // Same as inkey, but doesn't remove key from buffer. + +extern unsigned char key_to_ascii(int keycode ); +extern char *key_name(int keycode); // Convert keycode to the name of the key + +extern void key_debug(); // Does an INT3 + +//========================================================================== +// These are the unbuffered routines. Index by the keyboard scancode. + +// Set to 1 if the key is currently down, else 0 +extern volatile unsigned char keyd_pressed[]; +extern volatile unsigned char keyd_last_pressed; +extern volatile unsigned char keyd_last_released; + +// Returns the seconds this key has been down since last call. +extern fix key_down_time(int scancode); + +// Returns number of times key has went from up to down since last call. +extern unsigned int key_down_count(int scancode); + +// Returns number of times key has went from down to up since last call. +extern unsigned int key_up_count(int scancode); + +// Clears the times & counts used by the above functions +// Took out... use key_flush(); +//void key_clear_times(); +//void key_clear_counts(); + +extern char * key_text[256]; + +#define KEY_SHIFTED 0x100 +#define KEY_ALTED 0x200 +#define KEY_CTRLED 0x400 +#define KEY_DEBUGGED 0x800 + +#define KEY_0 0x0B +#define KEY_1 0x02 +#define KEY_2 0x03 +#define KEY_3 0x04 +#define KEY_4 0x05 +#define KEY_5 0x06 +#define KEY_6 0x07 +#define KEY_7 0x08 +#define KEY_8 0x09 +#define KEY_9 0x0A + +#define KEY_A 0x1E +#define KEY_B 0x30 +#define KEY_C 0x2E +#define KEY_D 0x20 +#define KEY_E 0x12 +#define KEY_F 0x21 +#define KEY_G 0x22 +#define KEY_H 0x23 +#define KEY_I 0x17 +#define KEY_J 0x24 +#define KEY_K 0x25 +#define KEY_L 0x26 +#define KEY_M 0x32 +#define KEY_N 0x31 +#define KEY_O 0x18 +#define KEY_P 0x19 +#define KEY_Q 0x10 +#define KEY_R 0x13 +#define KEY_S 0x1F +#define KEY_T 0x14 +#define KEY_U 0x16 +#define KEY_V 0x2F +#define KEY_W 0x11 +#define KEY_X 0x2D +#define KEY_Y 0x15 +#define KEY_Z 0x2C + +#define KEY_MINUS 0x0C +#define KEY_EQUAL 0x0D +#define KEY_DIVIDE 0x35 +#define KEY_SLASH 0x2B +#define KEY_COMMA 0x33 +#define KEY_PERIOD 0x34 +#define KEY_SEMICOL 0x27 + +#define KEY_LBRACKET 0x1A +#define KEY_RBRACKET 0x1B + +#define KEY_RAPOSTRO 0x28 +#define KEY_LAPOSTRO 0x29 + +#define KEY_ESC 0x01 +#define KEY_ENTER 0x1C +#define KEY_BACKSP 0x0E +#define KEY_TAB 0x0F +#define KEY_SPACEBAR 0x39 + +#define KEY_NUMLOCK 0x45 +#define KEY_SCROLLOCK 0x46 +#define KEY_CAPSLOCK 0x3A + +#define KEY_LSHIFT 0x2A +#define KEY_RSHIFT 0x36 + +#define KEY_LALT 0x38 +#define KEY_RALT 0xB8 + +#define KEY_LCTRL 0x1D +#define KEY_RCTRL 0x9D + +#define KEY_F1 0x3B +#define KEY_F2 0x3C +#define KEY_F3 0x3D +#define KEY_F4 0x3E +#define KEY_F5 0x3F +#define KEY_F6 0x40 +#define KEY_F7 0x41 +#define KEY_F8 0x42 +#define KEY_F9 0x43 +#define KEY_F10 0x44 +#define KEY_F11 0x57 +#define KEY_F12 0x58 + +#define KEY_PAD0 0x52 +#define KEY_PAD1 0x4F +#define KEY_PAD2 0x50 +#define KEY_PAD3 0x51 +#define KEY_PAD4 0x4B +#define KEY_PAD5 0x4C +#define KEY_PAD6 0x4D +#define KEY_PAD7 0x47 +#define KEY_PAD8 0x48 +#define KEY_PAD9 0x49 +#define KEY_PADMINUS 0x4A +#define KEY_PADPLUS 0x4E +#define KEY_PADPERIOD 0x53 +#define KEY_PADDIVIDE 0xB5 +#define KEY_PADMULTIPLY 0x37 +#define KEY_PADENTER 0x9C + +#define KEY_INSERT 0xD2 +#define KEY_HOME 0xC7 +#define KEY_PAGEUP 0xC9 +#define KEY_DELETE 0xD3 +#define KEY_END 0xCF +#define KEY_PAGEDOWN 0xD1 +#define KEY_UP 0xC8 +#define KEY_DOWN 0xD0 +#define KEY_LEFT 0xCB +#define KEY_RIGHT 0xCD + +#define KEY_PRINT_SCREEN 0xB7 +#define KEY_PAUSE 0x61 + +#endif diff --git a/input/sdl/include/mouse.h b/input/sdl/include/mouse.h new file mode 100644 index 00000000..24518a8d --- /dev/null +++ b/input/sdl/include/mouse.h @@ -0,0 +1,127 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/input/sdl/include/mouse.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:29:59 $ + * + * Header for mouse functions + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:02 donut + * Import of d1x 1.37 source. + * + * Revision 1.10 1995/02/02 10:22:29 john + * Added cyberman init parameter. + * + * Revision 1.9 1994/11/18 23:18:09 john + * Changed some shorts to ints. + * + * Revision 1.8 1994/09/13 12:33:49 john + * Added functions to get down count and state. + * + * Revision 1.7 1994/08/29 20:52:20 john + * Added better cyberman support; also, joystick calibration + * value return funcctiionn, + * + * Revision 1.6 1994/08/24 17:54:35 john + * *** empty log message *** + * + * Revision 1.5 1994/08/24 17:51:43 john + * Added transparent cyberman support + * + * Revision 1.4 1993/07/27 09:32:22 john + * *** empty log message *** + * + * Revision 1.3 1993/07/26 10:46:44 john + * added definition for mouse_set_pos + * + * Revision 1.2 1993/07/22 13:07:59 john + * added header for mousesetlimts + * + * Revision 1.1 1993/07/10 13:10:40 matt + * Initial revision + * + * + */ + +#ifndef MOUSE_H +#define MOUSE_H + +#include "pstypes.h" +#include "fix.h" + +#define MOUSE_MAX_BUTTONS 8 + +#define MB_LEFT 0 +#define MB_RIGHT 1 +#define MB_MIDDLE 2 +#define MB_Z_UP 3 +#define MB_Z_DOWN 4 +#define MB_PITCH_BACKWARD 5 +#define MB_PITCH_FORWARD 6 +#define MB_BANK_LEFT 7 +#define MB_BANK_RIGHT 8 +#define MB_HEAD_LEFT 9 +#define MB_HEAD_RIGHT 10 + +#define MOUSE_LBTN 1 +#define MOUSE_RBTN 2 +#define MOUSE_MBTN 4 + +#undef NOMOUSE +#ifndef NOMOUSE + +//======================================================================== +// Check for mouse driver, reset driver if installed. returns number of +// buttons if driver is present. + +extern int mouse_set_limits( int x1, int y1, int x2, int y2 ); +extern void mouse_flush(); // clears all mice events... + +//======================================================================== +extern void mouse_get_pos( int *x, int *y); +extern void mouse_get_delta( int *dx, int *dy ); +extern int mouse_get_btns(); +extern void mouse_set_pos( int x, int y); +extern void mouse_get_cyberman_pos( int *x, int *y ); + +// Returns how long this button has been down since last call. +extern fix mouse_button_down_time(int button); + +// Returns how many times this button has went down since last call. +extern int mouse_button_down_count(int button); + +// Returns 1 if this button is currently down +extern int mouse_button_state(int button); + +#else +// 'Neutered' functions... :-) +#define mouse_init(a) -1 +#define mouse_set_limits(a,b,c,d) -1 +#define mouse_flush() +#define mouse_close() +#define mouse_get_pos(a,b) +#define mouse_get_delta(a,b) +#define mouse_get_btns() 0 +#define mouse_set_pos(a,b) +#define mouse_get_cyberman_pos(a,b) +#define mouse_button_down_time(a) 0 +#define mouse_button_down_count(a) 0 +#define mouse_button_state(a) 0 + +#endif + +#endif + diff --git a/input/sdl/key.c b/input/sdl/key.c new file mode 100644 index 00000000..9eb590c5 --- /dev/null +++ b/input/sdl/key.c @@ -0,0 +1,616 @@ +// SDL keyboard input support + +#include +#include +#include + +#include + +#include "event.h" +#include "error.h" +#include "key.h" +#include "timer.h" + +//added on 9/3/98 by Matt Mueller to free some cpu instead of hogging during menus and such +#include "d_delay.h" +//end this section addition - Matt Mueller + +#define KEY_BUFFER_SIZE 16 + +static unsigned char Installed = 0; + +//-------- Variable accessed by outside functions --------- +unsigned char keyd_buffer_type; // 0=No buffer, 1=buffer ASCII, 2=buffer scans +unsigned char keyd_repeat; +unsigned char keyd_editor_mode; +volatile unsigned char keyd_last_pressed; +volatile unsigned char keyd_last_released; +volatile unsigned char keyd_pressed[256]; +volatile int keyd_time_when_last_pressed; + +typedef struct Key_info { + ubyte state; // state of key 1 == down, 0 == up + ubyte last_state; // previous state of key + int counter; // incremented each time key is down in handler + fix timewentdown; // simple counter incremented each time in interrupt and key is down + fix timehelddown; // counter to tell how long key is down -- gets reset to 0 by key routines + ubyte downcount; // number of key counts key was down + ubyte upcount; // number of times key was released +} Key_info; + +typedef struct keyboard { + unsigned short keybuffer[KEY_BUFFER_SIZE]; + Key_info keys[256]; + fix time_pressed[KEY_BUFFER_SIZE]; + unsigned int keyhead, keytail; +} keyboard; + +static keyboard key_data; + +typedef struct key_props { + char *key_text; + unsigned char ascii_value; + unsigned char shifted_ascii_value; + SDLKey sym; +} key_props; + +key_props key_properties[256] = { +{ "", 255, 255, -1 }, +{ "ESC", 255, 255, SDLK_ESCAPE }, +{ "1", '1', '!', SDLK_1 }, +{ "2", '2', '@', SDLK_2 }, +{ "3", '3', '#', SDLK_3 }, +{ "4", '4', '$', SDLK_4 }, +{ "5", '5', '%', SDLK_5 }, +{ "6", '6', '^', SDLK_6 }, +{ "7", '7', '&', SDLK_7 }, +{ "8", '8', '*', SDLK_8 }, +{ "9", '9', '(', SDLK_9 }, +{ "0", '0', ')', SDLK_0 }, +{ "-", '-', '_', SDLK_MINUS }, +{ "=", '=', '+', SDLK_EQUALS }, +{ "BSPC", 255, 255, SDLK_BACKSPACE }, +{ "TAB", 255, 255, SDLK_TAB }, +{ "Q", 'q', 'Q', SDLK_q }, +{ "W", 'w', 'W', SDLK_w }, +{ "E", 'e', 'E', SDLK_e }, +{ "R", 'r', 'R', SDLK_r }, +{ "T", 't', 'T', SDLK_t }, +{ "Y", 'y', 'Y', SDLK_y }, +{ "U", 'u', 'U', SDLK_u }, +{ "I", 'i', 'I', SDLK_i }, +{ "O", 'o', 'O', SDLK_o }, +{ "P", 'p', 'P', SDLK_p }, +{ "[", '[', '{', SDLK_LEFTBRACKET }, +{ "]", ']', '}', SDLK_RIGHTBRACKET }, +//edited 06/08/99 Matt Mueller - set to correct key_text +{ "ƒ", 255, 255, SDLK_RETURN }, +//end edit -MM +{ "LCTRL", 255, 255, SDLK_LCTRL }, +{ "A", 'a', 'A', SDLK_a }, +{ "S", 's', 'S', SDLK_s }, +{ "D", 'd', 'D', SDLK_d }, +{ "F", 'f', 'F', SDLK_f }, +{ "G", 'g', 'G', SDLK_g }, +{ "H", 'h', 'H', SDLK_h }, +{ "J", 'j', 'J', SDLK_j }, +{ "K", 'k', 'K', SDLK_k }, +{ "L", 'l', 'L', SDLK_l }, +//edited 06/08/99 Matt Mueller - set to correct sym +{ ";", ';', ':', SDLK_SEMICOLON }, +//end edit -MM +{ "'", '\'', '"', SDLK_QUOTE }, +//edited 06/08/99 Matt Mueller - set to correct sym +{ "`", '`', '~', SDLK_BACKQUOTE }, +//end edit -MM +{ "LSHFT", 255, 255, SDLK_LSHIFT }, +{ "\\", '\\', '|', SDLK_BACKSLASH }, +{ "Z", 'z', 'Z', SDLK_z }, +{ "X", 'x', 'X', SDLK_x }, +{ "C", 'c', 'C', SDLK_c }, +{ "V", 'v', 'V', SDLK_v }, +{ "B", 'b', 'B', SDLK_b }, +{ "N", 'n', 'N', SDLK_n }, +{ "M", 'm', 'M', SDLK_m }, +//edited 06/08/99 Matt Mueller - set to correct syms +{ ",", ',', '<', SDLK_COMMA }, +{ ".", '.', '>', SDLK_PERIOD }, +{ "/", '/', '?', SDLK_SLASH }, +//end edit -MM +{ "RSHFT", 255, 255, SDLK_RSHIFT }, +{ "PAD*", '*', 255, SDLK_KP_MULTIPLY }, +{ "LALT", 255, 255, SDLK_LALT }, +{ "SPC", ' ', ' ', SDLK_SPACE }, +{ "CPSLK", 255, 255, SDLK_CAPSLOCK }, +{ "F1", 255, 255, SDLK_F1 }, +{ "F2", 255, 255, SDLK_F2 }, +{ "F3", 255, 255, SDLK_F3 }, +{ "F4", 255, 255, SDLK_F4 }, +{ "F5", 255, 255, SDLK_F5 }, +{ "F6", 255, 255, SDLK_F6 }, +{ "F7", 255, 255, SDLK_F7 }, +{ "F8", 255, 255, SDLK_F8 }, +{ "F9", 255, 255, SDLK_F9 }, +{ "F10", 255, 255, SDLK_F10 }, +{ "NMLCK", 255, 255, SDLK_NUMLOCK }, +{ "SCLK", 255, 255, SDLK_SCROLLOCK }, +{ "PAD7", 255, 255, SDLK_KP7 }, +{ "PAD8", 255, 255, SDLK_KP8 }, +{ "PAD9", 255, 255, SDLK_KP9 }, +{ "PAD-", 255, 255, SDLK_KP_MINUS }, +{ "PAD4", 255, 255, SDLK_KP4 }, +{ "PAD5", 255, 255, SDLK_KP5 }, +{ "PAD6", 255, 255, SDLK_KP6 }, +{ "PAD+", 255, 255, SDLK_KP_PLUS }, +{ "PAD1", 255, 255, SDLK_KP1 }, +{ "PAD2", 255, 255, SDLK_KP2 }, +{ "PAD3", 255, 255, SDLK_KP3 }, +{ "PAD0", 255, 255, SDLK_KP0 }, +{ "PAD.", 255, 255, SDLK_KP_PERIOD }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "F11", 255, 255, SDLK_F11 }, +{ "F12", 255, 255, SDLK_F12 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +//edited 06/08/99 Matt Mueller - add pause ability +{ "PAUSE", 255, 255, SDLK_PAUSE }, +//end edit -MM +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +//edited 06/08/99 Matt Mueller - set to correct key_text +{ "PADƒ", 255, 255, SDLK_KP_ENTER }, +//end edit -MM +//edited 06/08/99 Matt Mueller - set to correct sym +{ "RCTRL", 255, 255, SDLK_RCTRL }, +//end edit -MM +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "PAD/", 255, 255, SDLK_KP_DIVIDE }, +{ "", 255, 255, -1 }, +//edited 06/08/99 Matt Mueller - add printscreen ability +{ "PRSCR", 255, 255, SDLK_PRINT }, +//end edit -MM +{ "RALT", 255, 255, SDLK_RALT }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "HOME", 255, 255, SDLK_HOME }, +//edited 06/08/99 Matt Mueller - set to correct key_text +{ "UP", 255, 255, SDLK_UP }, +//end edit -MM +{ "PGUP", 255, 255, SDLK_PAGEUP }, +{ "", 255, 255, -1 }, +//edited 06/08/99 Matt Mueller - set to correct key_text +{ "LEFT", 255, 255, SDLK_LEFT }, +//end edit -MM +{ "", 255, 255, -1 }, +//edited 06/08/99 Matt Mueller - set to correct key_text +{ "RIGHT", 255, 255, SDLK_RIGHT }, +//end edit -MM +{ "", 255, 255, -1 }, +//edited 06/08/99 Matt Mueller - set to correct key_text +{ "END", 255, 255, SDLK_END }, +//end edit -MM +{ "DOWN", 255, 255, SDLK_DOWN }, +{ "PGDN", 255, 255, SDLK_PAGEDOWN }, +{ "INS", 255, 255, SDLK_INSERT }, +{ "DEL", 255, 255, SDLK_DELETE }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +{ "", 255, 255, -1 }, +}; + +char *key_text[256]; + +void key_buid_key_text(void) +{ +} + +unsigned char key_to_ascii(int keycode ) +{ + int shifted; + + shifted = keycode & KEY_SHIFTED; + keycode &= 0xFF; + + if (shifted) + return key_properties[keycode].shifted_ascii_value; + else + return key_properties[keycode].ascii_value; +} + +void key_handler(SDL_KeyboardEvent *event) +{ + ubyte state; + int i, keycode, event_key, key_state; + Key_info *key; + unsigned char temp; + + event_key = event->keysym.sym; + + key_state = (event->state == SDL_PRESSED); // !(wInfo & KF_UP); + //===================================================== + //Here a translation from win keycodes to mac keycodes! + //===================================================== + + for (i = 255; i >= 0; i--) { + + keycode = i; + key = &(key_data.keys[keycode]); + if (key_properties[i].sym == event_key) + state = key_state; + else + state = key->last_state; + + if ( key->last_state == state ) { + if (state) { + key->counter++; + keyd_last_pressed = keycode; + keyd_time_when_last_pressed = timer_get_fixed_seconds(); + } + } else { + if (state) { + keyd_last_pressed = keycode; + keyd_pressed[keycode] = 1; + key->downcount += state; + key->state = 1; + key->timewentdown = keyd_time_when_last_pressed = timer_get_fixed_seconds(); + key->counter++; + } else { + keyd_pressed[keycode] = 0; + keyd_last_released = keycode; + key->upcount += key->state; + key->state = 0; + key->counter = 0; + key->timehelddown += timer_get_fixed_seconds() - key->timewentdown; + } + } + if ( (state && !key->last_state) || (state && key->last_state && (key->counter > 30) && (key->counter & 0x01)) ) { + if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT]) + keycode |= KEY_SHIFTED; + if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT]) + keycode |= KEY_ALTED; + if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL]) + keycode |= KEY_CTRLED; + if ( keyd_pressed[KEY_DELETE] ) + keycode |= KEY_DEBUGGED; + temp = key_data.keytail+1; + if ( temp >= KEY_BUFFER_SIZE ) temp=0; + if (temp!=key_data.keyhead) { + key_data.keybuffer[key_data.keytail] = keycode; + key_data.time_pressed[key_data.keytail] = keyd_time_when_last_pressed; + key_data.keytail = temp; + } + } + key->last_state = state; + } +} + +void key_close() +{ + Installed = 0; +} + +void key_init() +{ + int i; + + if (Installed) return; + + Installed=1; + + keyd_time_when_last_pressed = timer_get_fixed_seconds(); + keyd_buffer_type = 1; + keyd_repeat = 1; + + for(i=0; i<256; i++) + key_text[i] = key_properties[i].key_text; + + // Clear the keyboard array + key_flush(); + atexit(key_close); +} + +void key_flush() +{ + int i; + fix curtime; + + if (!Installed) + key_init(); + + key_data.keyhead = key_data.keytail = 0; + + //Clear the keyboard buffer + for (i=0; i= KEY_BUFFER_SIZE ) n=0; + return n; +} + +int key_checkch() +{ + int is_one_waiting = 0; + event_poll(); + if (key_data.keytail!=key_data.keyhead) + is_one_waiting = 1; + return is_one_waiting; +} + +int key_inkey() +{ + int key = 0; + if (!Installed) + key_init(); + event_poll(); + if (key_data.keytail!=key_data.keyhead) { + key = key_data.keybuffer[key_data.keyhead]; + key_data.keyhead = add_one(key_data.keyhead); + } +//added 9/3/98 by Matt Mueller to free cpu time instead of hogging during menus and such + else d_delay(1); +//end addition - Matt Mueller + + return key; +} + +int key_inkey_time(fix * time) +{ + int key = 0; + + if (!Installed) + key_init(); + event_poll(); + if (key_data.keytail!=key_data.keyhead) { + key = key_data.keybuffer[key_data.keyhead]; + *time = key_data.time_pressed[key_data.keyhead]; + key_data.keyhead = add_one(key_data.keyhead); + } + return key; +} + +int key_peekkey() +{ + int key = 0; + event_poll(); + if (key_data.keytail!=key_data.keyhead) + key = key_data.keybuffer[key_data.keyhead]; + + return key; +} + +int key_getch() +{ + int dummy=0; + + if (!Installed) + return 0; +// return getch(); + + while (!key_checkch()) + dummy++; + return key_inkey(); +} + +unsigned int key_get_shift_status() +{ + unsigned int shift_status = 0; + + if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT] ) + shift_status |= KEY_SHIFTED; + + if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT] ) + shift_status |= KEY_ALTED; + + if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL] ) + shift_status |= KEY_CTRLED; + +#ifndef NDEBUG + if (keyd_pressed[KEY_DELETE]) + shift_status |=KEY_DEBUGGED; +#endif + + return shift_status; +} + +// Returns the number of seconds this key has been down since last call. +fix key_down_time(int scancode) +{ + fix time_down, time; + + event_poll(); + if ((scancode<0)|| (scancode>255)) return 0; + + if (!keyd_pressed[scancode]) { + time_down = key_data.keys[scancode].timehelddown; + key_data.keys[scancode].timehelddown = 0; + } else { + time = timer_get_fixed_seconds(); + time_down = time - key_data.keys[scancode].timewentdown; + key_data.keys[scancode].timewentdown = time; + } + + return time_down; +} + +unsigned int key_down_count(int scancode) +{ + int n; + event_poll(); + if ((scancode<0)|| (scancode>255)) return 0; + + n = key_data.keys[scancode].downcount; + key_data.keys[scancode].downcount = 0; + + return n; +} + +unsigned int key_up_count(int scancode) +{ + int n; + event_poll(); + if ((scancode<0)|| (scancode>255)) return 0; + + n = key_data.keys[scancode].upcount; + key_data.keys[scancode].upcount = 0; + + return n; +} diff --git a/input/sdl/mouse.c b/input/sdl/mouse.c new file mode 100644 index 00000000..c0f01830 --- /dev/null +++ b/input/sdl/mouse.c @@ -0,0 +1,234 @@ +// SDL mouse driver. + +#include +#include +#include +#include "fix.h" +#include "timer.h" +#include "event.h" +#include "mouse.h" + +struct mousebutton { + ubyte pressed; + fix time_went_down; + fix time_held_down; + uint num_downs; + uint num_ups; +}; + +static struct mouseinfo { + struct mousebutton buttons[MOUSE_MAX_BUTTONS]; +//added on 10/17/98 by Hans de Goede for mouse functionality + int min_x, min_y; + int max_x, max_y; + int delta_x, delta_y; + int x,y; +//end this section addition - Hans +} Mouse; + +//added on 10/17/98 by Hans de Goede for mouse functionality +void d_mouse_init(void) +{ + memset(&Mouse,0,sizeof(Mouse)); +} + +//added/changed on 10/17/98 by Hans de Goede for mouse functionality +//void mouse_handler(SDL_MouseButtonEvent *mbe) +void mouse_button_handler(SDL_MouseButtonEvent *mbe) +{ + // to bad, SDL buttons use a different mapping as descent expects, + // this is atleast true and tested for the first three buttons + int button_remap[11] = { + MB_LEFT, + MB_MIDDLE, + MB_RIGHT, + MB_Z_UP, + MB_Z_DOWN, + MB_PITCH_BACKWARD, + MB_PITCH_FORWARD, + MB_BANK_LEFT, + MB_BANK_RIGHT, + MB_HEAD_LEFT, + MB_HEAD_RIGHT }; + + int button = button_remap[mbe->button - 1]; // -1 since SDL seems to start counting at 1 + + if (mbe->state == SDL_PRESSED) { +// Mouse.buttons[mbe->button].pressed = 1; +// Mouse.buttons[mbe->button].time_went_down = timer_get_fixed_seconds(); +// Mouse.buttons[mbe->button].num_downs++; + Mouse.buttons[button].pressed = 1; + Mouse.buttons[button].time_went_down = timer_get_fixed_seconds(); + Mouse.buttons[button].num_downs++; + } else { +// Mouse.buttons[mbe->button].pressed = 0; +// Mouse.buttons[mbe->button].time_held_down += timer_get_fixed_seconds() - Mouse.buttons[mbe->button].time_went_down; +// Mouse.buttons[mbe->button].num_ups++; + Mouse.buttons[button].pressed = 0; + Mouse.buttons[button].time_held_down += timer_get_fixed_seconds() - Mouse.buttons[mbe->button].time_went_down; + Mouse.buttons[button].num_ups++; +//end this section addition/change - Hans + } +} + +//added on 10/17/98 by Hans de Goede for mouse functionality +void mouse_motion_handler(SDL_MouseMotionEvent *mme) +{ + Mouse.delta_x += mme->xrel; + Mouse.delta_y += mme->yrel; + Mouse.x += mme->xrel; + Mouse.y += mme->yrel; + if (Mouse.x > Mouse.max_x) Mouse.x = Mouse.max_x; + else if (Mouse.x < Mouse.min_x) Mouse.x = Mouse.min_x; + if (Mouse.y > Mouse.max_y) Mouse.y = Mouse.max_y; + else if (Mouse.y < Mouse.min_y) Mouse.y = Mouse.min_y; +} +//end this section addition - Hans + + +int mouse_set_limits( int x1, int y1, int x2, int y2 ) +{ +//added on 10/17/98 by Hans de Goede for mouse functionality +//-killed- // Shrug... +//-killed- event_poll(); + Mouse.min_x = x1; + Mouse.min_y = y1; + Mouse.max_x = x2; + Mouse.max_y = y2; +//end this section addition - Hans + return 0; +} + +void mouse_flush() // clears all mice events... +{ + int i; + fix current_time; + + event_poll(); + + current_time = timer_get_fixed_seconds(); + for (i=0; i Mouse.max_x) Mouse.x = Mouse.max_x; + else if (Mouse.x < Mouse.min_x) Mouse.x = Mouse.min_x; + if (Mouse.y > Mouse.max_y) Mouse.y = Mouse.max_y; + else if (Mouse.y < Mouse.min_y) Mouse.y = Mouse.min_y; +//end this section change - Hans +} + +void mouse_get_cyberman_pos( int *x, int *y ) +{ + // Shrug... + event_poll(); +} + +// Returns how long this button has been down since last call. +fix mouse_button_down_time(int button) +{ + fix time_down, time; + + event_poll(); + + if (!Mouse.buttons[button].pressed) { + time_down = Mouse.buttons[button].time_held_down; + Mouse.buttons[button].time_held_down = 0; + } else { + time = timer_get_fixed_seconds(); + time_down = time - Mouse.buttons[button].time_held_down; + Mouse.buttons[button].time_held_down = time; + } + return time_down; +} + +// Returns how many times this button has went down since last call +int mouse_button_down_count(int button) +{ + int count; + + event_poll(); + + count = Mouse.buttons[button].num_downs; + Mouse.buttons[button].num_downs = 0; + + return count; +} + +// Returns 1 if this button is currently down +int mouse_button_state(int button) +{ + event_poll(); + return Mouse.buttons[button].pressed; +} + + diff --git a/install-sh b/install-sh new file mode 100644 index 00000000..e9de2384 --- /dev/null +++ b/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/libtool b/libtool new file mode 100644 index 00000000..c8782d26 --- /dev/null +++ b/libtool @@ -0,0 +1,4240 @@ +#! /bin/sh + +# libtool - Provide generalized library-building support services. +# Generated automatically by ltconfig (GNU libtool 1.3.3 (1.385.2.181 1999/07/02 15:49:11)) +# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh. +# +# Copyright (C) 1996-1999 Free Software Foundation, Inc. +# Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="sed -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi + +### BEGIN LIBTOOL CONFIG +# Libtool was configured as follows, on host nexus: +# +# CC="gcc" CFLAGS="-g -O2" CPPFLAGS="" \ +# LD="/usr/bin/ld" LDFLAGS="" LIBS="" \ +# NM="/usr/bin/nm -B" RANLIB="ranlib" LN_S="ln -s" \ +# DLLTOOL="" OBJDUMP="" AS="" \ +# ./ltconfig --cache-file=./config.cache --with-gcc --with-gnu-ld --no-verify ./ltmain.sh i686-pc-linux-gnu +# +# Compiler and other test output produced by ltconfig, useful for +# debugging ltconfig, is in ./config.log if it exists. + +# The version of ltconfig that generated this script. +LTCONFIG_VERSION="1.3.3" + +# Shell to use when invoking shell scripts. +SHELL="/bin/sh" + +# Whether or not to build shared libraries. +build_libtool_libs=yes + +# Whether or not to build static libraries. +build_old_libs=yes + +# Whether or not to optimize for fast installation. +fast_install=yes + +# The host system. +host_alias=i686-pc-linux-gnu +host=i686-pc-linux-gnu + +# An echo program that does not interpret backslashes. +echo="echo" + +# The archiver. +AR="ar" + +# The default C compiler. +CC="gcc" + +# The linker used to build libraries. +LD="/usr/bin/ld" + +# Whether we need hard or soft links. +LN_S="ln -s" + +# A BSD-compatible nm program. +NM="/usr/bin/nm -B" + +# Used on cygwin: DLL creation program. +DLLTOOL="dlltool" + +# Used on cygwin: object dumper. +OBJDUMP="objdump" + +# Used on cygwin: assembler. +AS="as" + +# The name of the directory that contains temporary libtool files. +objdir=.libs + +# How to create reloadable object files. +reload_flag=" -r" +reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs" + +# How to pass a linker flag through the compiler. +wl="-Wl," + +# Object file suffix (normally "o"). +objext="o" + +# Old archive suffix (normally "a"). +libext="a" + +# Executable file suffix (normally ""). +exeext="" + +# Additional compiler flags for building library objects. +pic_flag=" -fPIC" + +# Does compiler simultaneously support -c and -o options? +compiler_c_o="yes" + +# Can we write directly to a .lo ? +compiler_o_lo="yes" + +# Must we lock files when doing compilation ? +need_locks="no" + +# Do we need the lib prefix for modules? +need_lib_prefix=no + +# Do we need a version for libraries? +need_version=no + +# Whether dlopen is supported. +dlopen=unknown + +# Whether dlopen of programs is supported. +dlopen_self=unknown + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=unknown + +# Compiler flag to prevent dynamic linking. +link_static_flag="-static" + +# Compiler flag to turn off builtin functions. +no_builtin_flag=" -fno-builtin -fno-rtti -fno-exceptions" + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec="\${wl}--export-dynamic" + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec="\${wl}--whole-archive\$convenience \${wl}--no-whole-archive" + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec="" + +# Library versioning type. +version_type=linux + +# Format of library name prefix. +libname_spec="lib\$name" + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec="\${libname}\${release}.so\$versuffix \${libname}\${release}.so\$major \$libname.so" + +# The coded name of the library, if different from the real name. +soname_spec="\${libname}\${release}.so\$major" + +# Commands used to build and install an old-style archive. +RANLIB="ranlib" +old_archive_cmds="\$AR cru \$oldlib\$oldobjs~\$RANLIB \$oldlib" +old_postinstall_cmds="\$RANLIB \$oldlib~chmod 644 \$oldlib" +old_postuninstall_cmds="" + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds="" + +# Commands used to build and install a shared archive. +archive_cmds="\$CC -shared \$libobjs \$deplibs \$linkopts \${wl}-soname \$wl\$soname -o \$lib" +archive_expsym_cmds="\$CC -shared \$libobjs \$deplibs \$linkopts \${wl}-soname \$wl\$soname \${wl}-retain-symbols-file \$wl\$export_symbols -o \$lib" +postinstall_cmds="" +postuninstall_cmds="" + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )" + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd="/usr/bin/file" + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag="" + +# Flag that forces no undefined symbols. +no_undefined_flag="" + +# Commands used to finish a libtool library installation in a directory. +finish_cmds="PATH=\\\"\\\$PATH:/sbin\\\" ldconfig -n \$libdir" + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval="" + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe="sed -n -e 's/^.*[ ]\\([ABCDGISTW]\\)[ ][ ]*\\(\\)\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 \\2\\3 \\3/p'" + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl="sed -n -e 's/^. .* \\(.*\\)\$/extern char \\1;/p'" + +# This is the shared library runtime path variable. +runpath_var=LD_RUN_PATH + +# This is the shared library path variable. +shlibpath_var=LD_LIBRARY_PATH + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=no + +# How to hardcode a shared library path into an executable. +hardcode_action=immediate + +# Flag to hardcode $libdir into a binary during linking. +# This must work even if $libdir does not exist. +hardcode_libdir_flag_spec="\${wl}--rpath \${wl}\$libdir" +if test -f /etc/debian_version; then +# Debian policy mandates that rpaths should not be encoded into a binary +# so it is overridden. + hardcode_libdir_flag_spec=" -D_DEBIAN_PATCHED_LIBTOOL_ " +fi + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator="" + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=no + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=no + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=unsupported + +# Compile-time system search path for libraries +sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec="/lib /usr/lib" + +# Fix the shell variable $srcfile for the compiler. +fix_srcfile_path="" + +# Set to yes if exported symbols are required. +always_export_symbols=no + +# The commands to list exported symbols. +export_symbols_cmds="\$NM \$libobjs \$convenience | \$global_symbol_pipe | sed 's/.* //' | sort | uniq > \$export_symbols" + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms="_GLOBAL_OFFSET_TABLE_" + +# Symbols that must always be exported. +include_expsyms="" + +### END LIBTOOL CONFIG + +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun ltconfig. +# +# Copyright (C) 1996-1999 Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Check that we have a working $echo. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell, and then maybe $echo will work. + exec $SHELL "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + echo "$modename: not configured to build any kind of library" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" + +# Parse our command line options once, thoroughly. +while test $# -gt 0 +do + arg="$1" + shift + + case "$arg" in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case "$prev" in + execute_dlfiles) + eval "$prev=\"\$$prev \$arg\"" + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case "$arg" in + --help) + show_help=yes + ;; + + --version) + echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" + exit 0 + ;; + + --config) + sed -e '1,/^### BEGIN LIBTOOL CONFIG/d' -e '/^### END LIBTOOL CONFIG/,$d' $0 + exit 0 + ;; + + --debug) + echo "$progname: enabling shell trace mode" + set -x + ;; + + --dry-run | -n) + run=: + ;; + + --features) + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + exit 0 + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --quiet | --silent) + show=: + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 +fi + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + case "$nonopt" in + *cc | *++ | gcc* | *-gcc*) + mode=link + for arg + do + case "$arg" in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx | *strace | *truss) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case "$mode" in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + lastarg= + srcfile="$nonopt" + suppress_output= + + user_target=no + for arg + do + # Accept any command-line options. + case "$arg" in + -o) + if test "$user_target" != "no"; then + $echo "$modename: you cannot specify \`-o' more than once" 1>&2 + exit 1 + fi + user_target=next + ;; + + -static) + build_old_libs=yes + continue + ;; + esac + + case "$user_target" in + next) + # The next one is the -o target name + user_target=yes + continue + ;; + yes) + # We got the output file + user_target=set + libobj="$arg" + continue + ;; + esac + + # Accept the current argument as the source file. + lastarg="$srcfile" + srcfile="$arg" + + # Aesthetically quote the previous argument. + + # Backslashify any backslashes, double quotes, and dollar signs. + # These are the only characters that are still specially + # interpreted inside of double-quoted scrings. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly in scan + # sets, so we specify it separately. + case "$lastarg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + lastarg="\"$lastarg\"" + ;; + esac + + # Add the previous argument to base_compile. + if test -z "$base_compile"; then + base_compile="$lastarg" + else + base_compile="$base_compile $lastarg" + fi + done + + case "$user_target" in + set) + ;; + no) + # Get the name of the library object. + libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + ;; + *) + $echo "$modename: you must specify a target with \`-o'" 1>&2 + exit 1 + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + xform='[cCFSfmso]' + case "$libobj" in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case "$libobj" in + *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; + *) + $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 + exit 1 + ;; + esac + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $libobj" + else + removelist="$libobj" + fi + + $run $rm $removelist + trap "$run $rm $removelist; exit 1" 1 2 15 + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\..*$%%'`.${objext} + lockfile="$output_obj.lock" + removelist="$removelist $output_obj $lockfile" + trap "$run $rm $removelist; exit 1" 1 2 15 + else + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until ln "$0" "$lockfile" 2>/dev/null; do + $show "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + echo "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + echo $srcfile > "$lockfile" + fi + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + # All platforms use -DPIC, to notify preprocessed assembler code. + command="$base_compile $pic_flag -DPIC $srcfile" + if test "$build_old_libs" = yes; then + lo_libobj="$libobj" + dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$libobj"; then + dir="$objdir" + else + dir="$dir/$objdir" + fi + libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` + + if test -d "$dir"; then + $show "$rm $libobj" + $run $rm $libobj + else + $show "$mkdir $dir" + $run $mkdir $dir + status=$? + if test $status -ne 0 && test ! -d $dir; then + exit $status + fi + fi + fi + if test "$compiler_o_lo" = yes; then + output_obj="$libobj" + command="$command -o $output_obj" + elif test "$compiler_c_o" = yes; then + output_obj="$obj" + command="$command -o $output_obj" + fi + + $run $rm "$output_obj" + $show "$command" + if $run eval "$command"; then : + else + test -n "$output_obj" && $run $rm $removelist + exit 1 + fi + + if test "$need_locks" = warn && + test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then + echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + + # Just move the object if needed, then go on to compile the next one + if test x"$output_obj" != x"$libobj"; then + $show "$mv $output_obj $libobj" + if $run $mv $output_obj $libobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # If we have no pic_flag, then copy the object into place and finish. + if test -z "$pic_flag" && test "$build_old_libs" = yes; then + # Rename the .lo from within objdir to obj + if test -f $obj; then + $show $rm $obj + $run $rm $obj + fi + + $show "$mv $libobj $obj" + if $run $mv $libobj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + + # Now arrange that obj and lo_libobj become the same file + $show "$LN_S $obj $lo_libobj" + if $run $LN_S $obj $lo_libobj; then + exit 0 + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Allow error messages only from the first compilation. + suppress_output=' >/dev/null 2>&1' + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + command="$base_compile $srcfile" + if test "$compiler_c_o" = yes; then + command="$command -o $obj" + output_obj="$obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + command="$command$suppress_output" + $run $rm "$output_obj" + $show "$command" + if $run eval "$command"; then : + else + $run $rm $removelist + exit 1 + fi + + if test "$need_locks" = warn && + test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then + echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + + # Just move the object if needed + if test x"$output_obj" != x"$obj"; then + $show "$mv $output_obj $obj" + if $run $mv $output_obj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Create an invalid libtool object if no PIC, so that we do not + # accidentally link it into a program. + if test "$build_libtool_libs" != yes; then + $show "echo timestamp > $libobj" + $run eval "echo timestamp > \$libobj" || exit $? + else + # Move the .lo from within objdir + $show "$mv $libobj $lo_libobj" + if $run $mv $libobj $lo_libobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + fi + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + $rm "$lockfile" + fi + + exit 0 + ;; + + # libtool link mode + link) + modename="$modename: link" + C_compiler="$CC" # save it, to compile generated C sources + CC="$nonopt" + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-os2*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invokation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + + # This is a source program that is used to create dlls on Windows + # Don't remove nor modify the starting and closing comments +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ + # This is a source program that is used to create import libraries + # on Windows for dlls which lack them. Don't remove nor modify the + # starting and closing comments +# /* impgen.c starts here */ +# /* Copyright (C) 1999 Free Software Foundation, Inc. +# +# This file is part of GNU libtool. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public 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 /* for printf() */ +# #include /* for open(), lseek(), read() */ +# #include /* for O_RDONLY, O_BINARY */ +# #include /* for strdup() */ +# +# static unsigned int +# pe_get16 (fd, offset) +# int fd; +# int offset; +# { +# unsigned char b[2]; +# lseek (fd, offset, SEEK_SET); +# read (fd, b, 2); +# return b[0] + (b[1]<<8); +# } +# +# static unsigned int +# pe_get32 (fd, offset) +# int fd; +# int offset; +# { +# unsigned char b[4]; +# lseek (fd, offset, SEEK_SET); +# read (fd, b, 4); +# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); +# } +# +# static unsigned int +# pe_as32 (ptr) +# void *ptr; +# { +# unsigned char *b = ptr; +# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); +# } +# +# int +# main (argc, argv) +# int argc; +# char *argv[]; +# { +# int dll; +# unsigned long pe_header_offset, opthdr_ofs, num_entries, i; +# unsigned long export_rva, export_size, nsections, secptr, expptr; +# unsigned long name_rvas, nexp; +# unsigned char *expdata, *erva; +# char *filename, *dll_name; +# +# filename = argv[1]; +# +# dll = open(filename, O_RDONLY|O_BINARY); +# if (!dll) +# return 1; +# +# dll_name = filename; +# +# for (i=0; filename[i]; i++) +# if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') +# dll_name = filename + i +1; +# +# pe_header_offset = pe_get32 (dll, 0x3c); +# opthdr_ofs = pe_header_offset + 4 + 20; +# num_entries = pe_get32 (dll, opthdr_ofs + 92); +# +# if (num_entries < 1) /* no exports */ +# return 1; +# +# export_rva = pe_get32 (dll, opthdr_ofs + 96); +# export_size = pe_get32 (dll, opthdr_ofs + 100); +# nsections = pe_get16 (dll, pe_header_offset + 4 +2); +# secptr = (pe_header_offset + 4 + 20 + +# pe_get16 (dll, pe_header_offset + 4 + 16)); +# +# expptr = 0; +# for (i = 0; i < nsections; i++) +# { +# char sname[8]; +# unsigned long secptr1 = secptr + 40 * i; +# unsigned long vaddr = pe_get32 (dll, secptr1 + 12); +# unsigned long vsize = pe_get32 (dll, secptr1 + 16); +# unsigned long fptr = pe_get32 (dll, secptr1 + 20); +# lseek(dll, secptr1, SEEK_SET); +# read(dll, sname, 8); +# if (vaddr <= export_rva && vaddr+vsize > export_rva) +# { +# expptr = fptr + (export_rva - vaddr); +# if (export_rva + export_size > vaddr + vsize) +# export_size = vsize - (export_rva - vaddr); +# break; +# } +# } +# +# expdata = (unsigned char*)malloc(export_size); +# lseek (dll, expptr, SEEK_SET); +# read (dll, expdata, export_size); +# erva = expdata - export_rva; +# +# nexp = pe_as32 (expdata+24); +# name_rvas = pe_as32 (expdata+32); +# +# printf ("EXPORTS\n"); +# for (i = 0; i&2 + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + else + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + fi + build_libtool_libs=no + build_old_libs=yes + prefer_static_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test $# -gt 0; do + arg="$1" + shift + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case "$prev" in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case "$prev" in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + preload=yes + fi + case "$arg" in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + ;; + esac + ;; + expsyms) + export_symbols="$arg" + if test ! -f "$arg"; then + $echo "$modename: symbol file \`$arg' does not exist" + exit 1 + fi + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case "$arg" in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit 1 + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi + + prevarg="$arg" + + case "$arg" in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: not more than one -exported-symbols argument allowed" + exit 1 + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` + # We need an absolute path. + case "$dir" in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + absdir="$dir" + fi + dir="$absdir" + ;; + esac + case " $deplibs " in + *" $arg "*) ;; + *) deplibs="$deplibs $arg";; + esac + case " $lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir";; + esac + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-os2*) + dllsearchdir=`cd "$dir" && pwd || echo "$dir"` + case ":$dllsearchpath:" in + ::) dllsearchpath="$dllsearchdir";; + *":$dllsearchdir:"*) ;; + *) dllsearchpath="$dllsearchpath:$dllsearchdir";; + esac + ;; + esac + ;; + + -l*) + if test "$arg" = "-lc"; then + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*) + # These systems don't actually have c library (as such) + continue + ;; + esac + elif test "$arg" = "-lm"; then + case "$host" in + *-*-cygwin* | *-*-beos*) + # These systems don't actually have math library (as such) + continue + ;; + esac + fi + deplibs="$deplibs $arg" + ;; + + -module) + module=yes + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -o) prev=output ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` + # We need an absolute path. + case "$dir" in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit 1 + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -static) + # If we have no pic_flag, then this is the same as -all-static. + if test -z "$pic_flag" && test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + ;; + + *.o | *.obj | *.a | *.lib) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A library object. + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + if test "$build_libtool_libs" = yes && test "$dlopen" = yes; then + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"` + prev= + fi + libobjs="$libobjs $arg" + ;; + + *.la) + # A libtool-controlled library. + + dlname= + libdir= + library_names= + old_library= + + # Check to see that this really is a libtool archive. + if (sed -e '2q' $arg | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2 + exit 1 + fi + + # If the library was installed with an old release of libtool, + # it will not redefine variable installed. + installed=yes + + # Read the .la file + # If there is no directory component, then add one. + case "$arg" in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$arg'" 1>&2 + exit 1 + fi + + # Find the relevant object directory and library name. + name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'` + + if test "X$installed" = Xyes; then + dir="$libdir" + else + dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$arg"; then + dir="$objdir" + else + dir="$dir/$objdir" + fi + fi + + if test -n "$dependency_libs"; then + # Extract -R and -L from dependency_libs + temp_deplibs= + for deplib in $dependency_libs; do + case "$deplib" in + -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + case " $rpath $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + -L*) case "$compile_command $temp_deplibs " in + *" $deplib "*) ;; + *) temp_deplibs="$temp_deplibs $deplib";; + esac + temp_dir=`$echo "X$deplib" | $Xsed -e 's/^-L//'` + case " $lib_search_path " in + *" $temp_dir "*) ;; + *) lib_search_path="$lib_search_path $temp_dir";; + esac + ;; + *) temp_deplibs="$temp_deplibs $deplib";; + esac + done + dependency_libs="$temp_deplibs" + fi + + if test -z "$libdir"; then + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $dir/$old_library" + old_convenience="$old_convenience $dir/$old_library" + deplibs="$deplibs$dependency_libs" + compile_command="$compile_command $dir/$old_library$dependency_libs" + finalize_command="$finalize_command $dir/$old_library$dependency_libs" + continue + fi + + # This library was specified with -dlopen. + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + if test -z "$dlname" || test "$dlopen" != yes || test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking statically, + # we need to preload. + prev=dlprefiles + else + # We should not create a dependency on this library, but we + # may need any libraries it requires. + compile_command="$compile_command$dependency_libs" + finalize_command="$finalize_command$dependency_libs" + prev= + continue + fi + fi + + # The library was specified with -dlpreopen. + if test "$prev" = dlprefiles; then + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + dlprefiles="$dlprefiles $dir/$old_library" + else + dlprefiles="$dlprefiles $dir/$linklib" + fi + prev= + fi + + if test -n "$library_names" && + { test "$prefer_static_libs" = no || test -z "$old_library"; }; then + link_against_libtool_libs="$link_against_libtool_libs $arg" + if test -n "$shlibpath_var"; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *) temp_rpath="$temp_rpath $dir" ;; + esac + fi + + # We need an absolute path. + case "$dir" in + [\\/] | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + absdir="$dir" + fi + ;; + esac + + # This is the magic to use -rpath. + # Skip directories that are in the system default run-time + # search path, unless they have been requested with -R. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + + lib_linked=yes + case "$hardcode_action" in + immediate | unsupported) + if test "$hardcode_direct" = no; then + compile_command="$compile_command $dir/$linklib" + deplibs="$deplibs $dir/$linklib" + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-os2*) + dllsearchdir=`cd "$dir" && pwd || echo "$dir"` + if test -n "$dllsearchpath"; then + dllsearchpath="$dllsearchpath:$dllsearchdir" + else + dllsearchpath="$dllsearchdir" + fi + ;; + esac + elif test "$hardcode_minus_L" = no; then + case "$host" in + *-*-sunos*) + compile_shlibpath="$compile_shlibpath$dir:" + ;; + esac + case "$compile_command " in + *" -L$dir "*) ;; + *) compile_command="$compile_command -L$dir";; + esac + compile_command="$compile_command -l$name" + deplibs="$deplibs -L$dir -l$name" + elif test "$hardcode_shlibpath_var" = no; then + case ":$compile_shlibpath:" in + *":$dir:"*) ;; + *) compile_shlibpath="$compile_shlibpath$dir:";; + esac + compile_command="$compile_command -l$name" + deplibs="$deplibs -l$name" + else + lib_linked=no + fi + ;; + + relink) + if test "$hardcode_direct" = yes; then + compile_command="$compile_command $absdir/$linklib" + deplibs="$deplibs $absdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + case "$compile_command " in + *" -L$absdir "*) ;; + *) compile_command="$compile_command -L$absdir";; + esac + compile_command="$compile_command -l$name" + deplibs="$deplibs -L$absdir -l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case ":$compile_shlibpath:" in + *":$absdir:"*) ;; + *) compile_shlibpath="$compile_shlibpath$absdir:";; + esac + compile_command="$compile_command -l$name" + deplibs="$deplibs -l$name" + else + lib_linked=no + fi + ;; + + *) + lib_linked=no + ;; + esac + + if test "$lib_linked" != yes; then + $echo "$modename: configuration error: unsupported hardcode properties" + exit 1 + fi + + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + finalize_command="$finalize_command $libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + case "$finalize_command " in + *" -L$libdir "*) ;; + *) finalize_command="$finalize_command -L$libdir";; + esac + finalize_command="$finalize_command -l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case ":$finalize_shlibpath:" in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:";; + esac + finalize_command="$finalize_command -l$name" + else + # We cannot seem to hardcode it, guess we'll fake it. + case "$finalize_command " in + *" -L$dir "*) ;; + *) finalize_command="$finalize_command -L$libdir";; + esac + finalize_command="$finalize_command -l$name" + fi + else + # Transform directly to old archives if we don't build new libraries. + if test -n "$pic_flag" && test -z "$old_library"; then + $echo "$modename: cannot find static library for \`$arg'" 1>&2 + exit 1 + fi + + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_command="$compile_command $dir/$linklib" + finalize_command="$finalize_command $dir/$linklib" + else + case "$compile_command " in + *" -L$dir "*) ;; + *) compile_command="$compile_command -L$dir";; + esac + compile_command="$compile_command -l$name" + case "$finalize_command " in + *" -L$dir "*) ;; + *) finalize_command="$finalize_command -L$dir";; + esac + finalize_command="$finalize_command -l$name" + fi + fi + + # Add in any libraries that this one depends upon. + compile_command="$compile_command$dependency_libs" + finalize_command="$finalize_command$dependency_libs" + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + ;; + esac + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` + libobjs_save="$libobjs" + + case "$output" in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + *.a | *.lib) + if test -n "$link_against_libtool_libs"; then + $echo "$modename: error: cannot link libtool libraries into archives" 1>&2 + exit 1 + fi + + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 + fi + + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 + fi + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + ;; + + *.la) + # Make sure we only generate libraries of the form `libNAME.la'. + case "$outputname" in + lib*) + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval libname=\"$libname_spec\" + ;; + *) + if test "$module" = no; then + $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + eval libname=\"$libname_spec\" + else + libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + fi + ;; + esac + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + + if test -n "$objs"; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1 + exit 1 + fi + + # How the heck are we supposed to write a wrapper for a shared library? + if test -n "$link_against_libtool_libs"; then + $echo "$modename: error: cannot link shared libraries into libtool libraries" 1>&2 + exit 1 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for libtool libraries" 1>&2 + fi + + set dummy $rpath + if test $# -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + libext=al + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + dependency_libs="$deplibs" + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 + fi + else + + # Parse the version information argument. + IFS="${IFS= }"; save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + IFS="$save_ifs" + + if test -n "$8"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + current="$2" + revision="$3" + age="$4" + + # Check that each of the things are valid numbers. + case "$current" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case "$revision" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case "$age" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + if test $age -gt $current; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case "$version_type" in + none) ;; + + irix) + major=`expr $current - $age + 1` + versuffix="$major.$revision" + verstring="sgi$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test $loop != 0; do + iface=`expr $revision - $loop` + loop=`expr $loop - 1` + verstring="sgi$major.$iface:$verstring" + done + ;; + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + major=`expr $current - $age` + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test $loop != 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current"; + ;; + + windows) + # Like Linux, but with '-' rather than '.', since we only + # want one extension on Windows 95. + major=`expr $current - $age` + versuffix="-$major-$age-$revision" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + verstring="0.0" + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + dependency_libs="$deplibs" + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*) + # these systems don't actually have a c library (as such)! + ;; + *) + # Add libc to deplibs on all other systems. + deplibs="$deplibs -lc" + ;; + esac + fi + + # Create the output directory, or remove our outputs if we need to. + if test -d $output_objdir; then + $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*" + $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.* + else + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + status=$? + if test $status -ne 0 && test ! -d $output_objdir; then + exit $status + fi + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + if test "$build_libtool_libs" = yes; then + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case "$deplibs_check_method" in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behaviour. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $rm conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null \ + | grep " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | sed 's/.* -> //'` + case "$potliblink" in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ + | sed 10q \ + | egrep "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + echo "*** Warning: This library needs some functionality provided by $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ + -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' | + grep . >/dev/null; then + echo + if test "X$deplibs_check_method" = "Xnone"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + echo "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + # Get the real and link names of the library. + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + lib="$output_objdir/$realname" + for link + do + linknames="$linknames $link" + done + + # Ensure that we have .o objects for linkers which dislike .lo + # (e.g. aix) incase we are running --disable-static + for obj in $libobjs; do + oldobj=`$echo "X$obj" | $Xsed -e "$lo2o"` + if test ! -f $oldobj; then + $show "${LN_S} $obj $oldobj" + $run ${LN_S} $obj $oldobj || exit $? + fi + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + eval cmds=\"$export_symbols_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + if test -n "$export_symbols_regex"; then + $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' + fi + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${outputname}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test $status -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + for xlib in $convenience; do + # Extract the objects. + case "$xlib" in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test $status -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` + done + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linkopts="$linkopts $flag" + fi + + # Do each of the archive commands. + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval cmds=\"$archive_expsym_cmds\" + else + eval cmds=\"$archive_cmds\" + fi + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + *.lo | *.o | *.obj) + if test -n "$link_against_libtool_libs"; then + $echo "$modename: error: cannot link libtool libraries into objects" 1>&2 + exit 1 + fi + + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 + fi + + case "$output" in + *.lo) + if test -n "$objs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit 1 + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e "$lo2o"` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${obj}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test $status -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + for xlib in $convenience; do + # Extract the objects. + case "$xlib" in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test $status -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` + done + fi + fi + + # Create the old-style object. + reload_objs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" + + output="$obj" + eval cmds=\"$reload_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit 0 + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + $show "echo timestamp > $libobj" + $run eval "echo timestamp > $libobj" || exit $? + exit 0 + fi + + if test -n "$pic_flag"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + eval cmds=\"$reload_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + else + # Just create a symlink. + $show $rm $libobj + $run $rm $libobj + $show "$LN_S $obj $libobj" + $run $LN_S $obj $libobj || exit $? + fi + + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit 0 + ;; + + # Anything else should be a program. + *) + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 + fi + + if test "$preload" = yes; then + if test "$dlopen" = unknown && test "$dlopen_self" = unknown && + test "$dlopen_self_static" = unknown; then + $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." + fi + fi + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$compile_rpath " in + *" $libdir "*) ;; + *) compile_rpath="$compile_rpath $libdir" ;; + esac + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + + # Create the binary in the object directory, then wrap it. + if test ! -d $output_objdir; then + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + status=$? + if test $status -ne 0 && test ! -d $output_objdir; then + exit $status + fi + fi + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + dlsyms= + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$dlsyms"; then + case "$dlsyms" in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$dlsyms" + + test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define lt_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$output.exp" + $run $rm $export_symbols + $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + else + $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' + $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`echo "$arg" | sed -e 's%^.*/%%'` + $run eval 'echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $mv "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then + : + else + grep -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$dlsyms" + fi + + $echo >> "$output_objdir/$dlsyms" "\ + +#undef lt_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{\ +" + + sed -n -e 's/^: \([^ ]*\) $/ {\"\1\", (lt_ptr_t) 0},/p' \ + -e 's/^. \([^ ]*\) \([^ ]*\)$/ {"\2", (lt_ptr_t) \&\2},/p' \ + < "$nlist" >> "$output_objdir/$dlsyms" + + $echo >> "$output_objdir/$dlsyms" "\ + {0, (lt_ptr_t) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + case "$host" in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $C_compiler -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $C_compiler -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + ;; + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit 1 + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + $show "$link_command" + $run eval "$link_command" + status=$? + + # Delete the generated files. + if test -n "$dlsyms"; then + $show "$rm $output_objdir/${outputname}S.${objext}" + $run $rm "$output_objdir/${outputname}S.${objext}" + fi + + exit $status + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case "$dir" in + [\\/]* | [A-Za-z]:[\\/]*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 + $echo "$modename: \`$output' will be relinked during installation" 1>&2 + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname + + $show "$link_command" + $run eval "$link_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $echo for shipping. + if test "X$echo" = "X$SHELL $0 --fallback-echo"; then + case "$0" in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; + *) qecho="$SHELL `pwd`/$0 --fallback-echo";; + esac + qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) output=`echo $output|sed 's,.exe$,,'` ;; + esac + $rm $output + trap "$rm $output; exit 1" 1 2 15 + + $echo > $output "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test \"\${CDPATH+set}\" = set; then CDPATH=; export CDPATH; fi + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variable: + link_against_libtool_libs='$link_against_libtool_libs' +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + echo=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$echo works! + : + else + # Restart under the correct shell, and then maybe \$echo will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + echo >> $output "\ + program=lt-'$outputname' + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $mkdir \"\$progdir\" + else + $rm \"\$progdir/\$file\" + fi" + + echo >> $output "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if (cd \"\$thisdir\" && eval \$relink_command); then : + else + $rm \"\$progdir/\$file\" + exit 1 + fi + fi + + $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $rm \"\$progdir/\$program\"; + $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $rm \"\$progdir/\$file\" + fi" + else + echo >> $output "\ + program='$outputname$exeext' + progdir=\"\$thisdir/$objdir\" +" + fi + + echo >> $output "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $echo >> $output "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + *-*-cygwin* | *-*-mingw | *-*-os2*) + # win32 systems need to use the prog path for dll + # lookup to work + $echo >> $output "\ + exec \$progdir\\\\\$program \${1+\"\$@\"} +" + ;; + *) + $echo >> $output "\ + # Export the path to the program. + PATH=\"\$progdir:\$PATH\" + export PATH + + exec \$program \${1+\"\$@\"} +" + ;; + esac + $echo >> $output "\ + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit 1 + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" + chmod +x $output + fi + exit 0 + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$objs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP` + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test $status -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + # Add in members from convenience archives. + for xlib in $addlibs; do + # Extract the objects. + case "$xlib" in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test $status -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` + done + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + eval cmds=\"$old_archive_from_new_cmds\" + else + # Ensure that we have .o objects in place incase we decided + # not to build a shared library, and have fallen back to building + # static libs even though --disable-static was passed! + for oldobj in $oldobjs; do + if test ! -f $oldobj; then + obj=`$echo "X$oldobj" | $Xsed -e "$o2lo"` + $show "${LN_S} $obj $oldobj" + $run ${LN_S} $obj $oldobj || exit $? + fi + done + + eval cmds=\"$old_archive_cmds\" + fi + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$generated"; then + $show "${rm}r$generated" + $run ${rm}r$generated + fi + + # Now create the libtool archive. + case "$output" in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + $show "creating $output" + + if test -n "$xrpath"; then + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + done + dependency_libs="$temp_xrpath $dependency_libs" + fi + + # Only create the output if not a dry run. + if test -z "$run"; then + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + fi + $rm $output + $echo > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$dlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Directory that this library needs to be installed in: +libdir='$install_libdir'\ +" + done + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" + $run eval "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" || exit $? + ;; + esac + exit 0 + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg="$nonopt" + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest="$arg" + continue + fi + + case "$arg" in + -d) isdir=yes ;; + -f) prev="-f" ;; + -g) prev="-g" ;; + -m) prev="-m" ;; + -o) prev="-o" ;; + -s) + stripme=" -s" + continue + ;; + -*) ;; + + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest="$arg" + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit 1 + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test $# -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + fi + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case "$file" in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case "$file" in + *.a | *.lib) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + library_names= + old_library= + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/" + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$realname $destdir/$realname" + $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $? + + if test $# -gt 0; then + # Delete the old symlinks, and create new ones. + for linkname + do + if test "$linkname" != "$realname"; then + $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" + fi + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + eval cmds=\"$postinstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + instname="$dir/$name"i + $show "$install_prog $instname $destdir/$name" + $run eval "$install_prog $instname $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case "$destfile" in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` + ;; + *.o | *.obj) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit 0 + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Do a test to see if this is really a libtool program. + if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + link_against_libtool_libs= + relink_command= + + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Check the variables that should have been set. + if test -z "$link_against_libtool_libs"; then + $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2 + exit 1 + fi + + finalize=yes + for lib in $link_against_libtool_libs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case "$lib" in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`" + if test -n "$libdir" && test ! -f "$libfile"; then + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + if test "$finalize" = yes && test -z "$run"; then + tmpdir="/tmp" + test -n "$TMPDIR" && tmpdir="$TMPDIR" + tmpdir="$tmpdir/libtool-$$" + if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then : + else + $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 + continue + fi + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + ${rm}r "$tmpdir" + continue + fi + file="$outputname" + else + $echo "$modename: warning: cannot relink \`$file'" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + $show "$install_prog$stripme $file $destfile" + $run eval "$install_prog\$stripme \$file \$destfile" || exit $? + test -n "$outputname" && ${rm}r "$tmpdir" + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + # Do each command in the postinstall commands. + eval cmds=\"$old_postinstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec $SHELL $0 --finish$current_libdirs + exit 1 + fi + + exit 0 + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + eval cmds=\"$finish_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || admincmds="$admincmds + $cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + test "$show" = : && exit 0 + + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + echo " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use \`-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + echo " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + echo " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + echo "See any operating system documentation about shared libraries for" + echo "more information, such as the ld(1) and ld.so(8) manual pages." + echo "----------------------------------------------------------------------" + exit 0 + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit 1 + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test ! -f "$file"; then + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + dir= + case "$file" in + *.la) + # Check to see that this really is a libtool archive. + if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit 1 + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case "$file" in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + + # Restore saved enviroment variables + if test "${save_LC_ALL+set}" = set; then + LC_ALL="$save_LC_ALL"; export LC_ALL + fi + if test "${save_LANG+set}" = set; then + LANG="$save_LANG"; export LANG + fi + + # Now actually exec the command. + eval "exec \$cmd$args" + + $echo "$modename: cannot exec \$cmd$args" + exit 1 + else + # Display what would be done. + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + $echo "$cmd$args" + exit 0 + fi + ;; + + # libtool uninstall mode + uninstall) + modename="$modename: uninstall" + rm="$nonopt" + files= + + for arg + do + case "$arg" in + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + rmfiles="$file" + + case "$name" in + *.la) + # Possibly a libtool archive, so verify it. + if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $dir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library" + + $show "$rm $rmfiles" + $run $rm $rmfiles + + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + eval cmds=\"$postuninstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + eval cmds=\"$old_postuninstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + + # FIXME: should reinstall the best remaining shared library. + fi + ;; + + *.lo) + if test "$build_old_libs" = yes; then + oldobj=`$echo "X$name" | $Xsed -e "$lo2o"` + rmfiles="$rmfiles $dir/$oldobj" + fi + $show "$rm $rmfiles" + $run $rm $rmfiles + ;; + + *) + $show "$rm $rmfiles" + $run $rm $rmfiles + ;; + esac + done + exit 0 + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 + ;; + esac + + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 +fi # test -z "$show_help" + +# We need to display help for each of the modes. +case "$mode" in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + + --config show all configuration variables + --debug enable verbose shell tracing +-n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --version print version information + +MODE must be one of the following: + + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE." + exit 0 + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -static always build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + +uninstall) + $echo \ +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; +esac + +echo +$echo "Try \`$modename --help' for more information about other modes." + +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/ltconfig b/ltconfig new file mode 100644 index 00000000..5ce1abaa --- /dev/null +++ b/ltconfig @@ -0,0 +1,3022 @@ +#! /bin/sh + +# ltconfig - Create a system-specific libtool. +# Copyright (C) 1996-1999 Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A lot of this script is taken from autoconf-2.10. + +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} +echo=echo +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec "$SHELL" "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null`} + case X$UNAME in + *-DOS) PATH_SEPARATOR=';' ;; + *) PATH_SEPARATOR=':' ;; + esac +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi + +if test "X${echo_test_string+set}" != "Xset"; then + # find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string="`eval $cmd`") 2>/dev/null && + echo_test_string="`eval $cmd`" && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" != 'X\t' || + test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for dir in $PATH /usr/ucb; do + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running ltconfig again with it. + ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}" + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"} + else + # Try using printf. + echo='printf "%s\n"' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + # Cool, printf works + : + elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' && + test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL" + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL $0 --fallback-echo" + elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' && + test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + echo="$CONFIG_SHELL $0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "$0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# The name of this program. +progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'` + +# Constants: +PROGRAM=ltconfig +PACKAGE=libtool +VERSION=1.3.3 +TIMESTAMP=" (1.385.2.181 1999/07/02 15:49:11)" +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.c 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.c $LIBS 1>&5' +rm="rm -f" + +help="Try \`$progname --help' for more information." + +# Global variables: +default_ofile=libtool +can_build_shared=yes +enable_shared=yes +# All known linkers require a `.a' archive for static linking (except M$VC, +# which needs '.lib'). +enable_static=yes +enable_fast_install=yes +enable_dlopen=unknown +enable_win32_dll=no +ltmain= +silent= +srcdir= +ac_config_guess= +ac_config_sub= +host= +nonopt= +ofile="$default_ofile" +verify_host=yes +with_gcc=no +with_gnu_ld=no +need_locks=yes +ac_ext=c +objext=o +libext=a +exeext= +cache_file= + +old_AR="$AR" +old_CC="$CC" +old_CFLAGS="$CFLAGS" +old_CPPFLAGS="$CPPFLAGS" +old_LDFLAGS="$LDFLAGS" +old_LD="$LD" +old_LN_S="$LN_S" +old_LIBS="$LIBS" +old_NM="$NM" +old_RANLIB="$RANLIB" +old_DLLTOOL="$DLLTOOL" +old_OBJDUMP="$OBJDUMP" +old_AS="$AS" + +# Parse the command line options. +args= +prev= +for option +do + case "$option" in + -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + eval "$prev=\$option" + prev= + continue + fi + + case "$option" in + --help) cat <&2 + echo "$help" 1>&2 + exit 1 + ;; + + *) + if test -z "$ltmain"; then + ltmain="$option" + elif test -z "$host"; then +# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1 +# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then +# echo "$progname: warning \`$option' is not a valid host type" 1>&2 +# fi + host="$option" + else + echo "$progname: too many arguments" 1>&2 + echo "$help" 1>&2 + exit 1 + fi ;; + esac +done + +if test -z "$ltmain"; then + echo "$progname: you must specify a LTMAIN file" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + +if test ! -f "$ltmain"; then + echo "$progname: \`$ltmain' does not exist" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + +# Quote any args containing shell metacharacters. +ltconfig_args= +for arg +do + case "$arg" in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ltconfig_args="$ltconfig_args '$arg'" ;; + *) ltconfig_args="$ltconfig_args $arg" ;; + esac +done + +# A relevant subset of AC_INIT. + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 5 compiler messages saved in config.log +# 6 checking for... messages and results +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>>./config.log + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LANG+set}" = set; then LANG=C; export LANG; fi + +if test -n "$cache_file" && test -r "$cache_file"; then + echo "loading cache $cache_file within ltconfig" + . $cache_file +fi + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + +if test -z "$srcdir"; then + # Assume the source directory is the same one as the path to LTMAIN. + srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'` + test "$srcdir" = "$ltmain" && srcdir=. +fi + +trap "$rm conftest*; exit 1" 1 2 15 +if test "$verify_host" = yes; then + # Check for config.guess and config.sub. + ac_aux_dir= + for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/config.guess; then + ac_aux_dir=$ac_dir + break + fi + done + if test -z "$ac_aux_dir"; then + echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2 + echo "$help" 1>&2 + exit 1 + fi + ac_config_guess=$ac_aux_dir/config.guess + ac_config_sub=$ac_aux_dir/config.sub + + # Make sure we can run config.sub. + if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then : + else + echo "$progname: cannot run $ac_config_sub" 1>&2 + echo "$help" 1>&2 + exit 1 + fi + + echo $ac_n "checking host system type""... $ac_c" 1>&6 + + host_alias=$host + case "$host_alias" in + "") + if host_alias=`$SHELL $ac_config_guess`; then : + else + echo "$progname: cannot guess host type; you must specify one" 1>&2 + echo "$help" 1>&2 + exit 1 + fi ;; + esac + host=`$SHELL $ac_config_sub $host_alias` + echo "$ac_t$host" 1>&6 + + # Make sure the host verified. + test -z "$host" && exit 1 + +elif test -z "$host"; then + echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2 + echo "$help" 1>&2 + exit 1 +else + host_alias=$host +fi + +# Transform linux* to *-*-linux-gnu*, to support old configure scripts. +case "$host_os" in +linux-gnu*) ;; +linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` +esac + +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +case "$host_os" in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "${COLLECT_NAMES+set}" != set; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR cru $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +# Set a sane default for `AR'. +test -z "$AR" && AR=ar + +# Set a sane default for `OBJDUMP'. +test -z "$OBJDUMP" && OBJDUMP=objdump + +# If RANLIB is not set, then run the test. +if test "${RANLIB+set}" != "set"; then + result=no + + echo $ac_n "checking for ranlib... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then + RANLIB="ranlib" + result="ranlib" + break + fi + done + IFS="$save_ifs" + + echo "$ac_t$result" 1>&6 +fi + +if test -n "$RANLIB"; then + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" + old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" +fi + +# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin. +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$AS" && AS=as + +# Check to see if we are using GCC. +if test "$with_gcc" != yes || test -z "$CC"; then + # If CC is not set, then try to find GCC or a usable CC. + if test -z "$CC"; then + echo $ac_n "checking for gcc... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then + CC="gcc" + break + fi + done + IFS="$save_ifs" + + if test -n "$CC"; then + echo "$ac_t$CC" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + fi + + # Not "gcc", so try "cc", rejecting "/usr/ucb/cc". + if test -z "$CC"; then + echo $ac_n "checking for cc... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + cc_rejected=no + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/cc || test -f $dir/cc$ac_exeext; then + if test "$dir/cc" = "/usr/ucb/cc"; then + cc_rejected=yes + continue + fi + CC="cc" + break + fi + done + IFS="$save_ifs" + if test $cc_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same name, so the bogon will be chosen + # first if we set CC to just the name; use the full file name. + shift + set dummy "$dir/cc" "$@" + shift + CC="$@" + fi + fi + + if test -n "$CC"; then + echo "$ac_t$CC" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + + if test -z "$CC"; then + echo "$progname: error: no acceptable cc found in \$PATH" 1>&2 + exit 1 + fi + fi + + # Now see if the compiler is really GCC. + with_gcc=no + echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6 + echo "$progname:581: checking whether we are using GNU C" >&5 + + $rm conftest.c + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + with_gcc=yes + fi + $rm conftest.c + echo "$ac_t$with_gcc" 1>&6 +fi + +# Allow CC to be a program name with arguments. +set dummy $CC +compiler="$2" + +echo $ac_n "checking for object suffix... $ac_c" 1>&6 +$rm conftest* +echo 'int i = 1;' > conftest.c +echo "$progname:603: checking for object suffix" >& 5 +if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then + # Append any warnings to the config.log. + cat conftest.err 1>&5 + + for ac_file in conftest.*; do + case $ac_file in + *.c) ;; + *) objext=`echo $ac_file | sed -e s/conftest.//` ;; + esac + done +else + cat conftest.err 1>&5 + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 +fi +$rm conftest* +echo "$ac_t$objext" 1>&6 + +echo $ac_n "checking for executable suffix... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_exeext="no" + $rm conftest* + echo 'main () { return 0; }' > conftest.c + echo "$progname:629: checking for executable suffix" >& 5 + if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then + # Append any warnings to the config.log. + cat conftest.err 1>&5 + + for ac_file in conftest.*; do + case $ac_file in + *.c | *.err | *.$objext ) ;; + *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;; + esac + done + else + cat conftest.err 1>&5 + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + $rm conftest* +fi +if test "X$ac_cv_exeext" = Xno; then + exeext="" +else + exeext="$ac_cv_exeext" +fi +echo "$ac_t$ac_cv_exeext" 1>&6 + +echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6 +pic_flag= +special_shlib_compile_flags= +wl= +link_static_flag= +no_builtin_flag= + +if test "$with_gcc" = yes; then + wl='-Wl,' + link_static_flag='-static' + + case "$host_os" in + beos* | irix5* | irix6* | osf3* | osf4*) + # PIC is the default for these OSes. + ;; + aix*) + # Below there is a dirty hack to force normal static linking with -ldl + # The problem is because libdl dynamically linked with both libc and + # libC (AIX C++ library), which obviously doesn't included in libraries + # list by gcc. This cause undefined symbols with -static flags. + # This hack allows C programs to be linked with "-static -ldl", but + # we not sure about C++ programs. + link_static_flag="$link_static_flag ${wl}-lC" + ;; + cygwin* | mingw* | os2*) + # We can build DLLs from non-PIC. + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + pic_flag='-m68020 -resident32 -malways-restore-a4' + ;; + sysv4*MP*) + if test -d /usr/nec; then + pic_flag=-Kconform_pic + fi + ;; + *) + pic_flag='-fPIC' + ;; + esac +else + # PORTME Check for PIC flags for the system compiler. + case "$host_os" in + aix3* | aix4*) + # All AIX code is PIC. + link_static_flag='-bnso -bI:/lib/syscalls.exp' + ;; + + hpux9* | hpux10* | hpux11*) + # Is there a better link_static_flag that works with the bundled CC? + wl='-Wl,' + link_static_flag="${wl}-a ${wl}archive" + pic_flag='+Z' + ;; + + irix5* | irix6*) + wl='-Wl,' + link_static_flag='-non_shared' + # PIC (with -KPIC) is the default. + ;; + + cygwin* | mingw* | os2*) + # We can build DLLs from non-PIC. + ;; + + osf3* | osf4*) + # All OSF/1 code is PIC. + wl='-Wl,' + link_static_flag='-non_shared' + ;; + + sco3.2v5*) + pic_flag='-Kpic' + link_static_flag='-dn' + special_shlib_compile_flags='-belf' + ;; + + solaris*) + pic_flag='-KPIC' + link_static_flag='-Bstatic' + wl='-Wl,' + ;; + + sunos4*) + pic_flag='-PIC' + link_static_flag='-Bstatic' + wl='-Qoption ld ' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + pic_flag='-KPIC' + link_static_flag='-Bstatic' + wl='-Wl,' + ;; + + uts4*) + pic_flag='-pic' + link_static_flag='-Bstatic' + ;; + sysv4*MP*) + if test -d /usr/nec ;then + pic_flag='-Kconform_pic' + link_static_flag='-Bstatic' + fi + ;; + *) + can_build_shared=no + ;; + esac +fi + +if test -n "$pic_flag"; then + echo "$ac_t$pic_flag" 1>&6 + + # Check to make sure the pic_flag actually works. + echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6 + $rm conftest* + echo "int some_variable = 0;" > conftest.c + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $pic_flag -DPIC" + echo "$progname:776: checking if $compiler PIC flag $pic_flag works" >&5 + if { (eval echo $progname:777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then + # Append any warnings to the config.log. + cat conftest.err 1>&5 + + case "$host_os" in + hpux9* | hpux10* | hpux11*) + # On HP-UX, both CC and GCC only warn that PIC is supported... then they + # create non-PIC objects. So, if there were any warnings, we assume that + # PIC is not supported. + if test -s conftest.err; then + echo "$ac_t"no 1>&6 + can_build_shared=no + pic_flag= + else + echo "$ac_t"yes 1>&6 + pic_flag=" $pic_flag" + fi + ;; + *) + echo "$ac_t"yes 1>&6 + pic_flag=" $pic_flag" + ;; + esac + else + # Append any errors to the config.log. + cat conftest.err 1>&5 + can_build_shared=no + pic_flag= + echo "$ac_t"no 1>&6 + fi + CFLAGS="$save_CFLAGS" + $rm conftest* +else + echo "$ac_t"none 1>&6 +fi + +# Check to see if options -o and -c are simultaneously supported by compiler +echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6 +$rm -r conftest 2>/dev/null +mkdir conftest +cd conftest +$rm conftest* +echo "int some_variable = 0;" > conftest.c +mkdir out +# According to Tom Tromey, Ian Lance Taylor reported there are C compilers +# that will create temporary files in the current directory regardless of +# the output directory. Thus, making CWD read-only will cause this test +# to fail, enabling locking or at least warning the user not to do parallel +# builds. +chmod -w . +save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -o out/conftest2.o" +echo "$progname:829: checking if $compiler supports -c -o file.o" >&5 +if { (eval echo $progname:830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then + + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s out/conftest.err; then + echo "$ac_t"no 1>&6 + compiler_c_o=no + else + echo "$ac_t"yes 1>&6 + compiler_c_o=yes + fi +else + # Append any errors to the config.log. + cat out/conftest.err 1>&5 + compiler_c_o=no + echo "$ac_t"no 1>&6 +fi +CFLAGS="$save_CFLAGS" +chmod u+w . +$rm conftest* out/* +rmdir out +cd .. +rmdir conftest +$rm -r conftest 2>/dev/null + +if test x"$compiler_c_o" = x"yes"; then + # Check to see if we can write to a .lo + echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6 + $rm conftest* + echo "int some_variable = 0;" > conftest.c + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -c -o conftest.lo" + echo "$progname:862: checking if $compiler supports -c -o file.lo" >&5 +if { (eval echo $progname:863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then + + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + echo "$ac_t"no 1>&6 + compiler_o_lo=no + else + echo "$ac_t"yes 1>&6 + compiler_o_lo=yes + fi + else + # Append any errors to the config.log. + cat conftest.err 1>&5 + compiler_o_lo=no + echo "$ac_t"no 1>&6 + fi + CFLAGS="$save_CFLAGS" + $rm conftest* +else + compiler_o_lo=no +fi + +# Check to see if we can do hard links to lock some files if needed +hard_links="nottested" +if test "$compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6 + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + echo "$ac_t$hard_links" 1>&6 + $rm conftest* + if test "$hard_links" = no; then + echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2 + need_locks=warn + fi +else + need_locks=no +fi + +if test "$with_gcc" = yes; then + # Check to see if options -fno-rtti -fno-exceptions are supported by compiler + echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6 + $rm conftest* + echo "int some_variable = 0;" > conftest.c + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c" + echo "$progname:914: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 + if { (eval echo $progname:915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then + + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + echo "$ac_t"no 1>&6 + compiler_rtti_exceptions=no + else + echo "$ac_t"yes 1>&6 + compiler_rtti_exceptions=yes + fi + else + # Append any errors to the config.log. + cat conftest.err 1>&5 + compiler_rtti_exceptions=no + echo "$ac_t"no 1>&6 + fi + CFLAGS="$save_CFLAGS" + $rm conftest* + + if test "$compiler_rtti_exceptions" = "yes"; then + no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions' + else + no_builtin_flag=' -fno-builtin' + fi + +fi + +# Check for any special shared library compilation flags. +if test -n "$special_shlib_compile_flags"; then + echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2 + if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then : + else + echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2 + can_build_shared=no + fi +fi + +echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6 +$rm conftest* +echo 'main(){return(0);}' > conftest.c +save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS $link_static_flag" +echo "$progname:958: checking if $compiler static flag $link_static_flag works" >&5 +if { (eval echo $progname:959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + echo "$ac_t$link_static_flag" 1>&6 +else + echo "$ac_t"none 1>&6 + link_static_flag= +fi +LDFLAGS="$save_LDFLAGS" +$rm conftest* + +if test -z "$LN_S"; then + # Check to see if we can use ln -s, or we need hard links. + echo $ac_n "checking whether ln -s works... $ac_c" 1>&6 + $rm conftest.dat + if ln -s X conftest.dat 2>/dev/null; then + $rm conftest.dat + LN_S="ln -s" + else + LN_S=ln + fi + if test "$LN_S" = "ln -s"; then + echo "$ac_t"yes 1>&6 + else + echo "$ac_t"no 1>&6 + fi +fi + +# Make sure LD is an absolute path. +if test -z "$LD"; then + ac_prog=ld + if test "$with_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6 + echo "$progname:991: checking for ld used by GCC" >&5 + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. + [\\/]* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we are not using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac + elif test "$with_gnu_ld" = yes; then + echo $ac_n "checking for GNU ld... $ac_c" 1>&6 + echo "$progname:1015: checking for GNU ld" >&5 + else + echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 + echo "$progname:1018: checking for non-GNU ld" >&5 + fi + + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" + fi + + if test -n "$LD"; then + echo "$ac_t$LD" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + + if test -z "$LD"; then + echo "$progname: error: no acceptable ld found in \$PATH" 1>&2 + exit 1 + fi +fi + +# Check to see if it really is or is not GNU ld. +echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6 +# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + with_gnu_ld=yes +else + with_gnu_ld=no +fi +echo "$ac_t$with_gnu_ld" 1>&6 + +# See if the linker supports building shared libraries. +echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6 + +allow_undefined_flag= +no_undefined_flag= +need_lib_prefix=unknown +need_version=unknown +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +archive_cmds= +archive_expsym_cmds= +old_archive_from_new_cmds= +export_dynamic_flag_spec= +whole_archive_flag_spec= +thread_safe_flag_spec= +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no +hardcode_shlibpath_var=unsupported +runpath_var= +always_export_symbols=no +export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' +# include_expsyms should be a list of space-separated symbols to be *always* +# included in the symbol list +include_expsyms= +# exclude_expsyms can be an egrep regular expression of symbols to exclude +# it will be wrapped by ` (' and `)$', so one must not match beginning or +# end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', +# as well as any symbol that contains `d'. +exclude_expsyms="_GLOBAL_OFFSET_TABLE_" +# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out +# platforms (ab)use it in PIC code, but their linkers get confused if +# the symbol is explicitly referenced. Since portable code cannot +# rely on this symbol name, it's probably fine to never include it in +# preloaded symbol tables. + +case "$host_os" in +cygwin* | mingw*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$with_gcc" != yes; then + with_gnu_ld=no + fi + ;; + +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # See if GNU ld supports shared libraries. + case "$host_os" in + aix3* | aix4*) + # On AIX, the GNU linker is very broken + ld_shlibs=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + ;; + + amigaos*) + archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can use + # them. + ld_shlibs=no + ;; + + beos*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw*) + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + allow_undefined_flag=unsupported + always_export_symbols=yes + + # Extract the symbol export list from an `--export-all' def file, + # then regenerate the def file from the symbol export list, so that + # the compiled dll only exports the symbol export list. + export_symbols_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~ + test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~ + $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def $objdir/$soname-ltdll.$objext $libobjs $convenience~ + sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]* ; *//" < $objdir/$soname-def > $export_symbols' + + archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~ + _lt_hint=1; + for symbol in `cat $export_symbols`; do + echo " \$symbol @ \$_lt_hint ; " >> $objdir/$soname-def; + _lt_hint=`expr 1 + \$_lt_hint`; + done~ + test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~ + test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~ + $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~ + $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~ + $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~ + $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~ + $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts' + + old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a' + ;; + + netbsd*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib' + # can we support soname and/or expsyms with a.out? -oliva + fi + ;; + + solaris*) + if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = yes; then + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + case $host_os in + cygwin* | mingw*) + # dlltool doesn't understand --whole-archive et. al. + whole_archive_flag_spec= + ;; + *) + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + ;; + esac + fi +else + # PORTME fill in a description of your system's linker (not GNU ld) + case "$host_os" in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$with_gcc" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix4*) + hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib' + hardcode_libdir_separator=':' + if test "$with_gcc" = yes; then + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct=yes + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + shared_flag='-shared' + else + shared_flag='${wl}-bM:SRE' + hardcode_direct=yes + fi + allow_undefined_flag=' ${wl}-berok' + archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}' + archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}' + case "$host_os" in aix4.[01]|aix4.[01].*) + # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on + always_export_symbols=yes ;; + esac + ;; + + amigaos*) + archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # see comment about different semantics on the GNU ld section + ld_shlibs=no + ;; + + cygwin* | mingw*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib /OUT:$oldlib$oldobjs' + fix_srcfile_path='`cygpath -w $srcfile`' + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd*) + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9* | hpux10* | hpux11*) + case "$host_os" in + hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;; + *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;; + esac + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_minus_L=yes # Not in the search PATH, but as the default + # location of the library. + export_dynamic_flag_spec='${wl}-E' + ;; + + irix5* | irix6*) + if test "$with_gcc" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + else + archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts' # ELF + fi + hardcode_libdir_flag_spec='${wl}-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + openbsd*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def' + ;; + + osf3* | osf4*) + if test "$with_gcc" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + sco3.2v5*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ;; + + solaris*) + no_undefined_flag=' -z text' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case "$host_os" in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + # archive_cmds='$LD -G -z text -h $soname -o $lib$libobjs$deplibs' + archive_cmds='$LD -G -h $soname -o $lib$libobjs$deplibs' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + *) + ld_shlibs=no + ;; + esac +fi +echo "$ac_t$ld_shlibs" 1>&6 +test "$ld_shlibs" = no && can_build_shared=no + +if test -z "$NM"; then + echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6 + case "$NM" in + [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path. + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + NM="$ac_dir/nm -B" + break + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + NM="$ac_dir/nm -p" + break + else + NM=${NM="$ac_dir/nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + fi + fi + done + IFS="$ac_save_ifs" + test -z "$NM" && NM=nm + ;; + esac + echo "$ac_t$NM" 1>&6 +fi + +# Check for command to grab the raw symbol name followed by C symbol from nm. +echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6 + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform the above into a raw symbol and a C symbol. +symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" + +# Define system-specific variables. +case "$host_os" in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw*) + symcode='[ABCDGISTW]' + ;; +hpux*) # Its linker distinguishes data from code symbols + global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'" + ;; +irix*) + symcode='[BCDEGRST]' + ;; +solaris*) + symcode='[BDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then + symcode='[ABCDGISTW]' +fi + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Write the raw and C identifiers. + global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode\)[ ][ ]*\($ac_symprfx\)$sympat$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + $rm conftest* + cat > conftest.c <&5 + if { (eval echo $progname:1593: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then + # Now try to grab the symbols. + nlist=conftest.nm + if { echo "$progname:1596: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then + + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if egrep ' nm_test_var$' "$nlist" >/dev/null; then + if egrep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.c +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c' + + cat <> conftest.c +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{ +EOF + sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c + cat <<\EOF >> conftest.c + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$objext conftstm.$objext + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="conftstm.$objext" + CFLAGS="$CFLAGS$no_builtin_flag" + if { (eval echo $progname:1648: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + pipe_works=yes + else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + LIBS="$save_LIBS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + $rm conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + global_symbol_pipe= + fi +done +if test "$pipe_works" = yes; then + echo "${ac_t}ok" 1>&6 +else + echo "${ac_t}failed" 1>&6 +fi + +if test -z "$global_symbol_pipe"; then + global_symbol_to_cdecl= +fi + +# Check hardcoding attributes. +echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6 +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || \ + test -n "$runpath_var"; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$hardcode_shlibpath_var" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +echo "$ac_t$hardcode_action" 1>&6 + + +reload_flag= +reload_cmds='$LD$reload_flag -o $output$reload_objs' +echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6 +# PORTME Some linkers may need a different reload flag. +reload_flag='-r' +echo "$ac_t$reload_flag" 1>&6 +test -n "$reload_flag" && reload_flag=" $reload_flag" + +# PORTME Fill in your ld.so characteristics +library_names_spec= +libname_spec='lib$name' +soname_spec= +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +file_magic_cmd= +file_magic_test_file= +deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [regex]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given egrep regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. +echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6 +case "$host_os" in +aix3*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}.so$major' + ;; + +aix4*) + version_type=linux + # AIX has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + # We preserve .a as extension for shared libraries though AIX4.2 + # and later linker supports .so + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a' + shlibpath_var=LIBPATH + deplibs_check_method=pass_all + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}.so' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + deplibs_check_method=pass_all + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + +bsdi4*) + version_type=linux + library_names_spec='${libname}.so$major ${libname}.so' + soname_spec='${libname}.so' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + file_magic_cmd=/usr/bin/file + file_magic_test_file=/shlib/libc.so + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw*) + version_type=windows + need_version=no + need_lib_prefix=no + if test "$with_gcc" = yes; then + library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a' + else + library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib' + fi + dynamic_linker='Win32 ld.exe' + deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + file_magic_cmd='${OBJDUMP} -f' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd*) + objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` + version_type=freebsd-$objformat + case "$version_type" in + freebsd-elf*) + deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object' + file_magic_cmd=/usr/bin/file + file_magic_test_file=`echo /usr/lib/libc.so*` + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + deplibs_check_method=unknown + library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix' + need_version=yes + ;; + esac + finish_cmds='PATH="\$PATH:/sbin" OBJFORMAT="'"$objformat"'" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + case "$host_os" in + freebsd2* | freebsd3.[01]*) + shlibpath_overrides_runpath=yes + ;; + *) # from 3.2 on + shlibpath_overrides_runpath=no + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + dynamic_linker="$host_os dld.sl" + version_type=sunos + need_lib_prefix=no + need_version=no + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl' + soname_spec='${libname}${release}.sl$major' + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6*) + version_type=irix + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}.so.$major' + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so' + case "$host_os" in + irix5*) + libsuff= shlibsuff= + # this will be overridden with pass_all, but let us keep it just in case + deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" + ;; + *) + case "$LD" in # libtool.m4 will add one of these switches to LD + *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + # this will be overridden with pass_all, but let us keep it just in case + deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[1234] dynamic lib MIPS - version 1" + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + file_magic_cmd=/usr/bin/file + file_magic_test_file=`echo /lib${libsuff}/libc.so*` + deplibs_check_method='pass_all' + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux-gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + file_magic_cmd=/usr/bin/file + file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` + + if test -f /lib/ld.so.1; then + dynamic_linker='GNU ld.so' + else + # Only the GNU ld.so supports shared libraries on MkLinux. + case "$host_cpu" in + powerpc*) dynamic_linker=no ;; + *) dynamic_linker='Linux ld.so' ;; + esac + fi + ;; + +netbsd*) + version_type=sunos + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so' + soname_spec='${libname}${release}.so$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + ;; + +openbsd*) + version_type=sunos + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + need_version=no + fi + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +os2*) + libname_spec='$name' + need_lib_prefix=no + library_names_spec='$libname.dll $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4*) + version_type=osf + need_version=no + soname_spec='${libname}${release}.so' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' + shlibpath_var=LD_LIBRARY_PATH + # this will be overridden with pass_all, but let us keep it just in case + deplibs_check_method='file_magic COFF format alpha shared library' + file_magic_cmd=/usr/bin/file + file_magic_test_file=/shlib/libc.so + deplibs_check_method='pass_all' + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}.so$major' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib" + file_magic_cmd=/usr/bin/file + file_magic_test_file=/lib/libc.so + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + case "$host_vendor" in + ncr) + deplibs_check_method='pass_all' + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + file_magic_cmd=/usr/bin/file + file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + esac + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so' + soname_spec='$libname.so.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$ac_t$dynamic_linker" 1>&6 +test "$dynamic_linker" = no && can_build_shared=no + +# Report the final consequences. +echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6 + +# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in +# configure.in, otherwise build static only libraries. +case "$host_os" in +cygwin* | mingw* | os2*) + if test x$can_build_shared = xyes; then + test x$enable_win32_dll = xno && can_build_shared=no + echo "checking if package supports dlls... $can_build_shared" 1>&6 + fi +;; +esac + +if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then + case "$deplibs_check_method" in + "file_magic "*) + file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + egrep "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac +fi + +echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6 +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4*) + test "$enable_shared" = yes && enable_static=no + ;; +esac + +echo "$ac_t$enable_shared" 1>&6 + +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes + +echo "checking whether to build static libraries... $enable_static" 1>&6 + +if test "$hardcode_action" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + +echo $ac_n "checking for objdir... $ac_c" 1>&6 +rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + objdir=_libs +fi +rmdir .libs 2>/dev/null +echo "$ac_t$objdir" 1>&6 + +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else +if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then + lt_cv_dlopen=no lt_cv_dlopen_libs= +echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 +echo "$progname:2170: checking for dlopen in -ldl" >&5 +ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for dlopen""... $ac_c" 1>&6 +echo "$progname:2207: checking for dlopen" >&5 +if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_dlopen) || defined (__stub___dlopen) +choke me +#else +dlopen(); +#endif + +; return 0; } +EOF +if { (eval echo $progname:2234: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_dlopen=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_dlopen=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="dlopen" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6 +echo "$progname:2251: checking for dld_link in -ldld" >&5 +ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldld $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for shl_load""... $ac_c" 1>&6 +echo "$progname:2288: checking for shl_load" >&5 +if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shl_load(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_shl_load) || defined (__stub___shl_load) +choke me +#else +shl_load(); +#endif + +; return 0; } +EOF +if { (eval echo $progname:2315: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_shl_load=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_shl_load=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="shl_load" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6 +echo "$progname:2333: checking for shl_load in -ldld" >&5 +ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldld $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + echo "$ac_t""no" 1>&6 +fi + + +fi + + +fi + + +fi + + +fi + +fi + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + fi + + case "$lt_cv_dlopen" in + dlopen) +for ac_hdr in dlfcn.h; do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "$progname:2395: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int fnord = 0; +EOF +ac_try="$ac_compile conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo $progname:2405: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi +done + + if test "x$ac_cv_header_dlfcn_h" = xyes; then + CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + fi + eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + LIBS="$lt_cv_dlopen_libs $LIBS" + + echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6 +echo "$progname:2433: checking whether a program can dlopen itself" >&5 +if test "${lt_cv_dlopen_self+set}" = set; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + lt_cv_dlopen_self=cross + else + cat > conftest.c < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LTDL_GLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LTDL_GLOBAL DL_GLOBAL +# else +# define LTDL_GLOBAL 0 +# endif +#endif + +/* We may have to define LTDL_LAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LTDL_LAZY_OR_NOW +# ifdef RTLD_LAZY +# define LTDL_LAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LTDL_LAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LTDL_LAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LTDL_LAZY_OR_NOW DL_NOW +# else +# define LTDL_LAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +fnord() { int i=42;} +main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); + if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); + if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } + +EOF +if { (eval echo $progname:2487: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + lt_cv_dlopen_self=yes +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + lt_cv_dlopen_self=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$lt_cv_dlopen_self" 1>&6 + + if test "$lt_cv_dlopen_self" = yes; then + LDFLAGS="$LDFLAGS $link_static_flag" + echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6 +echo "$progname:2506: checking whether a statically linked program can dlopen itself" >&5 +if test "${lt_cv_dlopen_self_static+set}" = set; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + lt_cv_dlopen_self_static=cross + else + cat > conftest.c < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LTDL_GLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LTDL_GLOBAL DL_GLOBAL +# else +# define LTDL_GLOBAL 0 +# endif +#endif + +/* We may have to define LTDL_LAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LTDL_LAZY_OR_NOW +# ifdef RTLD_LAZY +# define LTDL_LAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LTDL_LAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LTDL_LAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LTDL_LAZY_OR_NOW DL_NOW +# else +# define LTDL_LAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +fnord() { int i=42;} +main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); + if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); + if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } + +EOF +if { (eval echo $progname:2560: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + lt_cv_dlopen_self_static=yes +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + lt_cv_dlopen_self_static=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6 +fi + ;; + esac + + case "$lt_cv_dlopen_self" in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case "$lt_cv_dlopen_self_static" in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + +# Copy echo and quote the copy, instead of the original, because it is +# used later. +ltecho="$echo" +if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then + ltecho="$CONFIG_SHELL \$0 --fallback-echo" +fi +LTSHELL="$SHELL" + +LTCONFIG_VERSION="$VERSION" + +# Only quote variables if we're using ltmain.sh. +case "$ltmain" in +*.sh) + # Now quote all the things that may contain metacharacters. + for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \ + old_LD old_LDFLAGS old_LIBS \ + old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \ + AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \ + reload_flag reload_cmds wl \ + pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \ + thread_safe_flag_spec whole_archive_flag_spec libname_spec \ + library_names_spec soname_spec \ + RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ + old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \ + file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \ + finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \ + hardcode_libdir_flag_spec hardcode_libdir_separator \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do + + case "$var" in + reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + export_symbols_cmds | archive_cmds | archive_expsym_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case "$ltecho" in + *'\$0 --fallback-echo"') + ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + + trap "$rm \"$ofile\"; exit 1" 1 2 15 + echo "creating $ofile" + $rm "$ofile" + cat < "$ofile" +#! $SHELL + +# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh. +# +# Copyright (C) 1996-1999 Free Software Foundation, Inc. +# Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="sed -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "\${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi + +### BEGIN LIBTOOL CONFIG +EOF + cfgfile="$ofile" + ;; + +*) + # Double-quote the variables that need it (for aesthetics). + for var in old_CC old_CFLAGS old_CPPFLAGS \ + old_LD old_LDFLAGS old_LIBS \ + old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do + eval "$var=\\\"\$var\\\"" + done + + # Just create a config file. + cfgfile="$ofile.cfg" + trap "$rm \"$cfgfile\"; exit 1" 1 2 15 + echo "creating $cfgfile" + $rm "$cfgfile" + cat < "$cfgfile" +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +EOF + ;; +esac + +cat <> "$cfgfile" +# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\ +# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\ +# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\ +# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\ +# $0$ltconfig_args +# +# Compiler and other test output produced by $progname, useful for +# debugging $progname, is in ./config.log if it exists. + +# The version of $progname that generated this script. +LTCONFIG_VERSION=$LTCONFIG_VERSION + +# Shell to use when invoking shell scripts. +SHELL=$LTSHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host + +# An echo program that does not interpret backslashes. +echo=$ltecho + +# The archiver. +AR=$AR + +# The default C compiler. +CC=$CC + +# The linker used to build libraries. +LD=$LD + +# Whether we need hard or soft links. +LN_S=$LN_S + +# A BSD-compatible nm program. +NM=$NM + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$reload_flag +reload_cmds=$reload_cmds + +# How to pass a linker flag through the compiler. +wl=$wl + +# Object file suffix (normally "o"). +objext="$objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$pic_flag + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$compiler_c_o + +# Can we write directly to a .lo ? +compiler_o_lo=$compiler_o_lo + +# Must we lock files when doing compilation ? +need_locks=$need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$link_static_flag + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$no_builtin_flag + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$whole_archive_flag_spec + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$thread_safe_flag_spec + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$RANLIB +old_archive_cmds=$old_archive_cmds +old_postinstall_cmds=$old_postinstall_cmds +old_postuninstall_cmds=$old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$old_archive_from_new_cmds + +# Commands used to build and install a shared archive. +archive_cmds=$archive_cmds +archive_expsym_cmds=$archive_expsym_cmds +postinstall_cmds=$postinstall_cmds +postuninstall_cmds=$postuninstall_cmds + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$allow_undefined_flag + +# Flag that forces no undefined symbols. +no_undefined_flag=$no_undefined_flag + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$global_symbol_to_cdecl + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec +if test -f /etc/debian_version; then +# Debian policy mandates that rpaths should not be encoded into a binary +# so it is overridden. + hardcode_libdir_flag_spec=" -D_DEBIAN_PATCHED_LIBTOOL_ " +fi + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$hardcode_libdir_separator + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$include_expsyms + +EOF + +case "$ltmain" in +*.sh) + echo '### END LIBTOOL CONFIG' >> "$ofile" + echo >> "$ofile" + case "$host_os" in + aix3*) + cat <<\EOF >> "$ofile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "${COLLECT_NAMES+set}" != set; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # Append the ltmain.sh script. + sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1) + + chmod +x "$ofile" + ;; + +*) + # Compile the libtool program. + echo "FIXME: would compile $ltmain" + ;; +esac + +test -n "$cache_file" || exit 0 + +# AC_CACHE_SAVE +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/ltmain.sh b/ltmain.sh new file mode 100644 index 00000000..ae10cad0 --- /dev/null +++ b/ltmain.sh @@ -0,0 +1,3975 @@ +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun ltconfig. +# +# Copyright (C) 1996-1999 Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Check that we have a working $echo. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell, and then maybe $echo will work. + exec $SHELL "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + echo "$modename: not configured to build any kind of library" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" + +# Parse our command line options once, thoroughly. +while test $# -gt 0 +do + arg="$1" + shift + + case "$arg" in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case "$prev" in + execute_dlfiles) + eval "$prev=\"\$$prev \$arg\"" + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case "$arg" in + --help) + show_help=yes + ;; + + --version) + echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" + exit 0 + ;; + + --config) + sed -e '1,/^### BEGIN LIBTOOL CONFIG/d' -e '/^### END LIBTOOL CONFIG/,$d' $0 + exit 0 + ;; + + --debug) + echo "$progname: enabling shell trace mode" + set -x + ;; + + --dry-run | -n) + run=: + ;; + + --features) + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + exit 0 + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --quiet | --silent) + show=: + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 +fi + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + case "$nonopt" in + *cc | *++ | gcc* | *-gcc*) + mode=link + for arg + do + case "$arg" in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx | *strace | *truss) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case "$mode" in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + lastarg= + srcfile="$nonopt" + suppress_output= + + user_target=no + for arg + do + # Accept any command-line options. + case "$arg" in + -o) + if test "$user_target" != "no"; then + $echo "$modename: you cannot specify \`-o' more than once" 1>&2 + exit 1 + fi + user_target=next + ;; + + -static) + build_old_libs=yes + continue + ;; + esac + + case "$user_target" in + next) + # The next one is the -o target name + user_target=yes + continue + ;; + yes) + # We got the output file + user_target=set + libobj="$arg" + continue + ;; + esac + + # Accept the current argument as the source file. + lastarg="$srcfile" + srcfile="$arg" + + # Aesthetically quote the previous argument. + + # Backslashify any backslashes, double quotes, and dollar signs. + # These are the only characters that are still specially + # interpreted inside of double-quoted scrings. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly in scan + # sets, so we specify it separately. + case "$lastarg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + lastarg="\"$lastarg\"" + ;; + esac + + # Add the previous argument to base_compile. + if test -z "$base_compile"; then + base_compile="$lastarg" + else + base_compile="$base_compile $lastarg" + fi + done + + case "$user_target" in + set) + ;; + no) + # Get the name of the library object. + libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + ;; + *) + $echo "$modename: you must specify a target with \`-o'" 1>&2 + exit 1 + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + xform='[cCFSfmso]' + case "$libobj" in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case "$libobj" in + *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; + *) + $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 + exit 1 + ;; + esac + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $libobj" + else + removelist="$libobj" + fi + + $run $rm $removelist + trap "$run $rm $removelist; exit 1" 1 2 15 + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\..*$%%'`.${objext} + lockfile="$output_obj.lock" + removelist="$removelist $output_obj $lockfile" + trap "$run $rm $removelist; exit 1" 1 2 15 + else + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until ln "$0" "$lockfile" 2>/dev/null; do + $show "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + echo "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + echo $srcfile > "$lockfile" + fi + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + # All platforms use -DPIC, to notify preprocessed assembler code. + command="$base_compile $pic_flag -DPIC $srcfile" + if test "$build_old_libs" = yes; then + lo_libobj="$libobj" + dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$libobj"; then + dir="$objdir" + else + dir="$dir/$objdir" + fi + libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` + + if test -d "$dir"; then + $show "$rm $libobj" + $run $rm $libobj + else + $show "$mkdir $dir" + $run $mkdir $dir + status=$? + if test $status -ne 0 && test ! -d $dir; then + exit $status + fi + fi + fi + if test "$compiler_o_lo" = yes; then + output_obj="$libobj" + command="$command -o $output_obj" + elif test "$compiler_c_o" = yes; then + output_obj="$obj" + command="$command -o $output_obj" + fi + + $run $rm "$output_obj" + $show "$command" + if $run eval "$command"; then : + else + test -n "$output_obj" && $run $rm $removelist + exit 1 + fi + + if test "$need_locks" = warn && + test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then + echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + + # Just move the object if needed, then go on to compile the next one + if test x"$output_obj" != x"$libobj"; then + $show "$mv $output_obj $libobj" + if $run $mv $output_obj $libobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # If we have no pic_flag, then copy the object into place and finish. + if test -z "$pic_flag" && test "$build_old_libs" = yes; then + # Rename the .lo from within objdir to obj + if test -f $obj; then + $show $rm $obj + $run $rm $obj + fi + + $show "$mv $libobj $obj" + if $run $mv $libobj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + + # Now arrange that obj and lo_libobj become the same file + $show "$LN_S $obj $lo_libobj" + if $run $LN_S $obj $lo_libobj; then + exit 0 + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Allow error messages only from the first compilation. + suppress_output=' >/dev/null 2>&1' + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + command="$base_compile $srcfile" + if test "$compiler_c_o" = yes; then + command="$command -o $obj" + output_obj="$obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + command="$command$suppress_output" + $run $rm "$output_obj" + $show "$command" + if $run eval "$command"; then : + else + $run $rm $removelist + exit 1 + fi + + if test "$need_locks" = warn && + test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then + echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + + # Just move the object if needed + if test x"$output_obj" != x"$obj"; then + $show "$mv $output_obj $obj" + if $run $mv $output_obj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Create an invalid libtool object if no PIC, so that we do not + # accidentally link it into a program. + if test "$build_libtool_libs" != yes; then + $show "echo timestamp > $libobj" + $run eval "echo timestamp > \$libobj" || exit $? + else + # Move the .lo from within objdir + $show "$mv $libobj $lo_libobj" + if $run $mv $libobj $lo_libobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + fi + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + $rm "$lockfile" + fi + + exit 0 + ;; + + # libtool link mode + link) + modename="$modename: link" + C_compiler="$CC" # save it, to compile generated C sources + CC="$nonopt" + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-os2*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invokation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + + # This is a source program that is used to create dlls on Windows + # Don't remove nor modify the starting and closing comments +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ + # This is a source program that is used to create import libraries + # on Windows for dlls which lack them. Don't remove nor modify the + # starting and closing comments +# /* impgen.c starts here */ +# /* Copyright (C) 1999 Free Software Foundation, Inc. +# +# This file is part of GNU libtool. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public 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 /* for printf() */ +# #include /* for open(), lseek(), read() */ +# #include /* for O_RDONLY, O_BINARY */ +# #include /* for strdup() */ +# +# static unsigned int +# pe_get16 (fd, offset) +# int fd; +# int offset; +# { +# unsigned char b[2]; +# lseek (fd, offset, SEEK_SET); +# read (fd, b, 2); +# return b[0] + (b[1]<<8); +# } +# +# static unsigned int +# pe_get32 (fd, offset) +# int fd; +# int offset; +# { +# unsigned char b[4]; +# lseek (fd, offset, SEEK_SET); +# read (fd, b, 4); +# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); +# } +# +# static unsigned int +# pe_as32 (ptr) +# void *ptr; +# { +# unsigned char *b = ptr; +# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); +# } +# +# int +# main (argc, argv) +# int argc; +# char *argv[]; +# { +# int dll; +# unsigned long pe_header_offset, opthdr_ofs, num_entries, i; +# unsigned long export_rva, export_size, nsections, secptr, expptr; +# unsigned long name_rvas, nexp; +# unsigned char *expdata, *erva; +# char *filename, *dll_name; +# +# filename = argv[1]; +# +# dll = open(filename, O_RDONLY|O_BINARY); +# if (!dll) +# return 1; +# +# dll_name = filename; +# +# for (i=0; filename[i]; i++) +# if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') +# dll_name = filename + i +1; +# +# pe_header_offset = pe_get32 (dll, 0x3c); +# opthdr_ofs = pe_header_offset + 4 + 20; +# num_entries = pe_get32 (dll, opthdr_ofs + 92); +# +# if (num_entries < 1) /* no exports */ +# return 1; +# +# export_rva = pe_get32 (dll, opthdr_ofs + 96); +# export_size = pe_get32 (dll, opthdr_ofs + 100); +# nsections = pe_get16 (dll, pe_header_offset + 4 +2); +# secptr = (pe_header_offset + 4 + 20 + +# pe_get16 (dll, pe_header_offset + 4 + 16)); +# +# expptr = 0; +# for (i = 0; i < nsections; i++) +# { +# char sname[8]; +# unsigned long secptr1 = secptr + 40 * i; +# unsigned long vaddr = pe_get32 (dll, secptr1 + 12); +# unsigned long vsize = pe_get32 (dll, secptr1 + 16); +# unsigned long fptr = pe_get32 (dll, secptr1 + 20); +# lseek(dll, secptr1, SEEK_SET); +# read(dll, sname, 8); +# if (vaddr <= export_rva && vaddr+vsize > export_rva) +# { +# expptr = fptr + (export_rva - vaddr); +# if (export_rva + export_size > vaddr + vsize) +# export_size = vsize - (export_rva - vaddr); +# break; +# } +# } +# +# expdata = (unsigned char*)malloc(export_size); +# lseek (dll, expptr, SEEK_SET); +# read (dll, expdata, export_size); +# erva = expdata - export_rva; +# +# nexp = pe_as32 (expdata+24); +# name_rvas = pe_as32 (expdata+32); +# +# printf ("EXPORTS\n"); +# for (i = 0; i&2 + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + else + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + fi + build_libtool_libs=no + build_old_libs=yes + prefer_static_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test $# -gt 0; do + arg="$1" + shift + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case "$prev" in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case "$prev" in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + preload=yes + fi + case "$arg" in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + ;; + esac + ;; + expsyms) + export_symbols="$arg" + if test ! -f "$arg"; then + $echo "$modename: symbol file \`$arg' does not exist" + exit 1 + fi + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case "$arg" in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit 1 + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi + + prevarg="$arg" + + case "$arg" in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: not more than one -exported-symbols argument allowed" + exit 1 + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` + # We need an absolute path. + case "$dir" in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + absdir="$dir" + fi + dir="$absdir" + ;; + esac + case " $deplibs " in + *" $arg "*) ;; + *) deplibs="$deplibs $arg";; + esac + case " $lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir";; + esac + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-os2*) + dllsearchdir=`cd "$dir" && pwd || echo "$dir"` + case ":$dllsearchpath:" in + ::) dllsearchpath="$dllsearchdir";; + *":$dllsearchdir:"*) ;; + *) dllsearchpath="$dllsearchpath:$dllsearchdir";; + esac + ;; + esac + ;; + + -l*) + if test "$arg" = "-lc"; then + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*) + # These systems don't actually have c library (as such) + continue + ;; + esac + elif test "$arg" = "-lm"; then + case "$host" in + *-*-cygwin* | *-*-beos*) + # These systems don't actually have math library (as such) + continue + ;; + esac + fi + deplibs="$deplibs $arg" + ;; + + -module) + module=yes + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -o) prev=output ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` + # We need an absolute path. + case "$dir" in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit 1 + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -static) + # If we have no pic_flag, then this is the same as -all-static. + if test -z "$pic_flag" && test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + ;; + + *.o | *.obj | *.a | *.lib) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A library object. + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + if test "$build_libtool_libs" = yes && test "$dlopen" = yes; then + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"` + prev= + fi + libobjs="$libobjs $arg" + ;; + + *.la) + # A libtool-controlled library. + + dlname= + libdir= + library_names= + old_library= + + # Check to see that this really is a libtool archive. + if (sed -e '2q' $arg | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2 + exit 1 + fi + + # If the library was installed with an old release of libtool, + # it will not redefine variable installed. + installed=yes + + # Read the .la file + # If there is no directory component, then add one. + case "$arg" in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$arg'" 1>&2 + exit 1 + fi + + # Find the relevant object directory and library name. + name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'` + + if test "X$installed" = Xyes; then + dir="$libdir" + else + dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$arg"; then + dir="$objdir" + else + dir="$dir/$objdir" + fi + fi + + if test -n "$dependency_libs"; then + # Extract -R and -L from dependency_libs + temp_deplibs= + for deplib in $dependency_libs; do + case "$deplib" in + -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + case " $rpath $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + -L*) case "$compile_command $temp_deplibs " in + *" $deplib "*) ;; + *) temp_deplibs="$temp_deplibs $deplib";; + esac + temp_dir=`$echo "X$deplib" | $Xsed -e 's/^-L//'` + case " $lib_search_path " in + *" $temp_dir "*) ;; + *) lib_search_path="$lib_search_path $temp_dir";; + esac + ;; + *) temp_deplibs="$temp_deplibs $deplib";; + esac + done + dependency_libs="$temp_deplibs" + fi + + if test -z "$libdir"; then + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $dir/$old_library" + old_convenience="$old_convenience $dir/$old_library" + deplibs="$deplibs$dependency_libs" + compile_command="$compile_command $dir/$old_library$dependency_libs" + finalize_command="$finalize_command $dir/$old_library$dependency_libs" + continue + fi + + # This library was specified with -dlopen. + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + if test -z "$dlname" || test "$dlopen" != yes || test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking statically, + # we need to preload. + prev=dlprefiles + else + # We should not create a dependency on this library, but we + # may need any libraries it requires. + compile_command="$compile_command$dependency_libs" + finalize_command="$finalize_command$dependency_libs" + prev= + continue + fi + fi + + # The library was specified with -dlpreopen. + if test "$prev" = dlprefiles; then + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + dlprefiles="$dlprefiles $dir/$old_library" + else + dlprefiles="$dlprefiles $dir/$linklib" + fi + prev= + fi + + if test -n "$library_names" && + { test "$prefer_static_libs" = no || test -z "$old_library"; }; then + link_against_libtool_libs="$link_against_libtool_libs $arg" + if test -n "$shlibpath_var"; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *) temp_rpath="$temp_rpath $dir" ;; + esac + fi + + # We need an absolute path. + case "$dir" in + [\\/] | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + absdir="$dir" + fi + ;; + esac + + # This is the magic to use -rpath. + # Skip directories that are in the system default run-time + # search path, unless they have been requested with -R. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + + lib_linked=yes + case "$hardcode_action" in + immediate | unsupported) + if test "$hardcode_direct" = no; then + compile_command="$compile_command $dir/$linklib" + deplibs="$deplibs $dir/$linklib" + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-os2*) + dllsearchdir=`cd "$dir" && pwd || echo "$dir"` + if test -n "$dllsearchpath"; then + dllsearchpath="$dllsearchpath:$dllsearchdir" + else + dllsearchpath="$dllsearchdir" + fi + ;; + esac + elif test "$hardcode_minus_L" = no; then + case "$host" in + *-*-sunos*) + compile_shlibpath="$compile_shlibpath$dir:" + ;; + esac + case "$compile_command " in + *" -L$dir "*) ;; + *) compile_command="$compile_command -L$dir";; + esac + compile_command="$compile_command -l$name" + deplibs="$deplibs -L$dir -l$name" + elif test "$hardcode_shlibpath_var" = no; then + case ":$compile_shlibpath:" in + *":$dir:"*) ;; + *) compile_shlibpath="$compile_shlibpath$dir:";; + esac + compile_command="$compile_command -l$name" + deplibs="$deplibs -l$name" + else + lib_linked=no + fi + ;; + + relink) + if test "$hardcode_direct" = yes; then + compile_command="$compile_command $absdir/$linklib" + deplibs="$deplibs $absdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + case "$compile_command " in + *" -L$absdir "*) ;; + *) compile_command="$compile_command -L$absdir";; + esac + compile_command="$compile_command -l$name" + deplibs="$deplibs -L$absdir -l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case ":$compile_shlibpath:" in + *":$absdir:"*) ;; + *) compile_shlibpath="$compile_shlibpath$absdir:";; + esac + compile_command="$compile_command -l$name" + deplibs="$deplibs -l$name" + else + lib_linked=no + fi + ;; + + *) + lib_linked=no + ;; + esac + + if test "$lib_linked" != yes; then + $echo "$modename: configuration error: unsupported hardcode properties" + exit 1 + fi + + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + finalize_command="$finalize_command $libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + case "$finalize_command " in + *" -L$libdir "*) ;; + *) finalize_command="$finalize_command -L$libdir";; + esac + finalize_command="$finalize_command -l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case ":$finalize_shlibpath:" in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:";; + esac + finalize_command="$finalize_command -l$name" + else + # We cannot seem to hardcode it, guess we'll fake it. + case "$finalize_command " in + *" -L$dir "*) ;; + *) finalize_command="$finalize_command -L$libdir";; + esac + finalize_command="$finalize_command -l$name" + fi + else + # Transform directly to old archives if we don't build new libraries. + if test -n "$pic_flag" && test -z "$old_library"; then + $echo "$modename: cannot find static library for \`$arg'" 1>&2 + exit 1 + fi + + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_command="$compile_command $dir/$linklib" + finalize_command="$finalize_command $dir/$linklib" + else + case "$compile_command " in + *" -L$dir "*) ;; + *) compile_command="$compile_command -L$dir";; + esac + compile_command="$compile_command -l$name" + case "$finalize_command " in + *" -L$dir "*) ;; + *) finalize_command="$finalize_command -L$dir";; + esac + finalize_command="$finalize_command -l$name" + fi + fi + + # Add in any libraries that this one depends upon. + compile_command="$compile_command$dependency_libs" + finalize_command="$finalize_command$dependency_libs" + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + ;; + esac + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` + libobjs_save="$libobjs" + + case "$output" in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + *.a | *.lib) + if test -n "$link_against_libtool_libs"; then + $echo "$modename: error: cannot link libtool libraries into archives" 1>&2 + exit 1 + fi + + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 + fi + + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 + fi + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + ;; + + *.la) + # Make sure we only generate libraries of the form `libNAME.la'. + case "$outputname" in + lib*) + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval libname=\"$libname_spec\" + ;; + *) + if test "$module" = no; then + $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + eval libname=\"$libname_spec\" + else + libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + fi + ;; + esac + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + + if test -n "$objs"; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1 + exit 1 + fi + + # How the heck are we supposed to write a wrapper for a shared library? + if test -n "$link_against_libtool_libs"; then + $echo "$modename: error: cannot link shared libraries into libtool libraries" 1>&2 + exit 1 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for libtool libraries" 1>&2 + fi + + set dummy $rpath + if test $# -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + libext=al + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + dependency_libs="$deplibs" + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 + fi + else + + # Parse the version information argument. + IFS="${IFS= }"; save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + IFS="$save_ifs" + + if test -n "$8"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + current="$2" + revision="$3" + age="$4" + + # Check that each of the things are valid numbers. + case "$current" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case "$revision" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case "$age" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + if test $age -gt $current; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case "$version_type" in + none) ;; + + irix) + major=`expr $current - $age + 1` + versuffix="$major.$revision" + verstring="sgi$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test $loop != 0; do + iface=`expr $revision - $loop` + loop=`expr $loop - 1` + verstring="sgi$major.$iface:$verstring" + done + ;; + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + major=`expr $current - $age` + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test $loop != 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current"; + ;; + + windows) + # Like Linux, but with '-' rather than '.', since we only + # want one extension on Windows 95. + major=`expr $current - $age` + versuffix="-$major-$age-$revision" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + verstring="0.0" + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + dependency_libs="$deplibs" + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*) + # these systems don't actually have a c library (as such)! + ;; + *) + # Add libc to deplibs on all other systems. + deplibs="$deplibs -lc" + ;; + esac + fi + + # Create the output directory, or remove our outputs if we need to. + if test -d $output_objdir; then + $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*" + $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.* + else + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + status=$? + if test $status -ne 0 && test ! -d $output_objdir; then + exit $status + fi + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + if test "$build_libtool_libs" = yes; then + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case "$deplibs_check_method" in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behaviour. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $rm conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null \ + | grep " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | sed 's/.* -> //'` + case "$potliblink" in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ + | sed 10q \ + | egrep "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + echo "*** Warning: This library needs some functionality provided by $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ + -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' | + grep . >/dev/null; then + echo + if test "X$deplibs_check_method" = "Xnone"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + echo "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + # Get the real and link names of the library. + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + lib="$output_objdir/$realname" + for link + do + linknames="$linknames $link" + done + + # Ensure that we have .o objects for linkers which dislike .lo + # (e.g. aix) incase we are running --disable-static + for obj in $libobjs; do + oldobj=`$echo "X$obj" | $Xsed -e "$lo2o"` + if test ! -f $oldobj; then + $show "${LN_S} $obj $oldobj" + $run ${LN_S} $obj $oldobj || exit $? + fi + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + eval cmds=\"$export_symbols_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + if test -n "$export_symbols_regex"; then + $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' + fi + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${outputname}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test $status -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + for xlib in $convenience; do + # Extract the objects. + case "$xlib" in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test $status -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` + done + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linkopts="$linkopts $flag" + fi + + # Do each of the archive commands. + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval cmds=\"$archive_expsym_cmds\" + else + eval cmds=\"$archive_cmds\" + fi + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + *.lo | *.o | *.obj) + if test -n "$link_against_libtool_libs"; then + $echo "$modename: error: cannot link libtool libraries into objects" 1>&2 + exit 1 + fi + + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 + fi + + case "$output" in + *.lo) + if test -n "$objs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit 1 + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e "$lo2o"` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${obj}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test $status -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + for xlib in $convenience; do + # Extract the objects. + case "$xlib" in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test $status -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` + done + fi + fi + + # Create the old-style object. + reload_objs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" + + output="$obj" + eval cmds=\"$reload_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit 0 + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + $show "echo timestamp > $libobj" + $run eval "echo timestamp > $libobj" || exit $? + exit 0 + fi + + if test -n "$pic_flag"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + eval cmds=\"$reload_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + else + # Just create a symlink. + $show $rm $libobj + $run $rm $libobj + $show "$LN_S $obj $libobj" + $run $LN_S $obj $libobj || exit $? + fi + + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit 0 + ;; + + # Anything else should be a program. + *) + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 + fi + + if test "$preload" = yes; then + if test "$dlopen" = unknown && test "$dlopen_self" = unknown && + test "$dlopen_self_static" = unknown; then + $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." + fi + fi + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$compile_rpath " in + *" $libdir "*) ;; + *) compile_rpath="$compile_rpath $libdir" ;; + esac + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + + # Create the binary in the object directory, then wrap it. + if test ! -d $output_objdir; then + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + status=$? + if test $status -ne 0 && test ! -d $output_objdir; then + exit $status + fi + fi + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + dlsyms= + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$dlsyms"; then + case "$dlsyms" in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$dlsyms" + + test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define lt_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$output.exp" + $run $rm $export_symbols + $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + else + $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' + $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`echo "$arg" | sed -e 's%^.*/%%'` + $run eval 'echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $mv "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then + : + else + grep -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$dlsyms" + fi + + $echo >> "$output_objdir/$dlsyms" "\ + +#undef lt_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{\ +" + + sed -n -e 's/^: \([^ ]*\) $/ {\"\1\", (lt_ptr_t) 0},/p' \ + -e 's/^. \([^ ]*\) \([^ ]*\)$/ {"\2", (lt_ptr_t) \&\2},/p' \ + < "$nlist" >> "$output_objdir/$dlsyms" + + $echo >> "$output_objdir/$dlsyms" "\ + {0, (lt_ptr_t) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + case "$host" in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $C_compiler -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $C_compiler -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + ;; + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit 1 + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + $show "$link_command" + $run eval "$link_command" + status=$? + + # Delete the generated files. + if test -n "$dlsyms"; then + $show "$rm $output_objdir/${outputname}S.${objext}" + $run $rm "$output_objdir/${outputname}S.${objext}" + fi + + exit $status + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case "$dir" in + [\\/]* | [A-Za-z]:[\\/]*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 + $echo "$modename: \`$output' will be relinked during installation" 1>&2 + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname + + $show "$link_command" + $run eval "$link_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $echo for shipping. + if test "X$echo" = "X$SHELL $0 --fallback-echo"; then + case "$0" in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; + *) qecho="$SHELL `pwd`/$0 --fallback-echo";; + esac + qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) output=`echo $output|sed 's,.exe$,,'` ;; + esac + $rm $output + trap "$rm $output; exit 1" 1 2 15 + + $echo > $output "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test \"\${CDPATH+set}\" = set; then CDPATH=; export CDPATH; fi + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variable: + link_against_libtool_libs='$link_against_libtool_libs' +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + echo=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$echo works! + : + else + # Restart under the correct shell, and then maybe \$echo will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + echo >> $output "\ + program=lt-'$outputname' + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $mkdir \"\$progdir\" + else + $rm \"\$progdir/\$file\" + fi" + + echo >> $output "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if (cd \"\$thisdir\" && eval \$relink_command); then : + else + $rm \"\$progdir/\$file\" + exit 1 + fi + fi + + $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $rm \"\$progdir/\$program\"; + $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $rm \"\$progdir/\$file\" + fi" + else + echo >> $output "\ + program='$outputname$exeext' + progdir=\"\$thisdir/$objdir\" +" + fi + + echo >> $output "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $echo >> $output "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + *-*-cygwin* | *-*-mingw | *-*-os2*) + # win32 systems need to use the prog path for dll + # lookup to work + $echo >> $output "\ + exec \$progdir\\\\\$program \${1+\"\$@\"} +" + ;; + *) + $echo >> $output "\ + # Export the path to the program. + PATH=\"\$progdir:\$PATH\" + export PATH + + exec \$program \${1+\"\$@\"} +" + ;; + esac + $echo >> $output "\ + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit 1 + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" + chmod +x $output + fi + exit 0 + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$objs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP` + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test $status -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + # Add in members from convenience archives. + for xlib in $addlibs; do + # Extract the objects. + case "$xlib" in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test $status -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` + done + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + eval cmds=\"$old_archive_from_new_cmds\" + else + # Ensure that we have .o objects in place incase we decided + # not to build a shared library, and have fallen back to building + # static libs even though --disable-static was passed! + for oldobj in $oldobjs; do + if test ! -f $oldobj; then + obj=`$echo "X$oldobj" | $Xsed -e "$o2lo"` + $show "${LN_S} $obj $oldobj" + $run ${LN_S} $obj $oldobj || exit $? + fi + done + + eval cmds=\"$old_archive_cmds\" + fi + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$generated"; then + $show "${rm}r$generated" + $run ${rm}r$generated + fi + + # Now create the libtool archive. + case "$output" in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + $show "creating $output" + + if test -n "$xrpath"; then + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + done + dependency_libs="$temp_xrpath $dependency_libs" + fi + + # Only create the output if not a dry run. + if test -z "$run"; then + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + fi + $rm $output + $echo > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$dlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Directory that this library needs to be installed in: +libdir='$install_libdir'\ +" + done + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" + $run eval "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" || exit $? + ;; + esac + exit 0 + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg="$nonopt" + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest="$arg" + continue + fi + + case "$arg" in + -d) isdir=yes ;; + -f) prev="-f" ;; + -g) prev="-g" ;; + -m) prev="-m" ;; + -o) prev="-o" ;; + -s) + stripme=" -s" + continue + ;; + -*) ;; + + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest="$arg" + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit 1 + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test $# -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + fi + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case "$file" in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case "$file" in + *.a | *.lib) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + library_names= + old_library= + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/" + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$realname $destdir/$realname" + $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $? + + if test $# -gt 0; then + # Delete the old symlinks, and create new ones. + for linkname + do + if test "$linkname" != "$realname"; then + $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" + fi + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + eval cmds=\"$postinstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + instname="$dir/$name"i + $show "$install_prog $instname $destdir/$name" + $run eval "$install_prog $instname $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case "$destfile" in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` + ;; + *.o | *.obj) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit 0 + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Do a test to see if this is really a libtool program. + if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + link_against_libtool_libs= + relink_command= + + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Check the variables that should have been set. + if test -z "$link_against_libtool_libs"; then + $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2 + exit 1 + fi + + finalize=yes + for lib in $link_against_libtool_libs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case "$lib" in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`" + if test -n "$libdir" && test ! -f "$libfile"; then + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + if test "$finalize" = yes && test -z "$run"; then + tmpdir="/tmp" + test -n "$TMPDIR" && tmpdir="$TMPDIR" + tmpdir="$tmpdir/libtool-$$" + if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then : + else + $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 + continue + fi + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + ${rm}r "$tmpdir" + continue + fi + file="$outputname" + else + $echo "$modename: warning: cannot relink \`$file'" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + $show "$install_prog$stripme $file $destfile" + $run eval "$install_prog\$stripme \$file \$destfile" || exit $? + test -n "$outputname" && ${rm}r "$tmpdir" + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + # Do each command in the postinstall commands. + eval cmds=\"$old_postinstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec $SHELL $0 --finish$current_libdirs + exit 1 + fi + + exit 0 + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + eval cmds=\"$finish_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || admincmds="$admincmds + $cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + test "$show" = : && exit 0 + + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + echo " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use \`-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + echo " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + echo " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + echo "See any operating system documentation about shared libraries for" + echo "more information, such as the ld(1) and ld.so(8) manual pages." + echo "----------------------------------------------------------------------" + exit 0 + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit 1 + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test ! -f "$file"; then + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + dir= + case "$file" in + *.la) + # Check to see that this really is a libtool archive. + if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit 1 + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case "$file" in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + + # Restore saved enviroment variables + if test "${save_LC_ALL+set}" = set; then + LC_ALL="$save_LC_ALL"; export LC_ALL + fi + if test "${save_LANG+set}" = set; then + LANG="$save_LANG"; export LANG + fi + + # Now actually exec the command. + eval "exec \$cmd$args" + + $echo "$modename: cannot exec \$cmd$args" + exit 1 + else + # Display what would be done. + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + $echo "$cmd$args" + exit 0 + fi + ;; + + # libtool uninstall mode + uninstall) + modename="$modename: uninstall" + rm="$nonopt" + files= + + for arg + do + case "$arg" in + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + rmfiles="$file" + + case "$name" in + *.la) + # Possibly a libtool archive, so verify it. + if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $dir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library" + + $show "$rm $rmfiles" + $run $rm $rmfiles + + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + eval cmds=\"$postuninstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + eval cmds=\"$old_postuninstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + + # FIXME: should reinstall the best remaining shared library. + fi + ;; + + *.lo) + if test "$build_old_libs" = yes; then + oldobj=`$echo "X$name" | $Xsed -e "$lo2o"` + rmfiles="$rmfiles $dir/$oldobj" + fi + $show "$rm $rmfiles" + $run $rm $rmfiles + ;; + + *) + $show "$rm $rmfiles" + $run $rm $rmfiles + ;; + esac + done + exit 0 + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 + ;; + esac + + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 +fi # test -z "$show_help" + +# We need to display help for each of the modes. +case "$mode" in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + + --config show all configuration variables + --debug enable verbose shell tracing +-n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --version print version information + +MODE must be one of the following: + + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE." + exit 0 + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -static always build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + +uninstall) + $echo \ +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; +esac + +echo +$echo "Try \`$modename --help' for more information about other modes." + +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/main/Makefile.am b/main/Makefile.am new file mode 100644 index 00000000..72cdd31e --- /dev/null +++ b/main/Makefile.am @@ -0,0 +1,31 @@ +if USE_OPENGL +INCLUDES = -I $(top_srcdir)/includes -I $(top_srcdir)/input/ggi/include -I $(top_srcdir)/input/linux/include -fwritable-strings +else +INCLUDES = -I $(top_srcdir)/includes -I $(top_srcdir)/input/sdl/include -I $(top_srcdir)/input/linux/include -fwritable-strings +endif + +bin_PROGRAMS = d2x + +d2x_SOURCES = \ +ai.c gamerend.c lighting.c paging.c switch.c \ +ai2.c effects.c gamesave.c menu.c physics.c texmerge.c \ +aipath.c endlevel.c gameseg.c mglobal.c piggy.c text.c \ +automap.c escort.c gameseq.c mission.c playsave.c titles.c \ +bm.c fireball.c gauges.c morph.c polyobj.c vclip.c \ +bmread.c fuelcen.c hostage.c multi.c powerup.c wall.c \ +cntrlcen.c fvi.c hud.c multibot.c render.c weapon.c \ +collide.c game.c inferno.c netmisc.c robot.c \ +config.c gamecntl.c kconfig.c network.c scores.c \ +controls.c gamefont.c kludge.c newdemo.c slew.c \ +credits.c gamemine.c kmatrix.c newmenu.c songs.c \ +crypt.c gamepal.c laser.c object.c state.c \ +console.c cmd.c + + +d2x_LDFLAGS = -export-dynamic +if USE_OPENGL +d2x_LDADD = ../3d/lib3d.a ../2d/lib2d.a ../mem/libmem.a ../cfile/libcfile.a ../iff/libiff.a ../texmap/libtexmap.a ../misc/libmisc.a ../maths/libmaths.a ../arch/libarch.a ../video/libvideo.a ../sound/libsound.a ../input/libinput.a -lm -lSDL -ldl -lpthread -lMesaGL -lMesaGLU -lgii -L/usr/X11R6/lib -lXext +else +d2x_LDADD = ../3d/lib3d.a ../2d/lib2d.a ../mem/libmem.a ../cfile/libcfile.a ../iff/libiff.a ../texmap/libtexmap.a ../misc/libmisc.a ../maths/libmaths.a ../arch/libarch.a ../video/libvideo.a ../sound/libsound.a ../input/libinput.a -lm -lSDL -ldl -lpthread +endif + diff --git a/main/Makefile.in b/main/Makefile.in new file mode 100644 index 00000000..ba4647ca --- /dev/null +++ b/main/Makefile.in @@ -0,0 +1,355 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +CFLAGS = @CFLAGS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +NASM = @NASM@ +NASMFLAGS = @NASMFLAGS@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_LIBS = @SDL_LIBS@ +VERSION = @VERSION@ +@USE_OPENGL_TRUE@INCLUDES = -I $(top_srcdir)/includes -I $(top_srcdir)/input/ggi/include -I $(top_srcdir)/input/linux/include -fwritable-strings +@USE_OPENGL_FALSE@INCLUDES = -I $(top_srcdir)/includes -I $(top_srcdir)/input/sdl/include -I $(top_srcdir)/input/linux/include -fwritable-strings + +bin_PROGRAMS = d2x + +d2x_SOURCES = ai.c gamerend.c lighting.c paging.c switch.c ai2.c effects.c gamesave.c menu.c physics.c texmerge.c aipath.c endlevel.c gameseg.c mglobal.c piggy.c text.c automap.c escort.c gameseq.c mission.c playsave.c titles.c bm.c fireball.c gauges.c morph.c polyobj.c vclip.c bmread.c fuelcen.c hostage.c multi.c powerup.c wall.c cntrlcen.c fvi.c hud.c multibot.c render.c weapon.c collide.c game.c inferno.c netmisc.c robot.c config.c gamecntl.c kconfig.c network.c scores.c controls.c gamefont.c kludge.c newdemo.c slew.c credits.c gamemine.c kmatrix.c newmenu.c songs.c crypt.c gamepal.c laser.c object.c state.c console.c cmd.c + + +d2x_LDFLAGS = -export-dynamic +@USE_OPENGL_TRUE@d2x_LDADD = ../3d/lib3d.a ../2d/lib2d.a ../mem/libmem.a ../cfile/libcfile.a ../iff/libiff.a ../texmap/libtexmap.a ../misc/libmisc.a ../maths/libmaths.a ../arch/libarch.a ../video/libvideo.a ../sound/libsound.a ../input/libinput.a -lm -lSDL -ldl -lpthread -lMesaGL -lMesaGLU -lgii -L/usr/X11R6/lib -lXext +@USE_OPENGL_FALSE@d2x_LDADD = ../3d/lib3d.a ../2d/lib2d.a ../mem/libmem.a ../cfile/libcfile.a ../iff/libiff.a ../texmap/libtexmap.a ../misc/libmisc.a ../maths/libmaths.a ../arch/libarch.a ../video/libvideo.a ../sound/libsound.a ../input/libinput.a -lm -lSDL -ldl -lpthread +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../conf.h +CONFIG_CLEAN_FILES = +PROGRAMS = $(bin_PROGRAMS) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +d2x_OBJECTS = ai.o gamerend.o lighting.o paging.o switch.o ai2.o \ +effects.o gamesave.o menu.o physics.o texmerge.o aipath.o endlevel.o \ +gameseg.o mglobal.o piggy.o text.o automap.o escort.o gameseq.o \ +mission.o playsave.o titles.o bm.o fireball.o gauges.o morph.o \ +polyobj.o vclip.o bmread.o fuelcen.o hostage.o multi.o powerup.o wall.o \ +cntrlcen.o fvi.o hud.o multibot.o render.o weapon.o collide.o game.o \ +inferno.o netmisc.o robot.o config.o gamecntl.o kconfig.o network.o \ +scores.o controls.o gamefont.o kludge.o newdemo.o slew.o credits.o \ +gamemine.o kmatrix.o newmenu.o songs.o crypt.o gamepal.o laser.o \ +object.o state.o console.o cmd.o +@USE_OPENGL_TRUE@d2x_DEPENDENCIES = ../3d/lib3d.a ../2d/lib2d.a \ +@USE_OPENGL_TRUE@../mem/libmem.a ../cfile/libcfile.a ../iff/libiff.a \ +@USE_OPENGL_TRUE@../texmap/libtexmap.a ../misc/libmisc.a \ +@USE_OPENGL_TRUE@../maths/libmaths.a ../arch/libarch.a \ +@USE_OPENGL_TRUE@../video/libvideo.a ../sound/libsound.a \ +@USE_OPENGL_TRUE@../input/libinput.a +@USE_OPENGL_FALSE@d2x_DEPENDENCIES = ../3d/lib3d.a ../2d/lib2d.a \ +@USE_OPENGL_FALSE@../mem/libmem.a ../cfile/libcfile.a ../iff/libiff.a \ +@USE_OPENGL_FALSE@../texmap/libtexmap.a ../misc/libmisc.a \ +@USE_OPENGL_FALSE@../maths/libmaths.a ../arch/libarch.a \ +@USE_OPENGL_FALSE@../video/libvideo.a ../sound/libsound.a \ +@USE_OPENGL_FALSE@../input/libinput.a +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +DEP_FILES = .deps/ai.P .deps/ai2.P .deps/aipath.P .deps/automap.P \ +.deps/bm.P .deps/bmread.P .deps/cmd.P .deps/cntrlcen.P .deps/collide.P \ +.deps/config.P .deps/console.P .deps/controls.P .deps/credits.P \ +.deps/crypt.P .deps/effects.P .deps/endlevel.P .deps/escort.P \ +.deps/fireball.P .deps/fuelcen.P .deps/fvi.P .deps/game.P \ +.deps/gamecntl.P .deps/gamefont.P .deps/gamemine.P .deps/gamepal.P \ +.deps/gamerend.P .deps/gamesave.P .deps/gameseg.P .deps/gameseq.P \ +.deps/gauges.P .deps/hostage.P .deps/hud.P .deps/inferno.P \ +.deps/kconfig.P .deps/kludge.P .deps/kmatrix.P .deps/laser.P \ +.deps/lighting.P .deps/menu.P .deps/mglobal.P .deps/mission.P \ +.deps/morph.P .deps/multi.P .deps/multibot.P .deps/netmisc.P \ +.deps/network.P .deps/newdemo.P .deps/newmenu.P .deps/object.P \ +.deps/paging.P .deps/physics.P .deps/piggy.P .deps/playsave.P \ +.deps/polyobj.P .deps/powerup.P .deps/render.P .deps/robot.P \ +.deps/scores.P .deps/slew.P .deps/songs.P .deps/state.P .deps/switch.P \ +.deps/texmerge.P .deps/text.P .deps/titles.P .deps/vclip.P .deps/wall.P \ +.deps/weapon.P +SOURCES = $(d2x_SOURCES) +OBJECTS = $(d2x_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu main/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-binPROGRAMS: + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +distclean-binPROGRAMS: + +maintainer-clean-binPROGRAMS: + +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ + $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(bin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + done + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +d2x: $(d2x_OBJECTS) $(d2x_DEPENDENCIES) + @rm -f d2x + $(LINK) $(d2x_LDFLAGS) $(d2x_OBJECTS) $(d2x_LDADD) $(LIBS) + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = main + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu main/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: install-binPROGRAMS +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-binPROGRAMS +uninstall: uninstall-am +all-am: Makefile $(PROGRAMS) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(bindir) + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-compile \ + mostlyclean-tags mostlyclean-depend mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-binPROGRAMS clean-compile clean-tags clean-depend \ + clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-binPROGRAMS distclean-compile distclean-tags \ + distclean-depend distclean-generic clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-binPROGRAMS \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \ +maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/main/ai.c b/main/ai.c new file mode 100644 index 00000000..2dc8739e --- /dev/null +++ b/main/ai.c @@ -0,0 +1,1674 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + +char ai_rcsid[] = "$Id: ai.c,v 1.1.1.1 2001-01-19 03:30:02 bradleyb Exp $"; + +#include +#include +#include +#include + +#include "inferno.h" +#include "game.h" +#include "mono.h" +#include "3d.h" + +#include "object.h" +#include "render.h" +#include "error.h" +#include "ai.h" +#include "laser.h" +#include "fvi.h" +#include "polyobj.h" +#include "bm.h" +#include "weapon.h" +#include "physics.h" +#include "collide.h" +#include "player.h" +#include "wall.h" +#include "vclip.h" +#include "fireball.h" +#include "morph.h" +#include "effects.h" +#include "timer.h" +#include "sounds.h" +#include "cntrlcen.h" +#include "multibot.h" +#include "multi.h" +#include "network.h" +#include "gameseq.h" +#include "key.h" +#include "powerup.h" +#include "gauges.h" +#include "text.h" +#include "fuelcen.h" +#include "controls.h" +#include "kconfig.h" + +#ifdef EDITOR +#include "editor\editor.h" +#endif + +#include "string.h" + +#ifndef NDEBUG +#include +#endif + +// ---------- John: These variables must be saved as part of gamesave. ---------- +int Ai_initialized = 0; +int Overall_agitation; +ai_local Ai_local_info[MAX_OBJECTS]; +point_seg Point_segs[MAX_POINT_SEGS]; +point_seg *Point_segs_free_ptr = Point_segs; +ai_cloak_info Ai_cloak_info[MAX_AI_CLOAK_INFO]; +fix Boss_cloak_start_time = 0; +fix Boss_cloak_end_time = 0; +fix Last_teleport_time = 0; +fix Boss_teleport_interval = F1_0*8; +fix Boss_cloak_interval = F1_0*10; // Time between cloaks +fix Boss_cloak_duration = BOSS_CLOAK_DURATION; +fix Last_gate_time = 0; +fix Gate_interval = F1_0*6; +fix Boss_dying_start_time; +fix Boss_hit_time; +byte Boss_dying, Boss_dying_sound_playing, unused123, unused234; + +// -- MK, 10/21/95, unused! -- int Boss_been_hit=0; + + +// ---------- John: End of variables which must be saved as part of gamesave. ---------- + + +// -- ubyte Boss_cloaks[NUM_D2_BOSSES] = {1,1,1,1,1,1}; // Set byte if this boss can cloak + +ubyte Boss_teleports[NUM_D2_BOSSES] = {1,1,1,1,1,1, 1,1}; // Set byte if this boss can teleport +ubyte Boss_spew_more[NUM_D2_BOSSES] = {0,1,0,0,0,0, 0,0}; // If set, 50% of time, spew two bots. +ubyte Boss_spews_bots_energy[NUM_D2_BOSSES] = {1,1,0,1,0,1, 1,1}; // Set byte if boss spews bots when hit by energy weapon. +ubyte Boss_spews_bots_matter[NUM_D2_BOSSES] = {0,0,1,1,1,1, 0,1}; // Set byte if boss spews bots when hit by matter weapon. +ubyte Boss_invulnerable_energy[NUM_D2_BOSSES] = {0,0,1,1,0,0, 0,0}; // Set byte if boss is invulnerable to energy weapons. +ubyte Boss_invulnerable_matter[NUM_D2_BOSSES] = {0,0,0,0,1,1, 1,0}; // Set byte if boss is invulnerable to matter weapons. +ubyte Boss_invulnerable_spot[NUM_D2_BOSSES] = {0,0,0,0,0,1, 0,1}; // Set byte if boss is invulnerable in all but a certain spot. (Dot product fvec|vec_to_collision < BOSS_INVULNERABLE_DOT) + +int ai_evaded=0; + +// -- byte Super_boss_gate_list[MAX_GATE_INDEX] = {0, 1, 8, 9, 10, 11, 12, 15, 16, 18, 19, 20, 22, 0, 8, 11, 19, 20, 8, 20, 8}; + +int Robot_firing_enabled = 1; +int Animation_enabled = 1; + +#ifndef NDEBUG +int Ai_info_enabled=0; +#endif + + +// These globals are set by a call to find_vector_intersection, which is a slow routine, +// so we don't want to call it again (for this object) unless we have to. +vms_vector Hit_pos; +int Hit_type, Hit_seg; +fvi_info Hit_data; + +int Num_awareness_events = 0; +awareness_event Awareness_events[MAX_AWARENESS_EVENTS]; + +vms_vector Believed_player_pos; +int Believed_player_seg; + +#ifndef NDEBUG +// Index into this array with ailp->mode +char *mode_text[18] = { + "STILL", + "WANDER", + "FOL_PATH", + "CHASE_OBJ", + "RUN_FROM", + "BEHIND", + "FOL_PATH2", + "OPEN_DOOR", + "GOTO_PLR", + "GOTO_OBJ", + "SN_ATT", + "SN_FIRE", + "SN_RETR", + "SN_RTBK", + "SN_WAIT", + "TH_ATTACK", + "TH_RETREAT", + "TH_WAIT", + +}; + +// Index into this array with aip->behavior +char behavior_text[6][9] = { + "STILL ", + "NORMAL ", + "HIDE ", + "RUN_FROM", + "FOLPATH ", + "STATION " +}; + +// Index into this array with aip->GOAL_STATE or aip->CURRENT_STATE +char state_text[8][5] = { + "NONE", + "REST", + "SRCH", + "LOCK", + "FLIN", + "FIRE", + "RECO", + "ERR_", +}; + + +#endif + +// Current state indicates where the robot current is, or has just done. +// Transition table between states for an AI object. +// First dimension is trigger event. +// Second dimension is current state. +// Third dimension is goal state. +// Result is new goal state. +// ERR_ means something impossible has happened. +byte Ai_transition_table[AI_MAX_EVENT][AI_MAX_STATE][AI_MAX_STATE] = { + { + // Event = AIE_FIRE, a nearby object fired + // none rest srch lock flin fire reco // CURRENT is rows, GOAL is columns + { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, // none + { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, // rest + { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, // search + { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, // lock + { AIS_ERR_, AIS_REST, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FIRE, AIS_RECO}, // flinch + { AIS_ERR_, AIS_FIRE, AIS_FIRE, AIS_FIRE, AIS_FLIN, AIS_FIRE, AIS_RECO}, // fire + { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_FIRE} // recoil + }, + + // Event = AIE_HITT, a nearby object was hit (or a wall was hit) + { + { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, + { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, + { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, + { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, + { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FLIN}, + { AIS_ERR_, AIS_REST, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FIRE, AIS_RECO}, + { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_FIRE} + }, + + // Event = AIE_COLL, player collided with robot + { + { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, + { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, + { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, + { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, + { AIS_ERR_, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_LOCK, AIS_FLIN, AIS_FLIN}, + { AIS_ERR_, AIS_REST, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FIRE, AIS_RECO}, + { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_FIRE} + }, + + // Event = AIE_HURT, player hurt robot (by firing at and hitting it) + // Note, this doesn't necessarily mean the robot JUST got hit, only that that is the most recent thing that happened. + { + { AIS_ERR_, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN}, + { AIS_ERR_, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN}, + { AIS_ERR_, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN}, + { AIS_ERR_, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN}, + { AIS_ERR_, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN}, + { AIS_ERR_, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN}, + { AIS_ERR_, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN} + } +}; + + + +fix Dist_to_last_fired_upon_player_pos = 0; + +// -------------------------------------------------------------------------------------------------------------------- +void init_ai_frame(void) +{ + int ab_state; + + Dist_to_last_fired_upon_player_pos = vm_vec_dist_quick(&Last_fired_upon_player_pos, &Believed_player_pos); + + ab_state = Afterburner_charge && Controls.afterburner_state && (Players[Player_num].flags & PLAYER_FLAGS_AFTERBURNER); + + if (!(Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) || (Players[Player_num].flags & PLAYER_FLAGS_HEADLIGHT_ON) || ab_state) { + ai_do_cloak_stuff(); + } +} + +// -------------------------------------------------------------------------------------------------------------------- +// Return firing status. +// If ready to fire a weapon, return true, else return false. +// Ready to fire a weapon if next_fire <= 0 or next_fire2 <= 0. +int ready_to_fire(robot_info *robptr, ai_local *ailp) +{ + if (robptr->weapon_type2 != -1) + return (ailp->next_fire <= 0) || (ailp->next_fire2 <= 0); + else + return (ailp->next_fire <= 0); +} + +// -------------------------------------------------------------------------------------------------------------------- +// Make a robot near the player snipe. +#define MNRS_SEG_MAX 70 +void make_nearby_robot_snipe(void) +{ + int bfs_length, i; + short bfs_list[MNRS_SEG_MAX]; + + create_bfs_list(ConsoleObject->segnum, bfs_list, &bfs_length, MNRS_SEG_MAX); + + for (i=0; iid]; + + if ((objp->type == OBJ_ROBOT) && (objp->id != ROBOT_BRAIN)) { + if ((objp->ctype.ai_info.behavior != AIB_SNIPE) && (objp->ctype.ai_info.behavior != AIB_RUN_FROM) && !Robot_info[objp->id].boss_flag && !robptr->companion) { + objp->ctype.ai_info.behavior = AIB_SNIPE; + Ai_local_info[objnum].mode = AIM_SNIPE_ATTACK; + mprintf((0, "Making robot #%i go into snipe mode!\n", objnum)); + return; + } + } + objnum = objp->next; + } + } + + mprintf((0, "Couldn't find a robot to make snipe!\n")); + +} + +int Ai_last_missile_camera; + +int Robots_kill_robots_cheat = 0; + +// -------------------------------------------------------------------------------------------------------------------- +void do_ai_frame(object *obj) +{ + int objnum = obj-Objects; + ai_static *aip = &obj->ctype.ai_info; + ai_local *ailp = &Ai_local_info[objnum]; + fix dist_to_player; + vms_vector vec_to_player; + fix dot; + robot_info *robptr; + int player_visibility=-1; + int obj_ref; + int object_animates; + int new_goal_state; + int visibility_and_vec_computed = 0; + int previous_visibility; + vms_vector gun_point; + vms_vector vis_vec_pos; + + ailp->next_action_time -= FrameTime; + + if (aip->SKIP_AI_COUNT) { + aip->SKIP_AI_COUNT--; + if (obj->mtype.phys_info.flags & PF_USES_THRUST) { + obj->mtype.phys_info.rotthrust.x = (obj->mtype.phys_info.rotthrust.x * 15)/16; + obj->mtype.phys_info.rotthrust.y = (obj->mtype.phys_info.rotthrust.y * 15)/16; + obj->mtype.phys_info.rotthrust.z = (obj->mtype.phys_info.rotthrust.z * 15)/16; + if (!aip->SKIP_AI_COUNT) + obj->mtype.phys_info.flags &= ~PF_USES_THRUST; + } + return; + } + + robptr = &Robot_info[obj->id]; + Assert(robptr->always_0xabcd == 0xabcd); + + if (do_any_robot_dying_frame(obj)) + return; + + // Kind of a hack. If a robot is flinching, but it is time for it to fire, unflinch it. + // Else, you can turn a big nasty robot into a wimp by firing flares at it. + // This also allows the player to see the cool flinch effect for mechs without unbalancing the game. + if ((aip->GOAL_STATE == AIS_FLIN) && ready_to_fire(robptr, ailp)) { + aip->GOAL_STATE = AIS_FIRE; + } + +#ifndef NDEBUG + if ((aip->behavior == AIB_RUN_FROM) && (ailp->mode != AIM_RUN_FROM_OBJECT)) + Int3(); // This is peculiar. Behavior is run from, but mode is not. Contact Mike. + + mprintf_animation_info((obj)); + + if (!Do_ai_flag) + return; + + if (Break_on_object != -1) + if ((obj-Objects) == Break_on_object) + Int3(); // Contact Mike: This is a debug break +#endif + + // mprintf((0, "Object %i: behavior = %02x, mode = %i, awareness = %i, time = %7.3f\n", obj-Objects, aip->behavior, ailp->mode, ailp->player_awareness_type, f2fl(ailp->player_awareness_time))); + // mprintf((0, "Object %i: behavior = %02x, mode = %i, awareness = %i, cur=%i, goal=%i\n", obj-Objects, aip->behavior, ailp->mode, ailp->player_awareness_type, aip->CURRENT_STATE, aip->GOAL_STATE)); + +// Assert((aip->behavior >= MIN_BEHAVIOR) && (aip->behavior <= MAX_BEHAVIOR)); + if (!((aip->behavior >= MIN_BEHAVIOR) && (aip->behavior <= MAX_BEHAVIOR))) { + // mprintf((0, "Object %i behavior is %i, setting to AIB_NORMAL, fix in editor!\n", objnum, aip->behavior)); + aip->behavior = AIB_NORMAL; + } + + Assert(obj->segnum != -1); + Assert(obj->id < N_robot_types); + + obj_ref = objnum ^ FrameCount; + + if (ailp->next_fire > -F1_0*8) + ailp->next_fire -= FrameTime; + + if (robptr->weapon_type2 != -1) { + if (ailp->next_fire2 > -F1_0*8) + ailp->next_fire2 -= FrameTime; + } else + ailp->next_fire2 = F1_0*8; + + if (ailp->time_since_processed < F1_0*256) + ailp->time_since_processed += FrameTime; + + previous_visibility = ailp->previous_visibility; // Must get this before we toast the master copy! + + // -- (No robots have this behavior...) + // -- // Deal with cloaking for robots which are cloaked except just before firing. + // -- if (robptr->cloak_type == RI_CLOAKED_EXCEPT_FIRING) + // -- if (ailp->next_fire < F1_0/2) + // -- aip->CLOAKED = 1; + // -- else + // -- aip->CLOAKED = 0; + + // If only awake because of a camera, make that the believed player position. + if ((aip->SUB_FLAGS & SUB_FLAGS_CAMERA_AWAKE) && (Ai_last_missile_camera != -1)) + Believed_player_pos = Objects[Ai_last_missile_camera].pos; + else { + if (Robots_kill_robots_cheat) { + vis_vec_pos = obj->pos; + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + if (player_visibility) { + int ii, min_obj = -1; + fix min_dist = F1_0*200, cur_dist; + + for (ii=0; ii<=Highest_object_index; ii++) + if ((Objects[ii].type == OBJ_ROBOT) && (ii != objnum)) { + cur_dist = vm_vec_dist_quick(&obj->pos, &Objects[ii].pos); + + if (cur_dist < F1_0*100) + if (object_to_object_visibility(obj, &Objects[ii], FQ_TRANSWALL)) + if (cur_dist < min_dist) { + min_obj = ii; + min_dist = cur_dist; + } + } + if (min_obj != -1) { + Believed_player_pos = Objects[min_obj].pos; + Believed_player_seg = Objects[min_obj].segnum; + vm_vec_normalized_dir_quick(&vec_to_player, &Believed_player_pos, &obj->pos); + } else + goto _exit_cheat; + } else + goto _exit_cheat; + } else { +_exit_cheat: + visibility_and_vec_computed = 0; + if (!(Players[Player_num].flags & PLAYER_FLAGS_CLOAKED)) + Believed_player_pos = ConsoleObject->pos; + else + Believed_player_pos = Ai_cloak_info[objnum & (MAX_AI_CLOAK_INFO-1)].last_position; + } + } + dist_to_player = vm_vec_dist_quick(&Believed_player_pos, &obj->pos); +// if (robptr->companion) +// mprintf((0, "%3i: %3i %8.3f %8s %8s [%3i %4i]\n", objnum, obj->segnum, f2fl(dist_to_player), mode_text[ailp->mode], behavior_text[aip->behavior-0x80], aip->hide_index, aip->path_length)); + + // If this robot can fire, compute visibility from gun position. + // Don't want to compute visibility twice, as it is expensive. (So is call to calc_gun_point). + if ((previous_visibility || !(obj_ref & 3)) && ready_to_fire(robptr, ailp) && (dist_to_player < F1_0*200) && (robptr->n_guns) && !(robptr->attack_type)) { + // Since we passed ready_to_fire(), either next_fire or next_fire2 <= 0. calc_gun_point from relevant one. + // If both are <= 0, we will deal with the mess in ai_do_actual_firing_stuff + if (ailp->next_fire <= 0) + calc_gun_point(&gun_point, obj, aip->CURRENT_GUN); + else + calc_gun_point(&gun_point, obj, 0); + vis_vec_pos = gun_point; + } else { + vis_vec_pos = obj->pos; + vm_vec_zero(&gun_point); + // mprintf((0, "Visibility = %i, computed from center.\n", player_visibility)); + } + +// MK: Debugging, July 26, 1995! +// if (objnum == 1) +// { +// compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); +// mprintf((0, "Frame %i: dist=%7.3f, vecdot = %7.3f, mode=%i\n", FrameCount, f2fl(dist_to_player), f2fl(vm_vec_dot(&vec_to_player, &obj->orient.fvec)), ailp->mode)); +// } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Occasionally make non-still robots make a path to the player. Based on agitation and distance from player. + if ((aip->behavior != AIB_SNIPE) && (aip->behavior != AIB_RUN_FROM) && (aip->behavior != AIB_STILL) && !(Game_mode & GM_MULTI) && (robptr->companion != 1) && (robptr->thief != 1)) + if (Overall_agitation > 70) { + if ((dist_to_player < F1_0*200) && (d_rand() < FrameTime/4)) { + if (d_rand() * (Overall_agitation - 40) > F1_0*5) { + // -- mprintf((0, "(1) Object #%i going from still to path in frame %i.\n", objnum, FrameCount)); + create_path_to_player(obj, 4 + Overall_agitation/8 + Difficulty_level, 1); + return; + } + } + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // If retry count not 0, then add it into consecutive_retries. + // If it is 0, cut down consecutive_retries. + // This is largely a hack to speed up physics and deal with stupid AI. This is low level + // communication between systems of a sort that should not be done. + if ((ailp->retry_count) && !(Game_mode & GM_MULTI)) { + ailp->consecutive_retries += ailp->retry_count; + ailp->retry_count = 0; + if (ailp->consecutive_retries > 3) { + switch (ailp->mode) { + case AIM_GOTO_PLAYER: + // -- mprintf((0, "Buddy stuck going to player...\n")); + // -- Buddy_got_stuck = 1; + move_towards_segment_center(obj); + create_path_to_player(obj, 100, 1); + // -- Buddy_got_stuck = 0; + break; + case AIM_GOTO_OBJECT: + // -- mprintf((0, "Buddy stuck going to object...\n")); + Escort_goal_object = ESCORT_GOAL_UNSPECIFIED; +// if (obj->segnum == ConsoleObject->segnum) { +// if (Point_segs[aip->hide_index + aip->cur_path_index].segnum == obj->segnum) +// if ((aip->cur_path_index + aip->PATH_DIR >= 0) && (aip->cur_path_index + aip->PATH_DIR < aip->path_length-1)) +// aip->cur_path_index += aip->PATH_DIR; +// } + break; + case AIM_CHASE_OBJECT: + // -- mprintf((0, "(2) Object #%i, retries while chasing, creating path to player in frame %i\n", objnum, FrameCount)); + create_path_to_player(obj, 4 + Overall_agitation/8 + Difficulty_level, 1); + break; + case AIM_STILL: + if (robptr->attack_type) + move_towards_segment_center(obj); + else if (!((aip->behavior == AIB_STILL) || (aip->behavior == AIB_STATION) || (aip->behavior == AIB_FOLLOW))) // Behavior is still, so don't follow path. + attempt_to_resume_path(obj); + break; + case AIM_FOLLOW_PATH: + // mprintf((0, "Object %i following path got %i retries in frame %i\n", obj-Objects, ailp->consecutive_retries, FrameCount)); + if (Game_mode & GM_MULTI) { + ailp->mode = AIM_STILL; + } else + attempt_to_resume_path(obj); + break; + case AIM_RUN_FROM_OBJECT: + move_towards_segment_center(obj); + obj->mtype.phys_info.velocity.x = 0; + obj->mtype.phys_info.velocity.y = 0; + obj->mtype.phys_info.velocity.z = 0; + create_n_segment_path(obj, 5, -1); + ailp->mode = AIM_RUN_FROM_OBJECT; + break; + case AIM_BEHIND: + mprintf((0, "Hiding robot (%i) collided much.\n", obj-Objects)); + move_towards_segment_center(obj); + obj->mtype.phys_info.velocity.x = 0; + obj->mtype.phys_info.velocity.y = 0; + obj->mtype.phys_info.velocity.z = 0; + break; + case AIM_OPEN_DOOR: + create_n_segment_path_to_door(obj, 5, -1); + break; + #ifndef NDEBUG + case AIM_FOLLOW_PATH_2: + Int3(); // Should never happen! + break; + #endif + } + ailp->consecutive_retries = 0; + } + } else + ailp->consecutive_retries /= 2; + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // If in materialization center, exit + if (!(Game_mode & GM_MULTI) && (Segment2s[obj->segnum].special == SEGMENT_IS_ROBOTMAKER)) { + if (Station[Segment2s[obj->segnum].value].Enabled) { + ai_follow_path(obj, 1, 1, NULL); // 1 = player is visible, which might be a lie, but it works. + return; + } + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Decrease player awareness due to the passage of time. + if (ailp->player_awareness_type) { + if (ailp->player_awareness_time > 0) { + ailp->player_awareness_time -= FrameTime; + if (ailp->player_awareness_time <= 0) { + ailp->player_awareness_time = F1_0*2; //new: 11/05/94 + ailp->player_awareness_type--; //new: 11/05/94 + } + } else { + ailp->player_awareness_type--; + ailp->player_awareness_time = F1_0*2; + // aip->GOAL_STATE = AIS_REST; + } + } else + aip->GOAL_STATE = AIS_REST; //new: 12/13/94 + + + if (Player_is_dead && (ailp->player_awareness_type == 0)) + if ((dist_to_player < F1_0*200) && (d_rand() < FrameTime/8)) { + if ((aip->behavior != AIB_STILL) && (aip->behavior != AIB_RUN_FROM)) { + if (!ai_multiplayer_awareness(obj, 30)) + return; + #ifndef SHAREWARE + ai_multi_send_robot_position(objnum, -1); + #endif + + if (!((ailp->mode == AIM_FOLLOW_PATH) && (aip->cur_path_index < aip->path_length-1))) + if ((aip->behavior != AIB_SNIPE) && (aip->behavior != AIB_RUN_FROM)) { + if (dist_to_player < F1_0*30) + create_n_segment_path(obj, 5, 1); + else + create_path_to_player(obj, 20, 1); + } + } + } + +// -- // Make sure that if this guy got hit or bumped, then he's chasing player. +// -- if ((ailp->player_awareness_type == PA_WEAPON_ROBOT_COLLISION) || (ailp->player_awareness_type >= PA_PLAYER_COLLISION)) { +// -- if ((ailp->mode != AIM_BEHIND) && (aip->behavior != AIB_STILL) && (aip->behavior != AIB_SNIPE) && (aip->behavior != AIB_RUN_FROM) && (!robptr->companion) && (!robptr->thief) && (obj->id != ROBOT_BRAIN)) { +// -- ailp->mode = AIM_CHASE_OBJECT; +// -- ailp->player_awareness_type = 0; +// -- ailp->player_awareness_time = 0; +// -- } +// -- } + + // Make sure that if this guy got hit or bumped, then he's chasing player. + if ((ailp->player_awareness_type == PA_WEAPON_ROBOT_COLLISION) || (ailp->player_awareness_type >= PA_PLAYER_COLLISION)) { + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + if (player_visibility == 1) // Only increase visibility if unobstructed, else claw guys attack through doors. + player_visibility = 2; + } else if (((obj_ref&3) == 0) && !previous_visibility && (dist_to_player < F1_0*100)) { + fix sval, rval; + + rval = d_rand(); + sval = (dist_to_player * (Difficulty_level+1))/64; + + // -- mprintf((0, "Object #%3i: dist = %7.3f, rval = %8x, sval = %8x", obj-Objects, f2fl(dist_to_player), rval, sval)); + if ((fixmul(rval, sval) < FrameTime) || (Players[Player_num].flags & PLAYER_FLAGS_HEADLIGHT_ON)) { + ailp->player_awareness_type = PA_PLAYER_COLLISION; + ailp->player_awareness_time = F1_0*3; + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + if (player_visibility == 1) { + player_visibility = 2; + // -- mprintf((0, "...SWITCH!")); + } + } + + // -- mprintf((0, "\n")); + } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + if ((aip->GOAL_STATE == AIS_FLIN) && (aip->CURRENT_STATE == AIS_FLIN)) + aip->GOAL_STATE = AIS_LOCK; + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Note: Should only do these two function calls for objects which animate + if (Animation_enabled && (dist_to_player < F1_0*100)) { // && !(Game_mode & GM_MULTI)) { + object_animates = do_silly_animation(obj); + if (object_animates) + ai_frame_animation(obj); + //mprintf((0, "Object %i: goal=%i, current=%i\n", obj-Objects, obj->ctype.ai_info.GOAL_STATE, obj->ctype.ai_info.CURRENT_STATE)); + } else { + // If Object is supposed to animate, but we don't let it animate due to distance, then + // we must change its state, else it will never update. + aip->CURRENT_STATE = aip->GOAL_STATE; + object_animates = 0; // If we're not doing the animation, then should pretend it doesn't animate. + } + + switch (Robot_info[obj->id].boss_flag) { + case 0: + break; + + case 1: + case 2: + mprintf((1, "Warning: D1 boss detected. Not supported!\n")); + break; + + default: { + int pv; + fix dtp = dist_to_player/4; + + if (aip->GOAL_STATE == AIS_FLIN) + aip->GOAL_STATE = AIS_FIRE; + if (aip->CURRENT_STATE == AIS_FLIN) + aip->CURRENT_STATE = AIS_FIRE; + + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + + pv = player_visibility; + + // If player cloaked, visibility is screwed up and superboss will gate in robots when not supposed to. + if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) { + pv = 0; + dtp = vm_vec_dist_quick(&ConsoleObject->pos, &obj->pos)/4; + } + + do_boss_stuff(obj, pv); + } + break; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Time-slice, don't process all the time, purely an efficiency hack. + // Guys whose behavior is station and are not at their hide segment get processed anyway. + if (!((aip->behavior == AIB_SNIPE) && (ailp->mode != AIM_SNIPE_WAIT)) && !robptr->companion && !robptr->thief && (ailp->player_awareness_type < PA_WEAPON_ROBOT_COLLISION-1)) { // If robot got hit, he gets to attack player always! + #ifndef NDEBUG + if (Break_on_object != objnum) { // don't time slice if we're interested in this object. + #endif + if ((aip->behavior == AIB_STATION) && (ailp->mode == AIM_FOLLOW_PATH) && (aip->hide_segment != obj->segnum)) { + if (dist_to_player > F1_0*250) // station guys not at home always processed until 250 units away. + return; + } else if ((!ailp->previous_visibility) && ((dist_to_player >> 7) > ailp->time_since_processed)) { // 128 units away (6.4 segments) processed after 1 second. + if (robptr->thief) + mprintf((0, "T")); + return; + } + #ifndef NDEBUG + } + #endif + } + + // Reset time since processed, but skew objects so not everything processed synchronously, else + // we get fast frames with the occasional very slow frame. + // AI_proc_time = ailp->time_since_processed; + ailp->time_since_processed = - ((objnum & 0x03) * FrameTime ) / 2; + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Perform special ability + switch (obj->id) { + case ROBOT_BRAIN: + // Robots function nicely if behavior is Station. This means they won't move until they + // can see the player, at which time they will start wandering about opening doors. + if (ConsoleObject->segnum == obj->segnum) { + if (!ai_multiplayer_awareness(obj, 97)) + return; + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + move_away_from_player(obj, &vec_to_player, 0); + ai_multi_send_robot_position(objnum, -1); + } else if (ailp->mode != AIM_STILL) { + int r; + + r = openable_doors_in_segment(obj->segnum); + if (r != -1) { + ailp->mode = AIM_OPEN_DOOR; + aip->GOALSIDE = r; + } else if (ailp->mode != AIM_FOLLOW_PATH) { + if (!ai_multiplayer_awareness(obj, 50)) + return; + create_n_segment_path_to_door(obj, 8+Difficulty_level, -1); // third parameter is avoid_seg, -1 means avoid nothing. + ai_multi_send_robot_position(objnum, -1); + } + + if (ailp->next_action_time < 0) { + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + if (player_visibility) { + make_nearby_robot_snipe(); + ailp->next_action_time = (NDL - Difficulty_level) * 2*F1_0; + } + } + } else { + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + if (player_visibility) { + if (!ai_multiplayer_awareness(obj, 50)) + return; + create_n_segment_path_to_door(obj, 8+Difficulty_level, -1); // third parameter is avoid_seg, -1 means avoid nothing. + ai_multi_send_robot_position(objnum, -1); + } + } + break; + default: + break; + } + + if (aip->behavior == AIB_SNIPE) { + if ((Game_mode & GM_MULTI) && !robptr->thief) { + aip->behavior = AIB_NORMAL; + ailp->mode = AIM_CHASE_OBJECT; + return; + } + + if (!(obj_ref & 3) || previous_visibility) { + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + + // If this sniper is in still mode, if he was hit or can see player, switch to snipe mode. + if (ailp->mode == AIM_STILL) + if (player_visibility || (ailp->player_awareness_type == PA_WEAPON_ROBOT_COLLISION)) + ailp->mode = AIM_SNIPE_ATTACK; + + if (!robptr->thief && (ailp->mode != AIM_STILL)) + do_snipe_frame(obj, dist_to_player, player_visibility, &vec_to_player); + } else if (!robptr->thief && !robptr->companion) + return; + } + + // More special ability stuff, but based on a property of a robot, not its ID. + if (robptr->companion) { + + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + do_escort_frame(obj, dist_to_player, player_visibility); + + if (obj->ctype.ai_info.danger_laser_num != -1) { + object *dobjp = &Objects[obj->ctype.ai_info.danger_laser_num]; + + if ((dobjp->type == OBJ_WEAPON) && (dobjp->signature == obj->ctype.ai_info.danger_laser_signature)) { + fix circle_distance; + // -- mprintf((0, "Evading! ")); + circle_distance = robptr->circle_distance[Difficulty_level] + ConsoleObject->size; + ai_move_relative_to_player(obj, ailp, dist_to_player, &vec_to_player, circle_distance, 1, player_visibility); + } + } + + if (ready_to_fire(robptr, ailp)) { + int do_stuff = 0; + if (openable_doors_in_segment(obj->segnum) != -1) + do_stuff = 1; + else if (openable_doors_in_segment(Point_segs[aip->hide_index + aip->cur_path_index + aip->PATH_DIR].segnum) != -1) + do_stuff = 1; + else if (openable_doors_in_segment(Point_segs[aip->hide_index + aip->cur_path_index + 2*aip->PATH_DIR].segnum) != -1) + do_stuff = 1; + else if ((ailp->mode == AIM_GOTO_PLAYER) && (dist_to_player < 3*MIN_ESCORT_DISTANCE/2) && (vm_vec_dot(&ConsoleObject->orient.fvec, &vec_to_player) > -F1_0/4)) { + // mprintf((0, "Firing at player because dot = %7.3f\n", f2fl(vm_vec_dot(&ConsoleObject->orient.fvec, &vec_to_player)))); + do_stuff = 1; + } else + ; // mprintf((0, "Not Firing at player because dot = %7.3f, dist = %7.3f\n", f2fl(vm_vec_dot(&ConsoleObject->orient.fvec, &vec_to_player)), f2fl(dist_to_player))); + + if (do_stuff) { + Laser_create_new_easy( &obj->orient.fvec, &obj->pos, obj-Objects, FLARE_ID, 1); + ailp->next_fire = F1_0/2; + if (!Buddy_allowed_to_talk) // If buddy not talking, make him fire flares less often. + ailp->next_fire += d_rand()*4; + } + + } + } + + if (robptr->thief) { + + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + do_thief_frame(obj, dist_to_player, player_visibility, &vec_to_player); + + if (ready_to_fire(robptr, ailp)) { + int do_stuff = 0; + if (openable_doors_in_segment(obj->segnum) != -1) + do_stuff = 1; + else if (openable_doors_in_segment(Point_segs[aip->hide_index + aip->cur_path_index + aip->PATH_DIR].segnum) != -1) + do_stuff = 1; + else if (openable_doors_in_segment(Point_segs[aip->hide_index + aip->cur_path_index + 2*aip->PATH_DIR].segnum) != -1) + do_stuff = 1; + + if (do_stuff) { + // @mk, 05/08/95: Firing flare from center of object, this is dumb... + Laser_create_new_easy( &obj->orient.fvec, &obj->pos, obj-Objects, FLARE_ID, 1); + ailp->next_fire = F1_0/2; + if (Stolen_item_index == 0) // If never stolen an item, fire flares less often (bad: Stolen_item_index wraps, but big deal) + ailp->next_fire += d_rand()*4; + } + } + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + switch (ailp->mode) { + case AIM_CHASE_OBJECT: { // chasing player, sort of, chase if far, back off if close, circle in between + fix circle_distance; + + circle_distance = robptr->circle_distance[Difficulty_level] + ConsoleObject->size; + // Green guy doesn't get his circle distance boosted, else he might never attack. + if (robptr->attack_type != 1) + circle_distance += (objnum&0xf) * F1_0/2; + + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + + // @mk, 12/27/94, structure here was strange. Would do both clauses of what are now this if/then/else. Used to be if/then, if/then. + if ((player_visibility < 2) && (previous_visibility == 2)) { // this is redundant: mk, 01/15/95: && (ailp->mode == AIM_CHASE_OBJECT)) { + // -- mprintf((0, "I used to be able to see the player!\n")); + if (!ai_multiplayer_awareness(obj, 53)) { + if (maybe_ai_do_actual_firing_stuff(obj, aip)) + ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); + return; + } + // -- mprintf((0, "(3) Object #%i going from chase to player path in frame %i.\n", objnum, FrameCount)); + create_path_to_player(obj, 8, 1); + ai_multi_send_robot_position(objnum, -1); + } else if ((player_visibility == 0) && (dist_to_player > F1_0*80) && (!(Game_mode & GM_MULTI))) { + // If pretty far from the player, player cannot be seen (obstructed) and in chase mode, switch to follow path mode. + // This has one desirable benefit of avoiding physics retries. + if (aip->behavior == AIB_STATION) { + ailp->goal_segment = aip->hide_segment; + // -- mprintf((0, "(1) Object #%i going from chase to STATION in frame %i.\n", objnum, FrameCount)); + create_path_to_station(obj, 15); + } // -- this looks like a dumb thing to do...robots following paths far away from you! else create_n_segment_path(obj, 5, -1); + break; + } + + if ((aip->CURRENT_STATE == AIS_REST) && (aip->GOAL_STATE == AIS_REST)) { + if (player_visibility) { + if (d_rand() < FrameTime*player_visibility) { + if (dist_to_player/256 < d_rand()*player_visibility) { + // mprintf((0, "Object %i searching for player.\n", obj-Objects)); + aip->GOAL_STATE = AIS_SRCH; + aip->CURRENT_STATE = AIS_SRCH; + } + } + } + } + + if (GameTime - ailp->time_player_seen > CHASE_TIME_LENGTH) { + + if (Game_mode & GM_MULTI) + if (!player_visibility && (dist_to_player > F1_0*70)) { + ailp->mode = AIM_STILL; + return; + } + + if (!ai_multiplayer_awareness(obj, 64)) { + if (maybe_ai_do_actual_firing_stuff(obj, aip)) + ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); + return; + } + // -- bad idea, robots charge player they've never seen! -- mprintf((0, "(4) Object #%i going from chase to player path in frame %i.\n", objnum, FrameCount)); + // -- bad idea, robots charge player they've never seen! -- create_path_to_player(obj, 10, 1); + // -- bad idea, robots charge player they've never seen! -- ai_multi_send_robot_position(objnum, -1); + } else if ((aip->CURRENT_STATE != AIS_REST) && (aip->GOAL_STATE != AIS_REST)) { + if (!ai_multiplayer_awareness(obj, 70)) { + if (maybe_ai_do_actual_firing_stuff(obj, aip)) + ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); + return; + } + ai_move_relative_to_player(obj, ailp, dist_to_player, &vec_to_player, circle_distance, 0, player_visibility); + + if ((obj_ref & 1) && ((aip->GOAL_STATE == AIS_SRCH) || (aip->GOAL_STATE == AIS_LOCK))) { + if (player_visibility) // == 2) + ai_turn_towards_vector(&vec_to_player, obj, robptr->turn_time[Difficulty_level]); + } + + if (ai_evaded) { + ai_multi_send_robot_position(objnum, 1); + ai_evaded = 0; + } else + ai_multi_send_robot_position(objnum, -1); + + do_firing_stuff(obj, player_visibility, &vec_to_player); + } + break; + } + + case AIM_RUN_FROM_OBJECT: + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + + if (player_visibility) { + if (ailp->player_awareness_type == 0) + ailp->player_awareness_type = PA_WEAPON_ROBOT_COLLISION; + + } + + // If in multiplayer, only do if player visible. If not multiplayer, do always. + if (!(Game_mode & GM_MULTI) || player_visibility) + if (ai_multiplayer_awareness(obj, 75)) { + ai_follow_path(obj, player_visibility, previous_visibility, &vec_to_player); + ai_multi_send_robot_position(objnum, -1); + } + + if (aip->GOAL_STATE != AIS_FLIN) + aip->GOAL_STATE = AIS_LOCK; + else if (aip->CURRENT_STATE == AIS_FLIN) + aip->GOAL_STATE = AIS_LOCK; + + // Bad to let run_from robot fire at player because it will cause a war in which it turns towards the + // player to fire and then towards its goal to move. + // do_firing_stuff(obj, player_visibility, &vec_to_player); + // Instead, do this: + // (Note, only drop if player is visible. This prevents the bombs from being a giveaway, and + // also ensures that the robot is moving while it is dropping. Also means fewer will be dropped.) + if ((ailp->next_fire <= 0) && (player_visibility)) { + vms_vector fire_vec, fire_pos; + + if (!ai_multiplayer_awareness(obj, 75)) + return; + + fire_vec = obj->orient.fvec; + vm_vec_negate(&fire_vec); + vm_vec_add(&fire_pos, &obj->pos, &fire_vec); + + if (aip->SUB_FLAGS & SUB_FLAGS_SPROX) + Laser_create_new_easy( &fire_vec, &fire_pos, obj-Objects, ROBOT_SUPERPROX_ID, 1); + else + Laser_create_new_easy( &fire_vec, &fire_pos, obj-Objects, PROXIMITY_ID, 1); + + ailp->next_fire = (F1_0/2)*(NDL+5 - Difficulty_level); // Drop a proximity bomb every 5 seconds. + +#ifdef NETWORK + #ifndef SHAREWARE + if (Game_mode & GM_MULTI) + { + ai_multi_send_robot_position(obj-Objects, -1); + if (aip->SUB_FLAGS & SUB_FLAGS_SPROX) + multi_send_robot_fire(obj-Objects, -2, &fire_vec); + else + multi_send_robot_fire(obj-Objects, -1, &fire_vec); + } + #endif +#endif + } + break; + + case AIM_GOTO_PLAYER: + case AIM_GOTO_OBJECT: + ai_follow_path(obj, 2, previous_visibility, &vec_to_player); // Follows path as if player can see robot. + ai_multi_send_robot_position(objnum, -1); + break; + + case AIM_FOLLOW_PATH: { + int anger_level = 65; + + if (aip->behavior == AIB_STATION) + if (Point_segs[aip->hide_index + aip->path_length - 1].segnum == aip->hide_segment) { + anger_level = 64; + // mprintf((0, "Object %i, station, lowering anger to 64.\n")); + } + + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + + if (Game_mode & (GM_MODEM | GM_SERIAL)) + if (!player_visibility && (dist_to_player > F1_0*70)) { + ailp->mode = AIM_STILL; + return; + } + + if (!ai_multiplayer_awareness(obj, anger_level)) { + if (maybe_ai_do_actual_firing_stuff(obj, aip)) { + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); + } + return; + } + + ai_follow_path(obj, player_visibility, previous_visibility, &vec_to_player); + + if (aip->GOAL_STATE != AIS_FLIN) + aip->GOAL_STATE = AIS_LOCK; + else if (aip->CURRENT_STATE == AIS_FLIN) + aip->GOAL_STATE = AIS_LOCK; + + if (aip->behavior != AIB_RUN_FROM) + do_firing_stuff(obj, player_visibility, &vec_to_player); + + if ((player_visibility == 2) && (aip->behavior != AIB_SNIPE) && (aip->behavior != AIB_FOLLOW) && (aip->behavior != AIB_RUN_FROM) && (obj->id != ROBOT_BRAIN) && (robptr->companion != 1) && (robptr->thief != 1)) { + if (robptr->attack_type == 0) + ailp->mode = AIM_CHASE_OBJECT; + // This should not just be distance based, but also time-since-player-seen based. + } else if ((dist_to_player > F1_0*(20*(2*Difficulty_level + robptr->pursuit))) + && (GameTime - ailp->time_player_seen > (F1_0/2*(Difficulty_level+robptr->pursuit))) + && (player_visibility == 0) + && (aip->behavior == AIB_NORMAL) + && (ailp->mode == AIM_FOLLOW_PATH)) { + ailp->mode = AIM_STILL; + aip->hide_index = -1; + aip->path_length = 0; + } + + ai_multi_send_robot_position(objnum, -1); + + break; + } + + case AIM_BEHIND: + if (!ai_multiplayer_awareness(obj, 71)) { + if (maybe_ai_do_actual_firing_stuff(obj, aip)) { + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); + } + return; + } + + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + + if (player_visibility == 2) { + // Get behind the player. + // Method: + // If vec_to_player dot player_rear_vector > 0, behind is goal. + // Else choose goal with larger dot from left, right. + vms_vector goal_point, goal_vector, vec_to_goal, rand_vec; + fix dot; + + dot = vm_vec_dot(&ConsoleObject->orient.fvec, &vec_to_player); + if (dot > 0) { // Remember, we're interested in the rear vector dot being < 0. + goal_vector = ConsoleObject->orient.fvec; + vm_vec_negate(&goal_vector); + // -- mprintf((0, "Goal is BEHIND\n")); + } else { + fix dot; + dot = vm_vec_dot(&ConsoleObject->orient.rvec, &vec_to_player); + goal_vector = ConsoleObject->orient.rvec; + if (dot > 0) { + vm_vec_negate(&goal_vector); + // -- mprintf((0, "Goal is LEFT\n")); + } else + ; // -- mprintf((0, "Goal is RIGHT\n")); + } + + vm_vec_scale(&goal_vector, 2*(ConsoleObject->size + obj->size + (((objnum*4 + FrameCount) & 63) << 12))); + vm_vec_add(&goal_point, &ConsoleObject->pos, &goal_vector); + make_random_vector(&rand_vec); + vm_vec_scale_add2(&goal_point, &rand_vec, F1_0*8); + vm_vec_sub(&vec_to_goal, &goal_point, &obj->pos); + vm_vec_normalize_quick(&vec_to_goal); + move_towards_vector(obj, &vec_to_goal, 0); + ai_turn_towards_vector(&vec_to_player, obj, robptr->turn_time[Difficulty_level]); + ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); + } + + if (aip->GOAL_STATE != AIS_FLIN) + aip->GOAL_STATE = AIS_LOCK; + else if (aip->CURRENT_STATE == AIS_FLIN) + aip->GOAL_STATE = AIS_LOCK; + + ai_multi_send_robot_position(objnum, -1); + break; + + case AIM_STILL: + if ((dist_to_player < F1_0*120+Difficulty_level*F1_0*20) || (ailp->player_awareness_type >= PA_WEAPON_ROBOT_COLLISION-1)) { + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + + // turn towards vector if visible this time or last time, or rand + // new! + if ((player_visibility == 2) || (previous_visibility == 2)) { // -- MK, 06/09/95: || ((d_rand() > 0x4000) && !(Game_mode & GM_MULTI))) { + if (!ai_multiplayer_awareness(obj, 71)) { + if (maybe_ai_do_actual_firing_stuff(obj, aip)) + ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); + return; + } + ai_turn_towards_vector(&vec_to_player, obj, robptr->turn_time[Difficulty_level]); + ai_multi_send_robot_position(objnum, -1); + } + + do_firing_stuff(obj, player_visibility, &vec_to_player); + if (player_visibility == 2) { // Changed @mk, 09/21/95: Require that they be looking to evade. Change, MK, 01/03/95 for Multiplayer reasons. If robots can't see you (even with eyes on back of head), then don't do evasion. + if (robptr->attack_type == 1) { + aip->behavior = AIB_NORMAL; + if (!ai_multiplayer_awareness(obj, 80)) { + if (maybe_ai_do_actual_firing_stuff(obj, aip)) + ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); + return; + } + ai_move_relative_to_player(obj, ailp, dist_to_player, &vec_to_player, 0, 0, player_visibility); + if (ai_evaded) { + ai_multi_send_robot_position(objnum, 1); + ai_evaded = 0; + } + else + ai_multi_send_robot_position(objnum, -1); + } else { + // Robots in hover mode are allowed to evade at half normal speed. + if (!ai_multiplayer_awareness(obj, 81)) { + if (maybe_ai_do_actual_firing_stuff(obj, aip)) + ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); + return; + } + ai_move_relative_to_player(obj, ailp, dist_to_player, &vec_to_player, 0, 1, player_visibility); + if (ai_evaded) { + ai_multi_send_robot_position(objnum, -1); + ai_evaded = 0; + } + else + ai_multi_send_robot_position(objnum, -1); + } + } else if ((obj->segnum != aip->hide_segment) && (dist_to_player > F1_0*80) && (!(Game_mode & GM_MULTI))) { + // If pretty far from the player, player cannot be seen (obstructed) and in chase mode, switch to follow path mode. + // This has one desirable benefit of avoiding physics retries. + if (aip->behavior == AIB_STATION) { + ailp->goal_segment = aip->hide_segment; + // -- mprintf((0, "(2) Object #%i going from STILL to STATION in frame %i.\n", objnum, FrameCount)); + create_path_to_station(obj, 15); + } + break; + } + } + + break; + case AIM_OPEN_DOOR: { // trying to open a door. + vms_vector center_point, goal_vector; + Assert(obj->id == ROBOT_BRAIN); // Make sure this guy is allowed to be in this mode. + + if (!ai_multiplayer_awareness(obj, 62)) + return; + compute_center_point_on_side(¢er_point, &Segments[obj->segnum], aip->GOALSIDE); + vm_vec_sub(&goal_vector, ¢er_point, &obj->pos); + vm_vec_normalize_quick(&goal_vector); + ai_turn_towards_vector(&goal_vector, obj, robptr->turn_time[Difficulty_level]); + move_towards_vector(obj, &goal_vector, 0); + ai_multi_send_robot_position(objnum, -1); + + break; + } + + case AIM_SNIPE_WAIT: + break; + case AIM_SNIPE_RETREAT: + // -- if (ai_multiplayer_awareness(obj, 53)) + // -- if (ailp->next_fire < -F1_0) + // -- ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); + break; + case AIM_SNIPE_RETREAT_BACKWARDS: + case AIM_SNIPE_ATTACK: + case AIM_SNIPE_FIRE: + if (ai_multiplayer_awareness(obj, 53)) { + ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); + if (robptr->thief) + ai_move_relative_to_player(obj, ailp, dist_to_player, &vec_to_player, 0, 0, player_visibility); + break; + } + break; + + case AIM_THIEF_WAIT: + case AIM_THIEF_ATTACK: + case AIM_THIEF_RETREAT: + case AIM_WANDER: // Used for Buddy Bot + break; + + default: + mprintf((0, "Unknown mode = %i in robot %i, behavior = %i\n", ailp->mode, obj-Objects, aip->behavior)); + ailp->mode = AIM_CHASE_OBJECT; + break; + } // end: switch (ailp->mode) { + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // If the robot can see you, increase his awareness of you. + // This prevents the problem of a robot looking right at you but doing nothing. + // Assert(player_visibility != -1); // Means it didn't get initialized! + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + if ((player_visibility == 2) && (aip->behavior != AIB_FOLLOW) && (!robptr->thief)) { + if ((ailp->player_awareness_type == 0) && (aip->SUB_FLAGS & SUB_FLAGS_CAMERA_AWAKE)) + aip->SUB_FLAGS &= ~SUB_FLAGS_CAMERA_AWAKE; + else if (ailp->player_awareness_type == 0) + ailp->player_awareness_type = PA_PLAYER_COLLISION; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + if (!object_animates) { + aip->CURRENT_STATE = aip->GOAL_STATE; + // mprintf((0, "Setting current to goal (%i) because object doesn't animate.\n", aip->GOAL_STATE)); + } + + Assert(ailp->player_awareness_type <= AIE_MAX); + Assert(aip->CURRENT_STATE < AIS_MAX); + Assert(aip->GOAL_STATE < AIS_MAX); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + if (ailp->player_awareness_type) { + new_goal_state = Ai_transition_table[ailp->player_awareness_type-1][aip->CURRENT_STATE][aip->GOAL_STATE]; + if (ailp->player_awareness_type == PA_WEAPON_ROBOT_COLLISION) { + // Decrease awareness, else this robot will flinch every frame. + ailp->player_awareness_type--; + ailp->player_awareness_time = F1_0*3; + } + + if (new_goal_state == AIS_ERR_) + new_goal_state = AIS_REST; + + if (aip->CURRENT_STATE == AIS_NONE) + aip->CURRENT_STATE = AIS_REST; + + aip->GOAL_STATE = new_goal_state; + + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // If new state = fire, then set all gun states to fire. + if ((aip->GOAL_STATE == AIS_FIRE) ) { + int i,num_guns; + num_guns = Robot_info[obj->id].n_guns; + for (i=0; igoal_state[i] = AIS_FIRE; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Hack by mk on 01/04/94, if a guy hasn't animated to the firing state, but his next_fire says ok to fire, bash him there + if (ready_to_fire(robptr, ailp) && (aip->GOAL_STATE == AIS_FIRE)) + aip->CURRENT_STATE = AIS_FIRE; + + if ((aip->GOAL_STATE != AIS_FLIN) && (obj->id != ROBOT_BRAIN)) { + switch (aip->CURRENT_STATE) { + case AIS_NONE: + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + + dot = vm_vec_dot(&obj->orient.fvec, &vec_to_player); + if (dot >= F1_0/2) + if (aip->GOAL_STATE == AIS_REST) + aip->GOAL_STATE = AIS_SRCH; + break; + case AIS_REST: + if (aip->GOAL_STATE == AIS_REST) { + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + if (ready_to_fire(robptr, ailp) && (player_visibility)) { + // mprintf((0, "Setting goal state to fire from rest.\n")); + aip->GOAL_STATE = AIS_FIRE; + } + } + break; + case AIS_SRCH: + if (!ai_multiplayer_awareness(obj, 60)) + return; + + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + + if (player_visibility == 2) { + ai_turn_towards_vector(&vec_to_player, obj, robptr->turn_time[Difficulty_level]); + ai_multi_send_robot_position(objnum, -1); + } + break; + case AIS_LOCK: + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + + if (!(Game_mode & GM_MULTI) || (player_visibility)) { + if (!ai_multiplayer_awareness(obj, 68)) + return; + + if (player_visibility == 2) { // @mk, 09/21/95, require that they be looking towards you to turn towards you. + ai_turn_towards_vector(&vec_to_player, obj, robptr->turn_time[Difficulty_level]); + ai_multi_send_robot_position(objnum, -1); + } + } + break; + case AIS_FIRE: + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + + if (player_visibility == 2) { + if (!ai_multiplayer_awareness(obj, (ROBOT_FIRE_AGITATION-1))) { + if (Game_mode & GM_MULTI) { + ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); + return; + } + } + ai_turn_towards_vector(&vec_to_player, obj, robptr->turn_time[Difficulty_level]); + ai_multi_send_robot_position(objnum, -1); + } + + // Fire at player, if appropriate. + ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); + + break; + case AIS_RECO: + if (!(obj_ref & 3)) { + compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); + if (player_visibility == 2) { + if (!ai_multiplayer_awareness(obj, 69)) + return; + ai_turn_towards_vector(&vec_to_player, obj, robptr->turn_time[Difficulty_level]); + ai_multi_send_robot_position(objnum, -1); + } // -- MK, 06/09/95: else if (!(Game_mode & GM_MULTI)) { + } + break; + case AIS_FLIN: + // mprintf((0, "State = flinch, goal = %i.\n", aip->GOAL_STATE)); + break; + default: + mprintf((1, "Unknown mode for AI object #%i\n", objnum)); + aip->GOAL_STATE = AIS_REST; + aip->CURRENT_STATE = AIS_REST; + break; + } + } // end of: if (aip->GOAL_STATE != AIS_FLIN) { + + // Switch to next gun for next fire. + if (player_visibility == 0) { + aip->CURRENT_GUN++; + if (aip->CURRENT_GUN >= Robot_info[obj->id].n_guns) + { + if ((robptr->n_guns == 1) || (robptr->weapon_type2 == -1)) // Two weapon types hack. + aip->CURRENT_GUN = 0; + else + aip->CURRENT_GUN = 1; + } + } + +} + +// ----------------------------------------------------------------------------------- +void ai_do_cloak_stuff(void) +{ + int i; + + for (i=0; ipos; + Ai_cloak_info[i].last_segment = ConsoleObject->segnum; + Ai_cloak_info[i].last_time = GameTime; + } + + // Make work for control centers. + Believed_player_pos = Ai_cloak_info[0].last_position; + Believed_player_seg = Ai_cloak_info[0].last_segment; + +} + +// ----------------------------------------------------------------------------------- +// Returns false if awareness is considered too puny to add, else returns true. +int add_awareness_event(object *objp, int type) +{ + // If player cloaked and hit a robot, then increase awareness + if ((type == PA_WEAPON_ROBOT_COLLISION) || (type == PA_WEAPON_WALL_COLLISION) || (type == PA_PLAYER_COLLISION)) + ai_do_cloak_stuff(); + + if (Num_awareness_events < MAX_AWARENESS_EVENTS) { + if ((type == PA_WEAPON_WALL_COLLISION) || (type == PA_WEAPON_ROBOT_COLLISION)) + if (objp->id == VULCAN_ID) + if (d_rand() > 3276) + return 0; // For vulcan cannon, only about 1/10 actually cause awareness + + Awareness_events[Num_awareness_events].segnum = objp->segnum; + Awareness_events[Num_awareness_events].pos = objp->pos; + Awareness_events[Num_awareness_events].type = type; + Num_awareness_events++; + } else { +// Int3(); // Hey -- Overflowed Awareness_events, make more or something + // This just gets ignored, so you can just continue. + } + return 1; + +} + +// ---------------------------------------------------------------------------------- +// Robots will become aware of the player based on something that occurred. +// The object (probably player or weapon) which created the awareness is objp. +void create_awareness_event(object *objp, int type) +{ + // If not in multiplayer, or in multiplayer with robots, do this, else unnecessary! + if (!(Game_mode & GM_MULTI) || (Game_mode & GM_MULTI_ROBOTS)) { + if (add_awareness_event(objp, type)) { + if (((d_rand() * (type+4)) >> 15) > 4) + Overall_agitation++; + if (Overall_agitation > OVERALL_AGITATION_MAX) + Overall_agitation = OVERALL_AGITATION_MAX; + } + } +} + +byte New_awareness[MAX_SEGMENTS]; + +// ---------------------------------------------------------------------------------- +void pae_aux(int segnum, int type, int level) +{ + int j; + + if (New_awareness[segnum] < type) + New_awareness[segnum] = type; + + // Process children. + for (j=0; j Ai_local_info[i].player_awareness_type) { + Ai_local_info[i].player_awareness_type = New_awareness[Objects[i].segnum]; + Ai_local_info[i].player_awareness_time = PLAYER_AWARENESS_INITIAL_TIME; + } + + // Clear the bit that says this robot is only awake because a camera woke it up. + if (New_awareness[Objects[i].segnum] > Ai_local_info[i].player_awareness_type) + Objects[i].ctype.ai_info.SUB_FLAGS &= ~SUB_FLAGS_CAMERA_AWAKE; + } +} + +#ifndef NDEBUG +int Ai_dump_enable = 0; + +FILE *Ai_dump_file = NULL; + +char Ai_error_message[128] = ""; + +// ---------------------------------------------------------------------------------- +void force_dump_ai_objects_all(char *msg) +{ + int tsave; + + tsave = Ai_dump_enable; + + Ai_dump_enable = 1; + + sprintf(Ai_error_message, "%s\n", msg); + //dump_ai_objects_all(); + Ai_error_message[0] = 0; + + Ai_dump_enable = tsave; +} + +// ---------------------------------------------------------------------------------- +void turn_off_ai_dump(void) +{ + if (Ai_dump_file != NULL) + fclose(Ai_dump_file); + + Ai_dump_file = NULL; +} + +#endif + +extern void do_boss_dying_frame(object *objp); + +// ---------------------------------------------------------------------------------- +// Do things which need to get done for all AI objects each frame. +// This includes: +// Setting player_awareness (a fix, time in seconds which object is aware of player) +void do_ai_frame_all(void) +{ +#ifndef NDEBUG + //dump_ai_objects_all(); +#endif + + set_player_awareness_all(); + + if (Ai_last_missile_camera != -1) { + // Clear if supposed misisle camera is not a weapon, or just every so often, just in case. + if (((FrameCount & 0x0f) == 0) || (Objects[Ai_last_missile_camera].type != OBJ_WEAPON)) { + int i; + + Ai_last_missile_camera = -1; + for (i=0; i<=Highest_object_index; i++) + if (Objects[i].type == OBJ_ROBOT) + Objects[i].ctype.ai_info.SUB_FLAGS &= ~SUB_FLAGS_CAMERA_AWAKE; + } + } + + // (Moved here from do_boss_stuff() because that only gets called if robot aware of player.) + if (Boss_dying) { + int i; + + for (i=0; i<=Highest_object_index; i++) + if (Objects[i].type == OBJ_ROBOT) + if (Robot_info[Objects[i].id].boss_flag) + do_boss_dying_frame(&Objects[i]); + } +} + + +extern int Final_boss_is_dead; +extern fix Boss_invulnerable_dot; + +// Initializations to be performed for all robots for a new level. +void init_robots_for_level(void) +{ + Overall_agitation = 0; + Final_boss_is_dead=0; + + Buddy_objnum = 0; + Buddy_allowed_to_talk = 0; + + Boss_invulnerable_dot = F1_0/4 - i2f(Difficulty_level)/8; + Boss_dying_start_time = 0; +} + +int ai_save_state( FILE * fp ) +{ + fwrite( &Ai_initialized, sizeof(int), 1, fp ); + fwrite( &Overall_agitation, sizeof(int), 1, fp ); + fwrite( Ai_local_info, sizeof(ai_local)*MAX_OBJECTS, 1, fp ); + fwrite( Point_segs, sizeof(point_seg)*MAX_POINT_SEGS, 1, fp ); + fwrite( Ai_cloak_info, sizeof(ai_cloak_info)*MAX_AI_CLOAK_INFO, 1, fp ); + fwrite( &Boss_cloak_start_time, sizeof(fix), 1, fp ); + fwrite( &Boss_cloak_end_time , sizeof(fix), 1, fp ); + fwrite( &Last_teleport_time , sizeof(fix), 1, fp ); + fwrite( &Boss_teleport_interval, sizeof(fix), 1, fp ); + fwrite( &Boss_cloak_interval, sizeof(fix), 1, fp ); + fwrite( &Boss_cloak_duration, sizeof(fix), 1, fp ); + fwrite( &Last_gate_time, sizeof(fix), 1, fp ); + fwrite( &Gate_interval, sizeof(fix), 1, fp ); + fwrite( &Boss_dying_start_time, sizeof(fix), 1, fp ); + fwrite( &Boss_dying, sizeof(int), 1, fp ); + fwrite( &Boss_dying_sound_playing, sizeof(int), 1, fp ); + fwrite( &Boss_hit_time, sizeof(fix), 1, fp ); + // -- MK, 10/21/95, unused! -- fwrite( &Boss_been_hit, sizeof(int), 1, fp ); + + fwrite( &Escort_kill_object, sizeof(Escort_kill_object), 1, fp); + fwrite( &Escort_last_path_created, sizeof(Escort_last_path_created), 1, fp); + fwrite( &Escort_goal_object, sizeof(Escort_goal_object), 1, fp); + fwrite( &Escort_special_goal, sizeof(Escort_special_goal), 1, fp); + fwrite( &Escort_goal_index, sizeof(Escort_goal_index), 1, fp); + fwrite( &Stolen_items, sizeof(Stolen_items[0])*MAX_STOLEN_ITEMS, 1, fp); + + { int temp; + temp = Point_segs_free_ptr - Point_segs; + fwrite( &temp, sizeof(int), 1, fp ); + } + + fwrite(&Num_boss_teleport_segs, sizeof(Num_boss_teleport_segs), 1, fp); + fwrite(&Num_boss_gate_segs, sizeof(Num_boss_gate_segs), 1, fp); + + if (Num_boss_gate_segs) + fwrite(Boss_gate_segs, sizeof(Boss_gate_segs[0]), Num_boss_gate_segs, fp); + + if (Num_boss_teleport_segs) + fwrite(Boss_teleport_segs, sizeof(Boss_teleport_segs[0]), Num_boss_teleport_segs, fp); + + return 1; +} + +int ai_restore_state( FILE * fp, int version ) +{ + fread( &Ai_initialized, sizeof(int), 1, fp ); + fread( &Overall_agitation, sizeof(int), 1, fp ); + fread( Ai_local_info, sizeof(ai_local)*MAX_OBJECTS, 1, fp ); + fread( Point_segs, sizeof(point_seg)*MAX_POINT_SEGS, 1, fp ); + fread( Ai_cloak_info, sizeof(ai_cloak_info)*MAX_AI_CLOAK_INFO, 1, fp ); + fread( &Boss_cloak_start_time, sizeof(fix), 1, fp ); + fread( &Boss_cloak_end_time , sizeof(fix), 1, fp ); + fread( &Last_teleport_time , sizeof(fix), 1, fp ); + fread( &Boss_teleport_interval, sizeof(fix), 1, fp ); + fread( &Boss_cloak_interval, sizeof(fix), 1, fp ); + fread( &Boss_cloak_duration, sizeof(fix), 1, fp ); + fread( &Last_gate_time, sizeof(fix), 1, fp ); + fread( &Gate_interval, sizeof(fix), 1, fp ); + fread( &Boss_dying_start_time, sizeof(fix), 1, fp ); + fread( &Boss_dying, sizeof(int), 1, fp ); + fread( &Boss_dying_sound_playing, sizeof(int), 1, fp ); + fread( &Boss_hit_time, sizeof(fix), 1, fp ); + // -- MK, 10/21/95, unused! -- fread( &Boss_been_hit, sizeof(int), 1, fp ); + + if (version >= 8) { + fread( &Escort_kill_object, sizeof(Escort_kill_object), 1, fp); + fread( &Escort_last_path_created, sizeof(Escort_last_path_created), 1, fp); + fread( &Escort_goal_object, sizeof(Escort_goal_object), 1, fp); + fread( &Escort_special_goal, sizeof(Escort_special_goal), 1, fp); + fread( &Escort_goal_index, sizeof(Escort_goal_index), 1, fp); + fread( &Stolen_items, sizeof(Stolen_items[0])*MAX_STOLEN_ITEMS, 1, fp); + } else { + int i; + + Escort_kill_object = -1; + Escort_last_path_created = 0; + Escort_goal_object = ESCORT_GOAL_UNSPECIFIED; + Escort_special_goal = -1; + Escort_goal_index = -1; + + for (i=0; i= 15) { + int temp; + fread( &temp, sizeof(int), 1, fp ); + Point_segs_free_ptr = &Point_segs[temp]; + } else + ai_reset_all_paths(); + + if (version >= 21) { + fread(&Num_boss_teleport_segs, sizeof(Num_boss_teleport_segs), 1, fp); + fread(&Num_boss_gate_segs, sizeof(Num_boss_gate_segs), 1, fp); + + if (Num_boss_gate_segs) + fread(Boss_gate_segs, sizeof(Boss_gate_segs[0]), Num_boss_gate_segs, fp); + + if (Num_boss_teleport_segs) + fread(Boss_teleport_segs, sizeof(Boss_teleport_segs[0]), Num_boss_teleport_segs, fp); + } else { + // -- Num_boss_teleport_segs = 1; + // -- Num_boss_gate_segs = 1; + // -- Boss_teleport_segs[0] = 0; + // -- Boss_gate_segs[0] = 0; + // Note: Maybe better to leave alone...will probably be ok. + mprintf((1, "Warning: If you fight the boss, he might teleport to segment #0!\n")); + } + + + return 1; +} diff --git a/main/ai.h b/main/ai.h new file mode 100644 index 00000000..057715ab --- /dev/null +++ b/main/ai.h @@ -0,0 +1,336 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + +#ifndef _AI_H +#define _AI_H + +#include + +#include "object.h" +#include "fvi.h" +#include "robot.h" + +#define PLAYER_AWARENESS_INITIAL_TIME (3*F1_0) +#define MAX_PATH_LENGTH 30 // Maximum length of path in ai path following. +#define MAX_DEPTH_TO_SEARCH_FOR_PLAYER 10 +#define BOSS_GATE_MATCEN_NUM -1 +#define MAX_BOSS_TELEPORT_SEGS 100 +#define BOSS_ECLIP_NUM 53 + +#define ROBOT_BRAIN 7 +#define ROBOT_BOSS1 17 + +#define ROBOT_FIRE_AGITATION 94 + +#define BOSS_D2 21 // Minimum D2 boss value. +#define BOSS_COOL 21 +#define BOSS_WATER 22 +#define BOSS_FIRE 23 +#define BOSS_ICE 24 +#define BOSS_ALIEN1 25 +#define BOSS_ALIEN2 26 + +#define NUM_D2_BOSSES 8 + +extern ubyte Boss_teleports[NUM_D2_BOSSES]; // Set byte if this boss can teleport +extern ubyte Boss_spew_more[NUM_D2_BOSSES]; // Set byte if this boss can teleport +//extern ubyte Boss_cloaks[NUM_D2_BOSSES]; // Set byte if this boss can cloak +extern ubyte Boss_spews_bots_energy[NUM_D2_BOSSES]; // Set byte if boss spews bots when hit by energy weapon. +extern ubyte Boss_spews_bots_matter[NUM_D2_BOSSES]; // Set byte if boss spews bots when hit by matter weapon. +extern ubyte Boss_invulnerable_energy[NUM_D2_BOSSES]; // Set byte if boss is invulnerable to energy weapons. +extern ubyte Boss_invulnerable_matter[NUM_D2_BOSSES]; // Set byte if boss is invulnerable to matter weapons. +extern ubyte Boss_invulnerable_spot[NUM_D2_BOSSES]; // Set byte if boss is invulnerable in all but a certain spot. (Dot product fvec|vec_to_collision < BOSS_INVULNERABLE_DOT) + +extern fix Boss_cloak_start_time, Boss_cloak_end_time; +extern int Num_boss_teleport_segs; +extern short Boss_teleport_segs[MAX_BOSS_TELEPORT_SEGS]; +extern fix Last_teleport_time; +extern fix Boss_cloak_duration; + +extern ai_local Ai_local_info[MAX_OBJECTS]; +extern vms_vector Believed_player_pos; +extern int Believed_player_seg; + +extern void move_towards_segment_center(object *objp); +extern int gate_in_robot(int type, int segnum); +extern void do_ai_movement(object *objp); +extern void ai_move_to_new_segment( object * obj, short newseg, int first_time ); +// extern void ai_follow_path( object * obj, short newseg, int first_time ); +extern void ai_recover_from_wall_hit(object *obj, int segnum); +extern void ai_move_one(object *objp); +extern void do_ai_frame(object *objp); +extern void init_ai_object(int objnum, int initial_mode, int hide_segment); +extern void update_player_awareness(object *objp, fix new_awareness); +extern void create_awareness_event(object *objp, int type); // object *objp can create awareness of player, amount based on "type" +extern void do_ai_frame_all(void); +extern void init_ai_system(void); +extern void reset_ai_states(object *objp); +extern int create_path_points(object *objp, int start_seg, int end_seg, point_seg *point_segs, short *num_points, int max_depth, int random_flag, int safety_flag, int avoid_seg); +extern void create_all_paths(void); +extern void create_path_to_station(object *objp, int max_length); +extern void ai_follow_path(object *objp, int player_visibility, int previous_visibility, vms_vector *vec_to_player); +extern void ai_turn_towards_vector(vms_vector *vec_to_player, object *obj, fix rate); +extern void ai_turn_towards_vel_vec(object *objp, fix rate); +extern void init_ai_objects(void); +extern void do_ai_robot_hit(object *robot, int type); +extern void create_n_segment_path(object *objp, int path_length, int avoid_seg); +extern void create_n_segment_path_to_door(object *objp, int path_length, int avoid_seg); +extern void make_random_vector(vms_vector *vec); +extern void init_robots_for_level(void); +extern int ai_behavior_to_mode(int behavior); +extern int Robot_firing_enabled; +extern void create_path_to_segment(object *objp, int goalseg, int max_length, int safety_flag); +extern int ready_to_fire(robot_info *robptr, ai_local *ailp); +extern int polish_path(object *objp, point_seg *psegs, int num_points); +extern void move_towards_player(object *objp, vms_vector *vec_to_player); + +// max_length is maximum depth of path to create. +// If -1, use default: MAX_DEPTH_TO_SEARCH_FOR_PLAYER +extern void create_path_to_player(object *objp, int max_length, int safety_flag); +extern void attempt_to_resume_path(object *objp); + +// When a robot and a player collide, some robots attack! +extern void do_ai_robot_hit_attack(object *robot, object *player, vms_vector *collision_point); +extern void ai_open_doors_in_segment(object *robot); +extern int ai_door_is_openable(object *objp, segment *segp, int sidenum); +extern int player_is_visible_from_object(object *objp, vms_vector *pos, fix field_of_view, vms_vector *vec_to_player); +extern void ai_reset_all_paths(void); // Reset all paths. Call at the start of a level. +extern int ai_multiplayer_awareness(object *objp, int awareness_level); + +// In escort.c +extern void do_escort_frame(object *objp, fix dist_to_player, int player_visibility); +extern void do_snipe_frame(object *objp, fix dist_to_player, int player_visibility, vms_vector *vec_to_player); +extern void do_thief_frame(object *objp, fix dist_to_player, int player_visibility, vms_vector *vec_to_player); + +#ifndef NDEBUG +extern void force_dump_ai_objects_all(char *msg); +#else +#define force_dump_ai_objects_all(msg) +#endif + +extern void start_boss_death_sequence(object *objp); +extern void ai_init_boss_for_ship(void); +extern int Boss_been_hit; +extern fix AI_proc_time; + +// Stuff moved from ai.c by MK on 05/25/95. +#define ANIM_RATE (F1_0/16) +#define DELTA_ANG_SCALE 16 + +#define OVERALL_AGITATION_MAX 100 +#define MAX_AI_CLOAK_INFO 8 // Must be a power of 2! + +typedef struct { + fix last_time; + int last_segment; + vms_vector last_position; +} ai_cloak_info; + +#define BOSS_CLOAK_DURATION (F1_0*7) +#define BOSS_DEATH_DURATION (F1_0*6) + +#define CHASE_TIME_LENGTH (F1_0*8) +#define DEFAULT_ROBOT_SOUND_VOLUME F1_0 + +extern fix Dist_to_last_fired_upon_player_pos; +extern vms_vector Last_fired_upon_player_pos; +extern int Laser_rapid_fire; + +#define MAX_AWARENESS_EVENTS 64 +typedef struct awareness_event { + short segnum; // segment the event occurred in + short type; // type of event, defines behavior + vms_vector pos; // absolute 3 space location of event +} awareness_event; + +#define AIS_MAX 8 +#define AIE_MAX 4 + +#define ESCORT_GOAL_UNSPECIFIED -1 + +#define ESCORT_GOAL_UNSPECIFIED -1 +#define ESCORT_GOAL_BLUE_KEY 1 +#define ESCORT_GOAL_GOLD_KEY 2 +#define ESCORT_GOAL_RED_KEY 3 +#define ESCORT_GOAL_CONTROLCEN 4 +#define ESCORT_GOAL_EXIT 5 + +// Custom escort goals. +#define ESCORT_GOAL_ENERGY 6 +#define ESCORT_GOAL_ENERGYCEN 7 +#define ESCORT_GOAL_SHIELD 8 +#define ESCORT_GOAL_POWERUP 9 +#define ESCORT_GOAL_ROBOT 10 +#define ESCORT_GOAL_HOSTAGE 11 +#define ESCORT_GOAL_PLAYER_SPEW 12 +#define ESCORT_GOAL_SCRAM 13 +#define ESCORT_GOAL_EXIT2 14 +#define ESCORT_GOAL_BOSS 15 +#define ESCORT_GOAL_MARKER1 16 +#define ESCORT_GOAL_MARKER2 17 +#define ESCORT_GOAL_MARKER3 18 +#define ESCORT_GOAL_MARKER4 19 +#define ESCORT_GOAL_MARKER5 20 +#define ESCORT_GOAL_MARKER6 21 +#define ESCORT_GOAL_MARKER7 22 +#define ESCORT_GOAL_MARKER8 23 +#define ESCORT_GOAL_MARKER9 24 + +#define MAX_ESCORT_GOALS 25 + +#define MAX_ESCORT_DISTANCE (F1_0*80) +#define MIN_ESCORT_DISTANCE (F1_0*40) + +#define FUELCEN_CHECK 1000 + +extern fix Escort_last_path_created; +extern int Escort_goal_object, Escort_special_goal, Escort_goal_index; + +#define GOAL_WIDTH 11 + +#define SNIPE_RETREAT_TIME (F1_0*5) +#define SNIPE_ABORT_RETREAT_TIME (SNIPE_RETREAT_TIME/2) // Can abort a retreat with this amount of time left in retreat +#define SNIPE_ATTACK_TIME (F1_0*10) +#define SNIPE_WAIT_TIME (F1_0*5) +#define SNIPE_FIRE_TIME (F1_0*2) + +#define THIEF_PROBABILITY 16384 // 50% chance of stealing an item at each attempt +#define MAX_STOLEN_ITEMS 10 // Maximum number kept track of, will keep stealing, causes stolen weapons to be lost! + +extern int Max_escort_length; +extern int Escort_kill_object; +extern ubyte Stolen_items[MAX_STOLEN_ITEMS]; +extern fix Escort_last_path_created; +extern int Escort_goal_object, Escort_special_goal, Escort_goal_index; + +#ifndef NDEBUG +extern void create_buddy_bot(void); +#endif + +extern int Max_escort_length; + +extern char *Escort_goal_text[MAX_ESCORT_GOALS]; + +extern void ai_multi_send_robot_position(int objnum, int force); + +extern int Flinch_scale; +extern int Attack_scale; +extern byte Mike_to_matt_xlate[]; + +// Amount of time since the current robot was last processed for things such as movement. +// It is not valid to use FrameTime because robots do not get moved every frame. + +extern int Num_boss_teleport_segs; +extern short Boss_teleport_segs[]; +extern int Num_boss_gate_segs; +extern short Boss_gate_segs[]; + + +// ---------- John: These variables must be saved as part of gamesave. ---------- +extern int Ai_initialized; +extern int Overall_agitation; +extern ai_local Ai_local_info[MAX_OBJECTS]; +extern point_seg Point_segs[MAX_POINT_SEGS]; +extern point_seg *Point_segs_free_ptr; +extern ai_cloak_info Ai_cloak_info[MAX_AI_CLOAK_INFO]; +extern fix Boss_cloak_start_time; +extern fix Boss_cloak_end_time; +extern fix Last_teleport_time; +extern fix Boss_teleport_interval; +extern fix Boss_cloak_interval; // Time between cloaks +extern fix Boss_cloak_duration; +extern fix Last_gate_time; +extern fix Gate_interval; +extern fix Boss_dying_start_time; +extern byte Boss_dying, Boss_dying_sound_playing; +extern fix Boss_hit_time; +// -- extern int Boss_been_hit; +// ---------- John: End of variables which must be saved as part of gamesave. ---------- + +extern int ai_evaded; + +extern byte Super_boss_gate_list[]; +#define MAX_GATE_INDEX 25 + +extern int Ai_info_enabled; +extern int Robot_firing_enabled; + + +// These globals are set by a call to find_vector_intersection, which is a slow routine, +// so we don't want to call it again (for this object) unless we have to. +extern vms_vector Hit_pos; +extern int Hit_type, Hit_seg; +extern fvi_info Hit_data; + +extern int Num_awareness_events; +extern awareness_event Awareness_events[MAX_AWARENESS_EVENTS]; + +extern vms_vector Believed_player_pos; + +#ifndef NDEBUG +// Index into this array with ailp->mode +extern char *mode_text[18]; + +// Index into this array with aip->behavior +extern char behavior_text[6][9]; + +// Index into this array with aip->GOAL_STATE or aip->CURRENT_STATE +extern char state_text[8][5]; + +extern int Do_ai_flag, Break_on_object; + +extern void mprintf_animation_info(object *objp); + +#endif //ifndef NDEBUG + +extern int Stolen_item_index; // Used in ai.c for controlling rate of Thief flare firing. + +extern void ai_frame_animation(object *objp); +extern int do_silly_animation(object *objp); +extern int openable_doors_in_segment(int segnum); +extern void compute_vis_and_vec(object *objp, vms_vector *pos, ai_local *ailp, vms_vector *vec_to_player, int *player_visibility, robot_info *robptr, int *flag); +extern void do_firing_stuff(object *obj, int player_visibility, vms_vector *vec_to_player); +extern int maybe_ai_do_actual_firing_stuff(object *obj, ai_static *aip); +extern void ai_do_actual_firing_stuff(object *obj, ai_static *aip, ai_local *ailp, robot_info *robptr, vms_vector *vec_to_player, fix dist_to_player, vms_vector *gun_point, int player_visibility, int object_animates, int gun_num); +extern void do_super_boss_stuff(object *objp, fix dist_to_player, int player_visibility); +extern void do_boss_stuff(object *objp, int player_visibility); +// -- unused, 08/07/95 -- extern void ai_turn_randomly(vms_vector *vec_to_player, object *obj, fix rate, int previous_visibility); +extern void ai_move_relative_to_player(object *objp, ai_local *ailp, fix dist_to_player, vms_vector *vec_to_player, fix circle_distance, int evade_only, int player_visibility); +extern void move_away_from_player(object *objp, vms_vector *vec_to_player, int attack_type); +extern void move_towards_vector(object *objp, vms_vector *vec_goal, int dot_based); +extern void init_ai_frame(void); +extern void detect_escort_goal_accomplished(int index); +extern void set_escort_special_goal(int key); + +extern void create_bfs_list(int start_seg, short bfs_list[], int *length, int max_segs); +extern void init_thief_for_level(); + + + + +extern int Escort_goal_object; + +extern int ai_save_state( FILE * fp ); +extern int ai_restore_state( FILE * fp, int version ); + +extern int Buddy_objnum, Buddy_allowed_to_talk; + +extern void start_robot_death_sequence(object *objp); +extern int do_any_robot_dying_frame(object *objp); +extern void buddy_message(char * format, ... ); + +#define SPECIAL_REACTOR_ROBOT 65 +extern void special_reactor_stuff(void); + +#endif diff --git a/main/ai2.c b/main/ai2.c new file mode 100644 index 00000000..9f381c84 --- /dev/null +++ b/main/ai2.c @@ -0,0 +1,2614 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + +#ifdef RCS +static char rcsid[] = "$Id: ai2.c,v 1.1.1.1 2001-01-19 03:30:01 bradleyb Exp $"; +#endif + +#include +#include +#include +#include + +#include "inferno.h" +#include "game.h" +#include "mono.h" +#include "3d.h" + +#include "u_mem.h" +#include "object.h" +#include "render.h" +#include "error.h" +#include "ai.h" +#include "laser.h" +#include "fvi.h" +#include "polyobj.h" +#include "bm.h" +#include "weapon.h" +#include "physics.h" +#include "collide.h" +#include "player.h" +#include "wall.h" +#include "vclip.h" +#include "digi.h" +#include "fireball.h" +#include "morph.h" +#include "effects.h" +#include "timer.h" +#include "sounds.h" +#include "cntrlcen.h" +#include "multibot.h" +#include "multi.h" +#include "network.h" +#include "gameseq.h" +#include "key.h" +#include "powerup.h" +#include "gauges.h" +#include "text.h" + +#ifdef EDITOR +#include "editor\editor.h" +#include "editor\kdefs.h" +#endif + +#ifndef NDEBUG +#include "string.h" +#include +#endif + +void teleport_boss(object *objp); +int boss_fits_in_seg(object *boss_objp, int segnum); + + +int Flinch_scale = 4; +int Attack_scale = 24; +byte Mike_to_matt_xlate[] = {AS_REST, AS_REST, AS_ALERT, AS_ALERT, AS_FLINCH, AS_FIRE, AS_RECOIL, AS_REST}; + +// Amount of time since the current robot was last processed for things such as movement. +// It is not valid to use FrameTime because robots do not get moved every frame. + +int Num_boss_teleport_segs; +short Boss_teleport_segs[MAX_BOSS_TELEPORT_SEGS]; +int Num_boss_gate_segs; +short Boss_gate_segs[MAX_BOSS_TELEPORT_SEGS]; + +// --------------------------------------------------------- +// On entry, N_robot_types had darn sure better be set. +// Mallocs N_robot_types robot_info structs into global Robot_info. +void init_ai_system(void) +{ +#if 0 + int i; + + mprintf((0, "Trying to malloc %i bytes for Robot_info.\n", N_robot_types * sizeof(*Robot_info))); + Robot_info = (robot_info *) d_malloc( N_robot_types * sizeof(*Robot_info) ); + mprintf((0, "Robot_info = %i\n", Robot_info)); + + for (i=0; ictype.ai_info; + ai_local *ailp = &Ai_local_info[objnum]; + robot_info *robptr = &Robot_info[objp->id]; + + if (behavior == 0) { + // mprintf((0, "Behavior of 0 for object #%i, bashing to AIB_NORMAL.\n", objnum)); + behavior = AIB_NORMAL; + aip->behavior = behavior; + } + // mprintf((0, "Initializing object #%i\n", objnum)); + + // mode is now set from the Robot dialog, so this should get overwritten. + ailp->mode = AIM_STILL; + + ailp->previous_visibility = 0; + + if (behavior != -1) { + aip->behavior = behavior; + ailp->mode = ai_behavior_to_mode(aip->behavior); + } else if (!((aip->behavior >= MIN_BEHAVIOR) && (aip->behavior <= MAX_BEHAVIOR))) { + mprintf((0, "[obj %i -> normal] ", objnum)); + aip->behavior = AIB_NORMAL; + } + + if (robptr->companion) { + ailp->mode = AIM_GOTO_PLAYER; + Escort_kill_object = -1; + } + + if (robptr->thief) { + aip->behavior = AIB_SNIPE; + ailp->mode = AIM_THIEF_WAIT; + } + + if (robptr->attack_type) { + aip->behavior = AIB_NORMAL; + ailp->mode = ai_behavior_to_mode(aip->behavior); + } + + // This is astonishingly stupid! This routine gets called by matcens! KILL KILL KILL!!! Point_segs_free_ptr = Point_segs; + + vm_vec_zero(&objp->mtype.phys_info.velocity); + // -- ailp->wait_time = F1_0*5; + ailp->player_awareness_time = 0; + ailp->player_awareness_type = 0; + aip->GOAL_STATE = AIS_SRCH; + aip->CURRENT_STATE = AIS_REST; + ailp->time_player_seen = GameTime; + ailp->next_misc_sound_time = GameTime; + ailp->time_player_sound_attacked = GameTime; + + if ((behavior == AIB_SNIPE) || (behavior == AIB_STATION) || (behavior == AIB_RUN_FROM) || (behavior == AIB_FOLLOW)) { + aip->hide_segment = hide_segment; + ailp->goal_segment = hide_segment; + aip->hide_index = -1; // This means the path has not yet been created. + aip->cur_path_index = 0; + } + + aip->SKIP_AI_COUNT = 0; + + if (robptr->cloak_type == RI_CLOAKED_ALWAYS) + aip->CLOAKED = 1; + else + aip->CLOAKED = 0; + + objp->mtype.phys_info.flags |= (PF_BOUNCE | PF_TURNROLL); + + aip->REMOTE_OWNER = -1; + + aip->dying_sound_playing = 0; + aip->dying_start_time = 0; + +} + + +extern object * create_morph_robot( segment *segp, vms_vector *object_pos, int object_id); + +// -------------------------------------------------------------------------------------------------------------------- +// Create a Buddy bot. +// This automatically happens when you bring up the Buddy menu in a debug version. +// It is available as a cheat in a non-debug (release) version. +void create_buddy_bot(void) +{ + int buddy_id; + vms_vector object_pos; + + for (buddy_id=0; buddy_idsegnum]); + + create_morph_robot( &Segments[ConsoleObject->segnum], &object_pos, buddy_id); +} + +#define QUEUE_SIZE 256 + +// -------------------------------------------------------------------------------------------------------------------- +// Create list of segments boss is allowed to teleport to at segptr. +// Set *num_segs. +// Boss is allowed to teleport to segments he fits in (calls object_intersects_wall) and +// he can reach from his initial position (calls find_connected_distance). +// If size_check is set, then only add segment if boss can fit in it, else any segment is legal. +// one_wall_hack added by MK, 10/13/95: A mega-hack! Set to !0 to ignore the +void init_boss_segments(short segptr[], int *num_segs, int size_check, int one_wall_hack) +{ + int boss_objnum=-1; + int i; + + *num_segs = 0; +#ifdef EDITOR + N_selected_segs = 0; +#endif + + +if (size_check) + mprintf((0, "Boss fits in segments:\n")); + // See if there is a boss. If not, quick out. + for (i=0; i<=Highest_object_index; i++) + if ((Objects[i].type == OBJ_ROBOT) && (Robot_info[Objects[i].id].boss_flag)) { + if (boss_objnum != -1) // There are two bosses in this mine! i and boss_objnum! + Int3(); //do int3 here instead of assert so museum will work + boss_objnum = i; + } + + if (boss_objnum != -1) { + int original_boss_seg; + vms_vector original_boss_pos; + object *boss_objp = &Objects[boss_objnum]; + int head, tail; + int seg_queue[QUEUE_SIZE]; +//ALREADY IN RENDER.H byte visited[MAX_SEGMENTS]; + fix boss_size_save; + + boss_size_save = boss_objp->size; + // -- Causes problems!! -- boss_objp->size = fixmul((F1_0/4)*3, boss_objp->size); + original_boss_seg = boss_objp->segnum; + original_boss_pos = boss_objp->pos; + head = 0; + tail = 0; + seg_queue[head++] = original_boss_seg; + + segptr[(*num_segs)++] = original_boss_seg; + mprintf((0, "%4i ", original_boss_seg)); + #ifdef EDITOR + Selected_segs[N_selected_segs++] = original_boss_seg; + #endif + + for (i=0; i<=Highest_segment_index; i++) + visited[i] = 0; + + while (tail != head) { + int sidenum; + segment *segp = &Segments[seg_queue[tail++]]; + + tail &= QUEUE_SIZE-1; + + for (sidenum=0; sidenumchildren[sidenum])) { + if (one_wall_hack) + one_wall_hack--; + } else + continue; + + if (visited[segp->children[sidenum]] == 0) { + seg_queue[head++] = segp->children[sidenum]; + visited[segp->children[sidenum]] = 1; + head &= QUEUE_SIZE-1; + if (head > tail) { + if (head == tail + QUEUE_SIZE-1) + Int3(); // queue overflow. Make it bigger! + } else + if (head+QUEUE_SIZE == tail + QUEUE_SIZE-1) + Int3(); // queue overflow. Make it bigger! + + if ((!size_check) || boss_fits_in_seg(boss_objp, segp->children[sidenum])) { + segptr[(*num_segs)++] = segp->children[sidenum]; + if (size_check) mprintf((0, "%4i ", segp->children[sidenum])); + #ifdef EDITOR + Selected_segs[N_selected_segs++] = segp->children[sidenum]; + #endif + if (*num_segs >= MAX_BOSS_TELEPORT_SEGS) { + mprintf((1, "Warning: Too many boss teleport segments. Found %i after searching %i/%i segments.\n", MAX_BOSS_TELEPORT_SEGS, segp->children[sidenum], Highest_segment_index+1)); + tail = head; + } + } + } + } + } + + } + + boss_objp->size = boss_size_save; + boss_objp->pos = original_boss_pos; + obj_relink(boss_objnum, original_boss_seg); + + } + +} + +extern void init_buddy_for_level(void); + +// --------------------------------------------------------------------------------------------------------------------- +void init_ai_objects(void) +{ + int i; + + Point_segs_free_ptr = Point_segs; + + for (i=0; icontrol_type == CT_AI) + init_ai_object(i, objp->ctype.ai_info.behavior, objp->ctype.ai_info.hide_segment); + } + + init_boss_segments(Boss_gate_segs, &Num_boss_gate_segs, 0, 0); + + init_boss_segments(Boss_teleport_segs, &Num_boss_teleport_segs, 1, 0); + if (Num_boss_teleport_segs == 1) + init_boss_segments(Boss_teleport_segs, &Num_boss_teleport_segs, 1, 1); + + Boss_dying_sound_playing = 0; + Boss_dying = 0; + // -- unused! MK, 10/21/95 -- Boss_been_hit = 0; + Gate_interval = F1_0*4 - Difficulty_level*i2f(2)/3; + + Ai_initialized = 1; + + ai_do_cloak_stuff(); + + init_buddy_for_level(); + + if (Current_level_num == Last_level) { + Boss_teleport_interval = F1_0*10; + Boss_cloak_interval = F1_0*15; // Time between cloaks + } else { + Boss_teleport_interval = F1_0*7; + Boss_cloak_interval = F1_0*10; // Time between cloaks + } +} + +int Lunacy = 0; +int Diff_save = 1; + +fix Firing_wait_copy[MAX_ROBOT_TYPES]; +fix Firing_wait2_copy[MAX_ROBOT_TYPES]; +byte Rapidfire_count_copy[MAX_ROBOT_TYPES]; + +void do_lunacy_on(void) +{ + int i; + + if (Lunacy) //already on + return; + + Lunacy = 1; + + Diff_save = Difficulty_level; + Difficulty_level = NDL-1; + + for (i=0; iid == BABY_SPIDER_ID) && (objp->type == OBJ_ROBOT)) { + physics_turn_towards_vector(goal_vector, objp, rate); + return; + } + + new_fvec = *goal_vector; + + dot = vm_vec_dot(goal_vector, &objp->orient.fvec); + + if (dot < (F1_0 - FrameTime/2)) { + fix mag; + fix new_scale = fixdiv(FrameTime * AI_TURN_SCALE, rate); + vm_vec_scale(&new_fvec, new_scale); + vm_vec_add2(&new_fvec, &objp->orient.fvec); + mag = vm_vec_normalize_quick(&new_fvec); + if (mag < F1_0/256) { + mprintf((1, "Degenerate vector in ai_turn_towards_vector (mag = %7.3f)\n", f2fl(mag))); + new_fvec = *goal_vector; // if degenerate vector, go right to goal + } + } + + if (Seismic_tremor_magnitude) { + vms_vector rand_vec; + fix scale; + make_random_vector(&rand_vec); + scale = fixdiv(2*Seismic_tremor_magnitude, Robot_info[objp->id].mass); + vm_vec_scale_add2(&new_fvec, &rand_vec, scale); + } + + vm_vector_2_matrix(&objp->orient, &new_fvec, NULL, &objp->orient.rvec); +} + +// -- unused, 08/07/95 -- // -------------------------------------------------------------------------------------------------------------------- +// -- unused, 08/07/95 -- void ai_turn_randomly(vms_vector *vec_to_player, object *obj, fix rate, int previous_visibility) +// -- unused, 08/07/95 -- { +// -- unused, 08/07/95 -- vms_vector curvec; +// -- unused, 08/07/95 -- +// -- unused, 08/07/95 -- // -- MK, 06/09/95 // Random turning looks too stupid, so 1/4 of time, cheat. +// -- unused, 08/07/95 -- // -- MK, 06/09/95 if (previous_visibility) +// -- unused, 08/07/95 -- // -- MK, 06/09/95 if (d_rand() > 0x7400) { +// -- unused, 08/07/95 -- // -- MK, 06/09/95 ai_turn_towards_vector(vec_to_player, obj, rate); +// -- unused, 08/07/95 -- // -- MK, 06/09/95 return; +// -- unused, 08/07/95 -- // -- MK, 06/09/95 } +// -- unused, 08/07/95 -- +// -- unused, 08/07/95 -- curvec = obj->mtype.phys_info.rotvel; +// -- unused, 08/07/95 -- +// -- unused, 08/07/95 -- curvec.y += F1_0/64; +// -- unused, 08/07/95 -- +// -- unused, 08/07/95 -- curvec.x += curvec.y/6; +// -- unused, 08/07/95 -- curvec.y += curvec.z/4; +// -- unused, 08/07/95 -- curvec.z += curvec.x/10; +// -- unused, 08/07/95 -- +// -- unused, 08/07/95 -- if (abs(curvec.x) > F1_0/8) curvec.x /= 4; +// -- unused, 08/07/95 -- if (abs(curvec.y) > F1_0/8) curvec.y /= 4; +// -- unused, 08/07/95 -- if (abs(curvec.z) > F1_0/8) curvec.z /= 4; +// -- unused, 08/07/95 -- +// -- unused, 08/07/95 -- obj->mtype.phys_info.rotvel = curvec; +// -- unused, 08/07/95 -- +// -- unused, 08/07/95 -- } + +// Overall_agitation affects: +// Widens field of view. Field of view is in range 0..1 (specified in bitmaps.tbl as N/360 degrees). +// Overall_agitation/128 subtracted from field of view, making robots see wider. +// Increases distance to which robot will search to create path to player by Overall_agitation/8 segments. +// Decreases wait between fire times by Overall_agitation/64 seconds. + + +// -------------------------------------------------------------------------------------------------------------------- +// Returns: +// 0 Player is not visible from object, obstruction or something. +// 1 Player is visible, but not in field of view. +// 2 Player is visible and in field of view. +// Note: Uses Believed_player_pos as player's position for cloak effect. +// NOTE: Will destructively modify *pos if *pos is outside the mine. +int player_is_visible_from_object(object *objp, vms_vector *pos, fix field_of_view, vms_vector *vec_to_player) +{ + fix dot; + fvi_query fq; + + // Assume that robot's gun tip is in same segment as robot's center. + objp->ctype.ai_info.SUB_FLAGS &= ~SUB_FLAGS_GUNSEG; + + fq.p0 = pos; + if ((pos->x != objp->pos.x) || (pos->y != objp->pos.y) || (pos->z != objp->pos.z)) { + int segnum = find_point_seg(pos, objp->segnum); + if (segnum == -1) { + fq.startseg = objp->segnum; + *pos = objp->pos; + mprintf((1, "Object %i, gun is outside mine, moving towards center.\n", objp-Objects)); + move_towards_segment_center(objp); + } else { + if (segnum != objp->segnum) { + // -- mprintf((0, "Warning: Robot's gun tip not in same segment as robot center, frame %i.\n", FrameCount)); + objp->ctype.ai_info.SUB_FLAGS |= SUB_FLAGS_GUNSEG; + } + fq.startseg = segnum; + } + } else + fq.startseg = objp->segnum; + fq.p1 = &Believed_player_pos; + fq.rad = F1_0/4; + fq.thisobjnum = objp-Objects; + fq.ignore_obj_list = NULL; + fq.flags = FQ_TRANSWALL; // -- Why were we checking objects? | FQ_CHECK_OBJS; //what about trans walls??? + + Hit_type = find_vector_intersection(&fq,&Hit_data); + + Hit_pos = Hit_data.hit_pnt; + Hit_seg = Hit_data.hit_seg; + + // -- when we stupidly checked objects -- if ((Hit_type == HIT_NONE) || ((Hit_type == HIT_OBJECT) && (Hit_data.hit_object == Players[Player_num].objnum))) { + if (Hit_type == HIT_NONE) { + dot = vm_vec_dot(vec_to_player, &objp->orient.fvec); + // mprintf((0, "Fvec = [%5.2f %5.2f %5.2f], vec_to_player = [%5.2f %5.2f %5.2f], dot = %7.3f\n", f2fl(objp->orient.fvec.x), f2fl(objp->orient.fvec.y), f2fl(objp->orient.fvec.z), f2fl(vec_to_player->x), f2fl(vec_to_player->y), f2fl(vec_to_player->z), f2fl(dot))); + if (dot > field_of_view - (Overall_agitation << 9)) { + return 2; + } else { + return 1; + } + } else { + return 0; + } +} + +// ------------------------------------------------------------------------------------------------------------------ +// Return 1 if animates, else return 0 +int do_silly_animation(object *objp) +{ + int objnum = objp-Objects; + jointpos *jp_list; + int robot_type, gun_num, robot_state, num_joint_positions; + polyobj_info *pobj_info = &objp->rtype.pobj_info; + ai_static *aip = &objp->ctype.ai_info; + // ai_local *ailp = &Ai_local_info[objnum]; + int num_guns, at_goal; + int attack_type; + int flinch_attack_scale = 1; + + robot_type = objp->id; + num_guns = Robot_info[robot_type].n_guns; + attack_type = Robot_info[robot_type].attack_type; + + if (num_guns == 0) { + // mprintf((0, "Object #%i of type #%i has 0 guns.\n", objp-Objects, robot_type)); + return 0; + } + + // This is a hack. All positions should be based on goal_state, not GOAL_STATE. + robot_state = Mike_to_matt_xlate[aip->GOAL_STATE]; + // previous_robot_state = Mike_to_matt_xlate[aip->CURRENT_STATE]; + + if (attack_type) // && ((robot_state == AS_FIRE) || (robot_state == AS_RECOIL))) + flinch_attack_scale = Attack_scale; + else if ((robot_state == AS_FLINCH) || (robot_state == AS_RECOIL)) + flinch_attack_scale = Flinch_scale; + + at_goal = 1; + for (gun_num=0; gun_num <= num_guns; gun_num++) { + int joint; + + num_joint_positions = robot_get_anim_state(&jp_list, robot_type, gun_num, robot_state); + + for (joint=0; jointanim_angles[jointnum]; + + if (jointnum >= Polygon_models[objp->rtype.pobj_info.model_num].n_models) { + Int3(); // Contact Mike: incompatible data, illegal jointnum, problem in pof file? + continue; + } + if (jp->p != pobjp->p) { + if (gun_num == 0) + at_goal = 0; + Ai_local_info[objnum].goal_angles[jointnum].p = jp->p; + + delta_angle = jp->p - pobjp->p; + if (delta_angle >= F1_0/2) + delta_2 = -ANIM_RATE; + else if (delta_angle >= 0) + delta_2 = ANIM_RATE; + else if (delta_angle >= -F1_0/2) + delta_2 = -ANIM_RATE; + else + delta_2 = ANIM_RATE; + + if (flinch_attack_scale != 1) + delta_2 *= flinch_attack_scale; + + Ai_local_info[objnum].delta_angles[jointnum].p = delta_2/DELTA_ANG_SCALE; // complete revolutions per second + } + + if (jp->b != pobjp->b) { + if (gun_num == 0) + at_goal = 0; + Ai_local_info[objnum].goal_angles[jointnum].b = jp->b; + + delta_angle = jp->b - pobjp->b; + if (delta_angle >= F1_0/2) + delta_2 = -ANIM_RATE; + else if (delta_angle >= 0) + delta_2 = ANIM_RATE; + else if (delta_angle >= -F1_0/2) + delta_2 = -ANIM_RATE; + else + delta_2 = ANIM_RATE; + + if (flinch_attack_scale != 1) + delta_2 *= flinch_attack_scale; + + Ai_local_info[objnum].delta_angles[jointnum].b = delta_2/DELTA_ANG_SCALE; // complete revolutions per second + } + + if (jp->h != pobjp->h) { + if (gun_num == 0) + at_goal = 0; + Ai_local_info[objnum].goal_angles[jointnum].h = jp->h; + + delta_angle = jp->h - pobjp->h; + if (delta_angle >= F1_0/2) + delta_2 = -ANIM_RATE; + else if (delta_angle >= 0) + delta_2 = ANIM_RATE; + else if (delta_angle >= -F1_0/2) + delta_2 = -ANIM_RATE; + else + delta_2 = ANIM_RATE; + + if (flinch_attack_scale != 1) + delta_2 *= flinch_attack_scale; + + Ai_local_info[objnum].delta_angles[jointnum].h = delta_2/DELTA_ANG_SCALE; // complete revolutions per second + } + } + + if (at_goal) { + //ai_static *aip = &objp->ctype.ai_info; + ai_local *ailp = &Ai_local_info[objp-Objects]; + ailp->achieved_state[gun_num] = ailp->goal_state[gun_num]; + if (ailp->achieved_state[gun_num] == AIS_RECO) + ailp->goal_state[gun_num] = AIS_FIRE; + + if (ailp->achieved_state[gun_num] == AIS_FLIN) + ailp->goal_state[gun_num] = AIS_LOCK; + + } + } + + if (at_goal == 1) //num_guns) + aip->CURRENT_STATE = aip->GOAL_STATE; + + return 1; +} + +// ------------------------------------------------------------------------------------------ +// Move all sub-objects in an object towards their goals. +// Current orientation of object is at: pobj_info.anim_angles +// Goal orientation of object is at: ai_info.goal_angles +// Delta orientation of object is at: ai_info.delta_angles +void ai_frame_animation(object *objp) +{ + int objnum = objp-Objects; + int joint; + int num_joints; + + num_joints = Polygon_models[objp->rtype.pobj_info.model_num].n_models; + + for (joint=1; jointrtype.pobj_info.anim_angles[joint]; + vms_angvec *goalangp = &Ai_local_info[objnum].goal_angles[joint]; + vms_angvec *deltaangp = &Ai_local_info[objnum].delta_angles[joint]; + + delta_to_goal = goalangp->p - curangp->p; + if (delta_to_goal > 32767) + delta_to_goal = delta_to_goal - 65536; + else if (delta_to_goal < -32767) + delta_to_goal = 65536 + delta_to_goal; + + if (delta_to_goal) { + scaled_delta_angle = fixmul(deltaangp->p, FrameTime) * DELTA_ANG_SCALE; + curangp->p += scaled_delta_angle; + if (abs(delta_to_goal) < abs(scaled_delta_angle)) + curangp->p = goalangp->p; + } + + delta_to_goal = goalangp->b - curangp->b; + if (delta_to_goal > 32767) + delta_to_goal = delta_to_goal - 65536; + else if (delta_to_goal < -32767) + delta_to_goal = 65536 + delta_to_goal; + + if (delta_to_goal) { + scaled_delta_angle = fixmul(deltaangp->b, FrameTime) * DELTA_ANG_SCALE; + curangp->b += scaled_delta_angle; + if (abs(delta_to_goal) < abs(scaled_delta_angle)) + curangp->b = goalangp->b; + } + + delta_to_goal = goalangp->h - curangp->h; + if (delta_to_goal > 32767) + delta_to_goal = delta_to_goal - 65536; + else if (delta_to_goal < -32767) + delta_to_goal = 65536 + delta_to_goal; + + if (delta_to_goal) { + scaled_delta_angle = fixmul(deltaangp->h, FrameTime) * DELTA_ANG_SCALE; + curangp->h += scaled_delta_angle; + if (abs(delta_to_goal) < abs(scaled_delta_angle)) + curangp->h = goalangp->h; + } + + } + +} + +// ---------------------------------------------------------------------------------- +void set_next_fire_time(object *objp, ai_local *ailp, robot_info *robptr, int gun_num) +{ + // For guys in snipe mode, they have a 50% shot of getting this shot in free. + if ((gun_num != 0) || (robptr->weapon_type2 == -1)) + if ((objp->ctype.ai_info.behavior != AIB_SNIPE) || (d_rand() > 16384)) + ailp->rapidfire_count++; + + // Old way, 10/15/95: Continuous rapidfire if rapidfire_count set. +// -- if (((robptr->weapon_type2 == -1) || (gun_num != 0)) && (ailp->rapidfire_count < robptr->rapidfire_count[Difficulty_level])) { +// -- ailp->next_fire = min(F1_0/8, robptr->firing_wait[Difficulty_level]/2); +// -- } else { +// -- if ((robptr->weapon_type2 == -1) || (gun_num != 0)) { +// -- ailp->rapidfire_count = 0; +// -- ailp->next_fire = robptr->firing_wait[Difficulty_level]; +// -- } else +// -- ailp->next_fire2 = robptr->firing_wait2[Difficulty_level]; +// -- } + + if (((gun_num != 0) || (robptr->weapon_type2 == -1)) && (ailp->rapidfire_count < robptr->rapidfire_count[Difficulty_level])) { + ailp->next_fire = min(F1_0/8, robptr->firing_wait[Difficulty_level]/2); + } else { + if ((robptr->weapon_type2 == -1) || (gun_num != 0)) { + ailp->next_fire = robptr->firing_wait[Difficulty_level]; + if (ailp->rapidfire_count >= robptr->rapidfire_count[Difficulty_level]) + ailp->rapidfire_count = 0; + } else + ailp->next_fire2 = robptr->firing_wait2[Difficulty_level]; + } +} + +// ---------------------------------------------------------------------------------- +// When some robots collide with the player, they attack. +// If player is cloaked, then robot probably didn't actually collide, deal with that here. +void do_ai_robot_hit_attack(object *robot, object *playerobj, vms_vector *collision_point) +{ + ai_local *ailp = &Ai_local_info[robot-Objects]; + robot_info *robptr = &Robot_info[robot->id]; + +//#ifndef NDEBUG + if (!Robot_firing_enabled) + return; +//#endif + + // If player is dead, stop firing. + if (Objects[Players[Player_num].objnum].type == OBJ_GHOST) + return; + + if (robptr->attack_type == 1) { + if (ailp->next_fire <= 0) { + if (!(Players[Player_num].flags & PLAYER_FLAGS_CLOAKED)) + if (vm_vec_dist_quick(&ConsoleObject->pos, &robot->pos) < robot->size + ConsoleObject->size + F1_0*2) { + collide_player_and_nasty_robot( playerobj, robot, collision_point ); + if (robptr->energy_drain && Players[Player_num].energy) { + Players[Player_num].energy -= robptr->energy_drain * F1_0; + if (Players[Player_num].energy < 0) + Players[Player_num].energy = 0; + // -- unused, use claw_sound in bitmaps.tbl -- digi_link_sound_to_pos( SOUND_ROBOT_SUCKED_PLAYER, playerobj->segnum, 0, collision_point, 0, F1_0 ); + } + } + + robot->ctype.ai_info.GOAL_STATE = AIS_RECO; + set_next_fire_time(robot, ailp, robptr, 1); // 1 = gun_num: 0 is special (uses next_fire2) + } + } + +} + +#ifndef _OBJECT_H +extern int Player_exploded; +#endif + +#define FIRE_K 8 // Controls average accuracy of robot firing. Smaller numbers make firing worse. Being power of 2 doesn't matter. + +// ==================================================================================================================== + +#define MIN_LEAD_SPEED (F1_0*4) +#define MAX_LEAD_DISTANCE (F1_0*200) +#define LEAD_RANGE (F1_0/2) + +// -------------------------------------------------------------------------------------------------------------------- +// Computes point at which projectile fired by robot can hit player given positions, player vel, elapsed time +fix compute_lead_component(fix player_pos, fix robot_pos, fix player_vel, fix elapsed_time) +{ + return fixdiv(player_pos - robot_pos, elapsed_time) + player_vel; +} + +// -------------------------------------------------------------------------------------------------------------------- +// Lead the player, returning point to fire at in fire_point. +// Rules: +// Player not cloaked +// Player must be moving at a speed >= MIN_LEAD_SPEED +// Player not farther away than MAX_LEAD_DISTANCE +// dot(vector_to_player, player_direction) must be in -LEAD_RANGE..LEAD_RANGE +// if firing a matter weapon, less leading, based on skill level. +int lead_player(object *objp, vms_vector *fire_point, vms_vector *believed_player_pos, int gun_num, vms_vector *fire_vec) +{ + fix dot, player_speed, dist_to_player, max_weapon_speed, projected_time; + vms_vector player_movement_dir, vec_to_player; + int weapon_type; + weapon_info *wptr; + robot_info *robptr; + + if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) + return 0; + + player_movement_dir = ConsoleObject->mtype.phys_info.velocity; + player_speed = vm_vec_normalize_quick(&player_movement_dir); + + if (player_speed < MIN_LEAD_SPEED) + return 0; + + vm_vec_sub(&vec_to_player, believed_player_pos, fire_point); + dist_to_player = vm_vec_normalize_quick(&vec_to_player); + if (dist_to_player > MAX_LEAD_DISTANCE) + return 0; + + dot = vm_vec_dot(&vec_to_player, &player_movement_dir); + + if ((dot < -LEAD_RANGE) || (dot > LEAD_RANGE)) + return 0; + + // Looks like it might be worth trying to lead the player. + robptr = &Robot_info[objp->id]; + weapon_type = robptr->weapon_type; + if (robptr->weapon_type2 != -1) + if (gun_num == 0) + weapon_type = robptr->weapon_type2; + + wptr = &Weapon_info[weapon_type]; + max_weapon_speed = wptr->speed[Difficulty_level]; + if (max_weapon_speed < F1_0) + return 0; + + // Matter weapons: + // At Rookie or Trainee, don't lead at all. + // At higher skill levels, don't lead as well. Accomplish this by screwing up max_weapon_speed. + if (wptr->matter) + { + if (Difficulty_level <= 1) + return 0; + else + max_weapon_speed *= (NDL-Difficulty_level); + } + + projected_time = fixdiv(dist_to_player, max_weapon_speed); + + fire_vec->x = compute_lead_component(believed_player_pos->x, fire_point->x, ConsoleObject->mtype.phys_info.velocity.x, projected_time); + fire_vec->y = compute_lead_component(believed_player_pos->y, fire_point->y, ConsoleObject->mtype.phys_info.velocity.y, projected_time); + fire_vec->z = compute_lead_component(believed_player_pos->z, fire_point->z, ConsoleObject->mtype.phys_info.velocity.z, projected_time); + + vm_vec_normalize_quick(fire_vec); + + Assert(vm_vec_dot(fire_vec, &objp->orient.fvec) < 3*F1_0/2); + + // Make sure not firing at especially strange angle. If so, try to correct. If still bad, give up after one try. + if (vm_vec_dot(fire_vec, &objp->orient.fvec) < F1_0/2) { + vm_vec_add2(fire_vec, &vec_to_player); + vm_vec_scale(fire_vec, F1_0/2); + if (vm_vec_dot(fire_vec, &objp->orient.fvec) < F1_0/2) { + return 0; + } + } + + return 1; +} + +// -------------------------------------------------------------------------------------------------------------------- +// Note: Parameter vec_to_player is only passed now because guns which aren't on the forward vector from the +// center of the robot will not fire right at the player. We need to aim the guns at the player. Barring that, we cheat. +// When this routine is complete, the parameter vec_to_player should not be necessary. +void ai_fire_laser_at_player(object *obj, vms_vector *fire_point, int gun_num, vms_vector *believed_player_pos) +{ + int objnum = obj-Objects; + ai_local *ailp = &Ai_local_info[objnum]; + robot_info *robptr = &Robot_info[obj->id]; + vms_vector fire_vec; + vms_vector bpp_diff; + int weapon_type; + fix aim, dot; + int count; + + Assert(robptr->attack_type == 0); // We should never be coming here for the green guy, as he has no laser! + + // If this robot is only awake because a camera woke it up, don't fire. + if (obj->ctype.ai_info.SUB_FLAGS & SUB_FLAGS_CAMERA_AWAKE) + return; + + if (!Robot_firing_enabled) + return; + + if (obj->control_type == CT_MORPH) + return; + + // If player is exploded, stop firing. + if (Player_exploded) + return; + + if (obj->ctype.ai_info.dying_start_time) + return; // No firing while in death roll. + + // Don't let the boss fire while in death roll. Sorry, this is the easiest way to do this. + // If you try to key the boss off obj->ctype.ai_info.dying_start_time, it will hose the endlevel stuff. + if (Boss_dying_start_time & Robot_info[obj->id].boss_flag) + return; + + // If player is cloaked, maybe don't fire based on how long cloaked and randomness. + if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) { + fix cloak_time = Ai_cloak_info[objnum % MAX_AI_CLOAK_INFO].last_time; + + if (GameTime - cloak_time > CLOAK_TIME_MAX/4) + if (d_rand() > fixdiv(GameTime - cloak_time, CLOAK_TIME_MAX)/2) { + set_next_fire_time(obj, ailp, robptr, gun_num); + return; + } + } + + // Handle problem of a robot firing through a wall because its gun tip is on the other + // side of the wall than the robot's center. For speed reasons, we normally only compute + // the vector from the gun point to the player. But we need to know whether the gun point + // is separated from the robot's center by a wall. If so, don't fire! + if (obj->ctype.ai_info.SUB_FLAGS & SUB_FLAGS_GUNSEG) { + // Well, the gun point is in a different segment than the robot's center. + // This is almost always ok, but it is not ok if something solid is in between. + int conn_side; + int gun_segnum = find_point_seg(fire_point, obj->segnum); + + // See if these segments are connected, which should almost always be the case. + conn_side = find_connect_side(&Segments[gun_segnum], &Segments[obj->segnum]); + if (conn_side != -1) { + // They are connected via conn_side in segment obj->segnum. + // See if they are unobstructed. + if (!(WALL_IS_DOORWAY(&Segments[obj->segnum], conn_side) & WID_FLY_FLAG)) { + // Can't fly through, so don't let this bot fire through! + return; + } + } else { + // Well, they are not directly connected, so use find_vector_intersection to see if they are unobstructed. + fvi_query fq; + fvi_info hit_data; + int fate; + + fq.startseg = obj->segnum; + fq.p0 = &obj->pos; + fq.p1 = fire_point; + fq.rad = 0; + fq.thisobjnum = obj-Objects; + fq.ignore_obj_list = NULL; + fq.flags = FQ_TRANSWALL; + + fate = find_vector_intersection(&fq, &hit_data); + if (fate != HIT_NONE) { + Int3(); // This bot's gun is poking through a wall, so don't fire. + move_towards_segment_center(obj); // And decrease chances it will happen again. + return; + } + } + } + + // -- mprintf((0, "Firing from gun #%i at time = %7.3f\n", gun_num, f2fl(GameTime))); + + // Set position to fire at based on difficulty level and robot's aiming ability + aim = FIRE_K*F1_0 - (FIRE_K-1)*(robptr->aim << 8); // F1_0 in bitmaps.tbl = same as used to be. Worst is 50% more error. + + // Robots aim more poorly during seismic disturbance. + if (Seismic_tremor_magnitude) { + fix temp; + + temp = F1_0 - abs(Seismic_tremor_magnitude); + if (temp < F1_0/2) + temp = F1_0/2; + + aim = fixmul(aim, temp); + } + + // Lead the player half the time. + // Note that when leading the player, aim is perfect. This is probably acceptable since leading is so hacked in. + // Problem is all robots will lead equally badly. + if (d_rand() < 16384) { + if (lead_player(obj, fire_point, believed_player_pos, gun_num, &fire_vec)) // Stuff direction to fire at in fire_point. + goto player_led; + } + + dot = 0; + count = 0; // Don't want to sit in this loop forever... + while ((count < 4) && (dot < F1_0/4)) { + bpp_diff.x = believed_player_pos->x + fixmul((d_rand()-16384) * (NDL-Difficulty_level-1) * 4, aim); + bpp_diff.y = believed_player_pos->y + fixmul((d_rand()-16384) * (NDL-Difficulty_level-1) * 4, aim); + bpp_diff.z = believed_player_pos->z + fixmul((d_rand()-16384) * (NDL-Difficulty_level-1) * 4, aim); + + vm_vec_normalized_dir_quick(&fire_vec, &bpp_diff, fire_point); + dot = vm_vec_dot(&obj->orient.fvec, &fire_vec); + count++; + } +player_led: ; + + weapon_type = robptr->weapon_type; + if (robptr->weapon_type2 != -1) + if (gun_num == 0) + weapon_type = robptr->weapon_type2; + + Laser_create_new_easy( &fire_vec, fire_point, obj-Objects, weapon_type, 1); + +#ifdef NETWORK + if (Game_mode & GM_MULTI) { + ai_multi_send_robot_position(objnum, -1); + multi_send_robot_fire(objnum, obj->ctype.ai_info.CURRENT_GUN, &fire_vec); + } +#endif + + create_awareness_event(obj, PA_NEARBY_ROBOT_FIRED); + + set_next_fire_time(obj, ailp, robptr, gun_num); + +} + +// -------------------------------------------------------------------------------------------------------------------- +// vec_goal must be normalized, or close to it. +// if dot_based set, then speed is based on direction of movement relative to heading +void move_towards_vector(object *objp, vms_vector *vec_goal, int dot_based) +{ + physics_info *pptr = &objp->mtype.phys_info; + fix speed, dot, max_speed; + robot_info *robptr = &Robot_info[objp->id]; + vms_vector vel; + + // Trying to move towards player. If forward vector much different than velocity vector, + // bash velocity vector twice as much towards player as usual. + + vel = pptr->velocity; + vm_vec_normalize_quick(&vel); + dot = vm_vec_dot(&vel, &objp->orient.fvec); + + if (robptr->thief) + dot = (F1_0+dot)/2; + + if (dot_based && (dot < 3*F1_0/4)) { + // This funny code is supposed to slow down the robot and move his velocity towards his direction + // more quickly than the general code + pptr->velocity.x = pptr->velocity.x/2 + fixmul(vec_goal->x, FrameTime*32); + pptr->velocity.y = pptr->velocity.y/2 + fixmul(vec_goal->y, FrameTime*32); + pptr->velocity.z = pptr->velocity.z/2 + fixmul(vec_goal->z, FrameTime*32); + } else { + pptr->velocity.x += fixmul(vec_goal->x, FrameTime*64) * (Difficulty_level+5)/4; + pptr->velocity.y += fixmul(vec_goal->y, FrameTime*64) * (Difficulty_level+5)/4; + pptr->velocity.z += fixmul(vec_goal->z, FrameTime*64) * (Difficulty_level+5)/4; + } + + speed = vm_vec_mag_quick(&pptr->velocity); + max_speed = robptr->max_speed[Difficulty_level]; + + // Green guy attacks twice as fast as he moves away. + if ((robptr->attack_type == 1) || robptr->thief || robptr->kamikaze) + max_speed *= 2; + + if (speed > max_speed) { + pptr->velocity.x = (pptr->velocity.x*3)/4; + pptr->velocity.y = (pptr->velocity.y*3)/4; + pptr->velocity.z = (pptr->velocity.z*3)/4; + } +} + +// -------------------------------------------------------------------------------------------------------------------- +void move_towards_player(object *objp, vms_vector *vec_to_player) +// vec_to_player must be normalized, or close to it. +{ + move_towards_vector(objp, vec_to_player, 1); +} + +// -------------------------------------------------------------------------------------------------------------------- +// I am ashamed of this: fast_flag == -1 means normal slide about. fast_flag = 0 means no evasion. +void move_around_player(object *objp, vms_vector *vec_to_player, int fast_flag) +{ + physics_info *pptr = &objp->mtype.phys_info; + fix speed; + robot_info *robptr = &Robot_info[objp->id]; + int objnum = objp-Objects; + int dir; + int dir_change; + fix ft; + vms_vector evade_vector; + int count=0; + + if (fast_flag == 0) + return; + + dir_change = 48; + ft = FrameTime; + if (ft < F1_0/32) { + dir_change *= 8; + count += 3; + } else + while (ft < F1_0/4) { + dir_change *= 2; + ft *= 2; + count++; + } + + dir = (FrameCount + (count+1) * (objnum*8 + objnum*4 + objnum)) & dir_change; + dir >>= (4+count); + + Assert((dir >= 0) && (dir <= 3)); + + switch (dir) { + case 0: + evade_vector.x = fixmul(vec_to_player->z, FrameTime*32); + evade_vector.y = fixmul(vec_to_player->y, FrameTime*32); + evade_vector.z = fixmul(-vec_to_player->x, FrameTime*32); + break; + case 1: + evade_vector.x = fixmul(-vec_to_player->z, FrameTime*32); + evade_vector.y = fixmul(vec_to_player->y, FrameTime*32); + evade_vector.z = fixmul(vec_to_player->x, FrameTime*32); + break; + case 2: + evade_vector.x = fixmul(-vec_to_player->y, FrameTime*32); + evade_vector.y = fixmul(vec_to_player->x, FrameTime*32); + evade_vector.z = fixmul(vec_to_player->z, FrameTime*32); + break; + case 3: + evade_vector.x = fixmul(vec_to_player->y, FrameTime*32); + evade_vector.y = fixmul(-vec_to_player->x, FrameTime*32); + evade_vector.z = fixmul(vec_to_player->z, FrameTime*32); + break; + default: + Error("Function move_around_player: Bad case."); + } + + // Note: -1 means normal circling about the player. > 0 means fast evasion. + if (fast_flag > 0) { + fix dot; + + // Only take evasive action if looking at player. + // Evasion speed is scaled by percentage of shields left so wounded robots evade less effectively. + + dot = vm_vec_dot(vec_to_player, &objp->orient.fvec); + if ((dot > robptr->field_of_view[Difficulty_level]) && !(ConsoleObject->flags & PLAYER_FLAGS_CLOAKED)) { + fix damage_scale; + + if (robptr->strength) + damage_scale = fixdiv(objp->shields, robptr->strength); + else + damage_scale = F1_0; + if (damage_scale > F1_0) + damage_scale = F1_0; // Just in case... + else if (damage_scale < 0) + damage_scale = 0; // Just in case... + + vm_vec_scale(&evade_vector, i2f(fast_flag) + damage_scale); + } + } + + pptr->velocity.x += evade_vector.x; + pptr->velocity.y += evade_vector.y; + pptr->velocity.z += evade_vector.z; + + speed = vm_vec_mag_quick(&pptr->velocity); + if ((objp-Objects != 1) && (speed > robptr->max_speed[Difficulty_level])) { + pptr->velocity.x = (pptr->velocity.x*3)/4; + pptr->velocity.y = (pptr->velocity.y*3)/4; + pptr->velocity.z = (pptr->velocity.z*3)/4; + } +} + +// -------------------------------------------------------------------------------------------------------------------- +void move_away_from_player(object *objp, vms_vector *vec_to_player, int attack_type) +{ + fix speed; + physics_info *pptr = &objp->mtype.phys_info; + robot_info *robptr = &Robot_info[objp->id]; + int objref; + + pptr->velocity.x -= fixmul(vec_to_player->x, FrameTime*16); + pptr->velocity.y -= fixmul(vec_to_player->y, FrameTime*16); + pptr->velocity.z -= fixmul(vec_to_player->z, FrameTime*16); + + if (attack_type) { + // Get value in 0..3 to choose evasion direction. + objref = ((objp-Objects) ^ ((FrameCount + 3*(objp-Objects)) >> 5)) & 3; + + switch (objref) { + case 0: vm_vec_scale_add2(&pptr->velocity, &objp->orient.uvec, FrameTime << 5); break; + case 1: vm_vec_scale_add2(&pptr->velocity, &objp->orient.uvec, -FrameTime << 5); break; + case 2: vm_vec_scale_add2(&pptr->velocity, &objp->orient.rvec, FrameTime << 5); break; + case 3: vm_vec_scale_add2(&pptr->velocity, &objp->orient.rvec, -FrameTime << 5); break; + default: Int3(); // Impossible, bogus value on objref, must be in 0..3 + } + } + + + speed = vm_vec_mag_quick(&pptr->velocity); + + if (speed > robptr->max_speed[Difficulty_level]) { + pptr->velocity.x = (pptr->velocity.x*3)/4; + pptr->velocity.y = (pptr->velocity.y*3)/4; + pptr->velocity.z = (pptr->velocity.z*3)/4; + } + +} + +// -------------------------------------------------------------------------------------------------------------------- +// Move towards, away_from or around player. +// Also deals with evasion. +// If the flag evade_only is set, then only allowed to evade, not allowed to move otherwise (must have mode == AIM_STILL). +void ai_move_relative_to_player(object *objp, ai_local *ailp, fix dist_to_player, vms_vector *vec_to_player, fix circle_distance, int evade_only, int player_visibility) +{ + object *dobjp; + robot_info *robptr = &Robot_info[objp->id]; + + Assert(player_visibility != -1); + + // See if should take avoidance. + + // New way, green guys don't evade: if ((robptr->attack_type == 0) && (objp->ctype.ai_info.danger_laser_num != -1)) { + if (objp->ctype.ai_info.danger_laser_num != -1) { + dobjp = &Objects[objp->ctype.ai_info.danger_laser_num]; + + if ((dobjp->type == OBJ_WEAPON) && (dobjp->signature == objp->ctype.ai_info.danger_laser_signature)) { + fix dot, dist_to_laser, field_of_view; + vms_vector vec_to_laser, laser_fvec; + + field_of_view = Robot_info[objp->id].field_of_view[Difficulty_level]; + + vm_vec_sub(&vec_to_laser, &dobjp->pos, &objp->pos); + dist_to_laser = vm_vec_normalize_quick(&vec_to_laser); + dot = vm_vec_dot(&vec_to_laser, &objp->orient.fvec); + + if ((dot > field_of_view) || (robptr->companion)) { + fix laser_robot_dot; + vms_vector laser_vec_to_robot; + + // The laser is seen by the robot, see if it might hit the robot. + // Get the laser's direction. If it's a polyobj, it can be gotten cheaply from the orientation matrix. + if (dobjp->render_type == RT_POLYOBJ) + laser_fvec = dobjp->orient.fvec; + else { // Not a polyobj, get velocity and normalize. + laser_fvec = dobjp->mtype.phys_info.velocity; //dobjp->orient.fvec; + vm_vec_normalize_quick(&laser_fvec); + } + vm_vec_sub(&laser_vec_to_robot, &objp->pos, &dobjp->pos); + vm_vec_normalize_quick(&laser_vec_to_robot); + laser_robot_dot = vm_vec_dot(&laser_fvec, &laser_vec_to_robot); + + if ((laser_robot_dot > F1_0*7/8) && (dist_to_laser < F1_0*80)) { + int evade_speed; + + ai_evaded = 1; + evade_speed = Robot_info[objp->id].evade_speed[Difficulty_level]; + + move_around_player(objp, vec_to_player, evade_speed); + } + } + return; + } + } + + // If only allowed to do evade code, then done. + // Hmm, perhaps brilliant insight. If want claw-type guys to keep coming, don't return here after evasion. + if ((!robptr->attack_type) && (!robptr->thief) && evade_only) + return; + + // If we fall out of above, then no object to be avoided. + objp->ctype.ai_info.danger_laser_num = -1; + + // Green guy selects move around/towards/away based on firing time, not distance. + if (robptr->attack_type == 1) { + if (((ailp->next_fire > robptr->firing_wait[Difficulty_level]/4) && (dist_to_player < F1_0*30)) || Player_is_dead) { + // 1/4 of time, move around player, 3/4 of time, move away from player + if (d_rand() < 8192) { + move_around_player(objp, vec_to_player, -1); + } else { + move_away_from_player(objp, vec_to_player, 1); + } + } else { + move_towards_player(objp, vec_to_player); + } + } else if (robptr->thief) { + move_towards_player(objp, vec_to_player); + } else { + int objval = ((objp-Objects) & 0x0f) ^ 0x0a; + + // Changes here by MK, 12/29/95. Trying to get rid of endless circling around bots in a large room. + if (robptr->kamikaze) { + move_towards_player(objp, vec_to_player); + } else if (dist_to_player < circle_distance) + move_away_from_player(objp, vec_to_player, 0); + else if ((dist_to_player < (3+objval)*circle_distance/2) && (ailp->next_fire > -F1_0)) { + move_around_player(objp, vec_to_player, -1); + } else { + if ((-ailp->next_fire > F1_0 + (objval << 12)) && player_visibility) { + // Usually move away, but sometimes move around player. + if ((((GameTime >> 18) & 0x0f) ^ objval) > 4) { + move_away_from_player(objp, vec_to_player, 0); + } else { + move_around_player(objp, vec_to_player, -1); + } + } else + move_towards_player(objp, vec_to_player); + } + } + +} + +// -------------------------------------------------------------------------------------------------------------------- +// Compute a somewhat random, normalized vector. +void make_random_vector(vms_vector *vec) +{ + vec->x = (d_rand() - 16384) | 1; // make sure we don't create null vector + vec->y = d_rand() - 16384; + vec->z = d_rand() - 16384; + + vm_vec_normalize_quick(vec); +} + +#ifndef NDEBUG +void mprintf_animation_info(object *objp) +{ + ai_static *aip = &objp->ctype.ai_info; + ai_local *ailp = &Ai_local_info[objp-Objects]; + + if (!Ai_info_enabled) + return; + + mprintf((0, "Goal = ")); + + switch (aip->GOAL_STATE) { + case AIS_NONE: mprintf((0, "NONE ")); break; + case AIS_REST: mprintf((0, "REST ")); break; + case AIS_SRCH: mprintf((0, "SRCH ")); break; + case AIS_LOCK: mprintf((0, "LOCK ")); break; + case AIS_FLIN: mprintf((0, "FLIN ")); break; + case AIS_FIRE: mprintf((0, "FIRE ")); break; + case AIS_RECO: mprintf((0, "RECO ")); break; + case AIS_ERR_: mprintf((0, "ERR_ ")); break; + + } + + mprintf((0, " Cur = ")); + + switch (aip->CURRENT_STATE) { + case AIS_NONE: mprintf((0, "NONE ")); break; + case AIS_REST: mprintf((0, "REST ")); break; + case AIS_SRCH: mprintf((0, "SRCH ")); break; + case AIS_LOCK: mprintf((0, "LOCK ")); break; + case AIS_FLIN: mprintf((0, "FLIN ")); break; + case AIS_FIRE: mprintf((0, "FIRE ")); break; + case AIS_RECO: mprintf((0, "RECO ")); break; + case AIS_ERR_: mprintf((0, "ERR_ ")); break; + } + + mprintf((0, " Aware = ")); + + switch (ailp->player_awareness_type) { + case AIE_FIRE: mprintf((0, "FIRE ")); break; + case AIE_HITT: mprintf((0, "HITT ")); break; + case AIE_COLL: mprintf((0, "COLL ")); break; + case AIE_HURT: mprintf((0, "HURT ")); break; + } + + mprintf((0, "Next fire = %6.3f, Time = %6.3f\n", f2fl(ailp->next_fire), f2fl(ailp->player_awareness_time))); + +} +#endif + +// ------------------------------------------------------------------------------------------------------------------- +int Break_on_object = -1; + +void do_firing_stuff(object *obj, int player_visibility, vms_vector *vec_to_player) +{ + if ((Dist_to_last_fired_upon_player_pos < FIRE_AT_NEARBY_PLAYER_THRESHOLD ) || (player_visibility >= 1)) { + // Now, if in robot's field of view, lock onto player + fix dot = vm_vec_dot(&obj->orient.fvec, vec_to_player); + if ((dot >= 7*F1_0/8) || (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED)) { + ai_static *aip = &obj->ctype.ai_info; + ai_local *ailp = &Ai_local_info[obj-Objects]; + + switch (aip->GOAL_STATE) { + case AIS_NONE: + case AIS_REST: + case AIS_SRCH: + case AIS_LOCK: + aip->GOAL_STATE = AIS_FIRE; + if (ailp->player_awareness_type <= PA_NEARBY_ROBOT_FIRED) { + ailp->player_awareness_type = PA_NEARBY_ROBOT_FIRED; + ailp->player_awareness_time = PLAYER_AWARENESS_INITIAL_TIME; + } + break; + } + } else if (dot >= F1_0/2) { + ai_static *aip = &obj->ctype.ai_info; + switch (aip->GOAL_STATE) { + case AIS_NONE: + case AIS_REST: + case AIS_SRCH: + aip->GOAL_STATE = AIS_LOCK; + break; + } + } + } +} + +// -------------------------------------------------------------------------------------------------------------------- +// If a hiding robot gets bumped or hit, he decides to find another hiding place. +void do_ai_robot_hit(object *objp, int type) +{ + if (objp->control_type == CT_AI) { + if ((type == PA_WEAPON_ROBOT_COLLISION) || (type == PA_PLAYER_COLLISION)) + switch (objp->ctype.ai_info.behavior) { + case AIB_STILL: + { + int r; + + // Attack robots (eg, green guy) shouldn't have behavior = still. + Assert(Robot_info[objp->id].attack_type == 0); + + r = d_rand(); + // 1/8 time, charge player, 1/4 time create path, rest of time, do nothing + if (r < 4096) { + // -- mprintf((0, "Still guy switching to Station, creating path to player.")); + create_path_to_player(objp, 10, 1); + objp->ctype.ai_info.behavior = AIB_STATION; + objp->ctype.ai_info.hide_segment = objp->segnum; + Ai_local_info[objp-Objects].mode = AIM_CHASE_OBJECT; + } else if (r < 4096+8192) { + // -- mprintf((0, "Still guy creating n segment path.")); + create_n_segment_path(objp, d_rand()/8192 + 2, -1); + Ai_local_info[objp-Objects].mode = AIM_FOLLOW_PATH; + } + break; + } + } + } + +} +#ifndef NDEBUG +int Do_ai_flag=1; +int Cvv_test=0; +int Cvv_last_time[MAX_OBJECTS]; +int Gun_point_hack=0; +#endif + +int Robot_sound_volume=DEFAULT_ROBOT_SOUND_VOLUME; + +// -------------------------------------------------------------------------------------------------------------------- +// Note: This function could be optimized. Surely player_is_visible_from_object would benefit from the +// information of a normalized vec_to_player. +// Return player visibility: +// 0 not visible +// 1 visible, but robot not looking at player (ie, on an unobstructed vector) +// 2 visible and in robot's field of view +// -1 player is cloaked +// If the player is cloaked, set vec_to_player based on time player cloaked and last uncloaked position. +// Updates ailp->previous_visibility if player is not cloaked, in which case the previous visibility is left unchanged +// and is copied to player_visibility +void compute_vis_and_vec(object *objp, vms_vector *pos, ai_local *ailp, vms_vector *vec_to_player, int *player_visibility, robot_info *robptr, int *flag) +{ + if (!*flag) { + if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) { + fix delta_time, dist; + int cloak_index = (objp-Objects) % MAX_AI_CLOAK_INFO; + + delta_time = GameTime - Ai_cloak_info[cloak_index].last_time; + if (delta_time > F1_0*2) { + vms_vector randvec; + + Ai_cloak_info[cloak_index].last_time = GameTime; + make_random_vector(&randvec); + vm_vec_scale_add2(&Ai_cloak_info[cloak_index].last_position, &randvec, 8*delta_time ); + } + + dist = vm_vec_normalized_dir_quick(vec_to_player, &Ai_cloak_info[cloak_index].last_position, pos); + *player_visibility = player_is_visible_from_object(objp, pos, robptr->field_of_view[Difficulty_level], vec_to_player); + // *player_visibility = 2; + + if ((ailp->next_misc_sound_time < GameTime) && ((ailp->next_fire < F1_0) || (ailp->next_fire2 < F1_0)) && (dist < F1_0*20)) { + // mprintf((0, "ANGRY! ")); + ailp->next_misc_sound_time = GameTime + (d_rand() + F1_0) * (7 - Difficulty_level) / 1; + digi_link_sound_to_pos( robptr->see_sound, objp->segnum, 0, pos, 0 , Robot_sound_volume); + } + } else { + // Compute expensive stuff -- vec_to_player and player_visibility + vm_vec_normalized_dir_quick(vec_to_player, &Believed_player_pos, pos); + if ((vec_to_player->x == 0) && (vec_to_player->y == 0) && (vec_to_player->z == 0)) { + // -- mprintf((0, "Warning: Player and robot at exactly the same location.\n")); + vec_to_player->x = F1_0; + } + *player_visibility = player_is_visible_from_object(objp, pos, robptr->field_of_view[Difficulty_level], vec_to_player); + + // This horrible code added by MK in desperation on 12/13/94 to make robots wake up as soon as they + // see you without killing frame rate. + { + ai_static *aip = &objp->ctype.ai_info; + if ((*player_visibility == 2) && (ailp->previous_visibility != 2)) + if ((aip->GOAL_STATE == AIS_REST) || (aip->CURRENT_STATE == AIS_REST)) { + aip->GOAL_STATE = AIS_FIRE; + aip->CURRENT_STATE = AIS_FIRE; + } + } + + if ((ailp->previous_visibility != *player_visibility) && (*player_visibility == 2)) { + if (ailp->previous_visibility == 0) { + if (ailp->time_player_seen + F1_0/2 < GameTime) { + // -- mprintf((0, "SEE! ")); + // -- if (Player_exploded) + // -- digi_link_sound_to_pos( robptr->taunt_sound, objp->segnum, 0, pos, 0 , Robot_sound_volume); + // -- else + digi_link_sound_to_pos( robptr->see_sound, objp->segnum, 0, pos, 0 , Robot_sound_volume); + ailp->time_player_sound_attacked = GameTime; + ailp->next_misc_sound_time = GameTime + F1_0 + d_rand()*4; + } + } else if (ailp->time_player_sound_attacked + F1_0/4 < GameTime) { + // -- mprintf((0, "ANGRY! ")); + // -- if (Player_exploded) + // -- digi_link_sound_to_pos( robptr->taunt_sound, objp->segnum, 0, pos, 0 , Robot_sound_volume); + // -- else + digi_link_sound_to_pos( robptr->attack_sound, objp->segnum, 0, pos, 0 , Robot_sound_volume); + ailp->time_player_sound_attacked = GameTime; + } + } + + if ((*player_visibility == 2) && (ailp->next_misc_sound_time < GameTime)) { + // -- mprintf((0, "ATTACK! ")); + ailp->next_misc_sound_time = GameTime + (d_rand() + F1_0) * (7 - Difficulty_level) / 2; + // -- if (Player_exploded) + // -- digi_link_sound_to_pos( robptr->taunt_sound, objp->segnum, 0, pos, 0 , Robot_sound_volume); + // -- else + digi_link_sound_to_pos( robptr->attack_sound, objp->segnum, 0, pos, 0 , Robot_sound_volume); + } + ailp->previous_visibility = *player_visibility; + } + + *flag = 1; + + // @mk, 09/21/95: If player view is not obstructed and awareness is at least as high as a nearby collision, + // act is if robot is looking at player. + if (ailp->player_awareness_type >= PA_NEARBY_ROBOT_FIRED) + if (*player_visibility == 1) + *player_visibility = 2; + + if (*player_visibility) { + ailp->time_player_seen = GameTime; + } + } + +} + +// -------------------------------------------------------------------------------------------------------------------- +// Move the object objp to a spot in which it doesn't intersect a wall. +// It might mean moving it outside its current segment. +void move_object_to_legal_spot(object *objp) +{ + vms_vector original_pos = objp->pos; + int i; + segment *segp = &Segments[objp->segnum]; + + for (i=0; ichildren[i]]); + vm_vec_sub(&goal_dir, &segment_center, &objp->pos); + dist_to_center = vm_vec_normalize_quick(&goal_dir); + vm_vec_scale(&goal_dir, objp->size); + vm_vec_add2(&objp->pos, &goal_dir); + if (!object_intersects_wall(objp)) { + int new_segnum = find_point_seg(&objp->pos, objp->segnum); + + if (new_segnum != -1) { + obj_relink(objp-Objects, new_segnum); + return; + } + } else + objp->pos = original_pos; + } + } + + if (Robot_info[objp->id].boss_flag) { + Int3(); // Note: Boss is poking outside mine. Will try to resolve. + teleport_boss(objp); + } else { + mprintf((0, "Note: Killing robot #%i because he's badly stuck outside the mine.\n", objp-Objects)); + apply_damage_to_robot(objp, objp->shields*2, objp-Objects); + } +} + +// -------------------------------------------------------------------------------------------------------------------- +// Move object one object radii from current position towards segment center. +// If segment center is nearer than 2 radii, move it to center. +void move_towards_segment_center(object *objp) +{ + int segnum = objp->segnum; + fix dist_to_center; + vms_vector segment_center, goal_dir; + + compute_segment_center(&segment_center, &Segments[segnum]); + + vm_vec_sub(&goal_dir, &segment_center, &objp->pos); + dist_to_center = vm_vec_normalize_quick(&goal_dir); + + if (dist_to_center < objp->size) { + // Center is nearer than the distance we want to move, so move to center. + objp->pos = segment_center; + mprintf((0, "Object #%i moved to center of segment #%i (%7.3f %7.3f %7.3f)\n", objp-Objects, objp->segnum, f2fl(objp->pos.x), f2fl(objp->pos.y), f2fl(objp->pos.z))); + if (object_intersects_wall(objp)) { + mprintf((0, "Object #%i still illegal, trying trickier move.\n")); + move_object_to_legal_spot(objp); + } + } else { + int new_segnum; + // Move one radii towards center. + vm_vec_scale(&goal_dir, objp->size); + vm_vec_add2(&objp->pos, &goal_dir); + new_segnum = find_point_seg(&objp->pos, objp->segnum); + if (new_segnum == -1) { + objp->pos = segment_center; + move_object_to_legal_spot(objp); + } + // -- mprintf((0, "Obj %i moved twrds seg %i (%6.2f %6.2f %6.2f), dists: [%6.2f %6.2f]\n", objp-Objects, objp->segnum, f2fl(objp->pos.x), f2fl(objp->pos.y), f2fl(objp->pos.z), f2fl(vm_vec_dist_quick(&objp->pos, &segment_center)), f2fl(vm_vec_dist_quick(&objp->pos, &segment_center)))); + } + +} + +extern int Buddy_objnum; + +//int Buddy_got_stuck = 0; + +// ----------------------------------------------------------------------------------------------------------- +// Return true if door can be flown through by a suitable type robot. +// Brains, avoid robots, companions can open doors. +// objp == NULL means treat as buddy. +int ai_door_is_openable(object *objp, segment *segp, int sidenum) +{ + int wall_num; + wall *wallp; + + if (!IS_CHILD(segp->children[sidenum])) + return 0; //trap -2 (exit side) + + wall_num = segp->sides[sidenum].wall_num; + + if (wall_num == -1) //if there's no door at all... + return 0; //..then say it can't be opened + + // The mighty console object can open all doors (for purposes of determining paths). + if (objp == ConsoleObject) { + + if (Walls[wall_num].type == WALL_DOOR) + return 1; + } + + wallp = &Walls[wall_num]; + + if ((objp == NULL) || (Robot_info[objp->id].companion == 1)) { + int ailp_mode; + + if (wallp->flags & WALL_BUDDY_PROOF) { + if ((wallp->type == WALL_DOOR) && (wallp->state == WALL_DOOR_CLOSED)) + return 0; + else if (wallp->type == WALL_CLOSED) + return 0; + else if ((wallp->type == WALL_ILLUSION) && !(wallp->flags & WALL_ILLUSION_OFF)) + return 0; + } + + if (wallp->keys != KEY_NONE) { + if (wallp->keys == KEY_BLUE) + return (Players[Player_num].flags & PLAYER_FLAGS_BLUE_KEY); + else if (wallp->keys == KEY_GOLD) + return (Players[Player_num].flags & PLAYER_FLAGS_GOLD_KEY); + else if (wallp->keys == KEY_RED) + return (Players[Player_num].flags & PLAYER_FLAGS_RED_KEY); + } + + if ((wallp->type != WALL_DOOR) && (wallp->type != WALL_CLOSED)) + return 1; + + // If Buddy is returning to player, don't let him think he can get through triggered doors. + // It's only valid to think that if the player is going to get him through. But if he's + // going to the player, the player is probably on the opposite side. + if (objp == NULL) + ailp_mode = Ai_local_info[Buddy_objnum].mode; + else + ailp_mode = Ai_local_info[objp-Objects].mode; + + // -- if (Buddy_got_stuck) { + if (ailp_mode == AIM_GOTO_PLAYER) { + if ((wallp->type == WALL_BLASTABLE) && (wallp->state != WALL_BLASTED)) + return 0; + if (wallp->type == WALL_CLOSED) + return 0; + if (wallp->type == WALL_DOOR) { + if ((wallp->flags & WALL_DOOR_LOCKED) && (wallp->state == WALL_DOOR_CLOSED)) + return 0; + } + } + // -- } + + if ((ailp_mode != AIM_GOTO_PLAYER) && (wallp->controlling_trigger != -1)) { + int clip_num = wallp->clip_num; + + if (clip_num == -1) + return 1; + else if (WallAnims[clip_num].flags & WCF_HIDDEN) { + if (wallp->state == WALL_DOOR_CLOSED) + return 0; + else + return 1; + } else + return 1; + } + + if (wallp->type == WALL_DOOR) { + if (wallp->type == WALL_BLASTABLE) + return 1; + else { + int clip_num = wallp->clip_num; + + if (clip_num == -1) + return 1; + // Buddy allowed to go through secret doors to get to player. + else if ((ailp_mode != AIM_GOTO_PLAYER) && (WallAnims[clip_num].flags & WCF_HIDDEN)) { + if (wallp->state == WALL_DOOR_CLOSED) + return 0; + else + return 1; + } else + return 1; + } + } + } else if ((objp->id == ROBOT_BRAIN) || (objp->ctype.ai_info.behavior == AIB_RUN_FROM) || (objp->ctype.ai_info.behavior == AIB_SNIPE)) { + if (wall_num != -1) + { + if ((wallp->type == WALL_DOOR) && (wallp->keys == KEY_NONE) && !(wallp->flags & WALL_DOOR_LOCKED)) + return 1; + else if (wallp->keys != KEY_NONE) { // Allow bots to open doors to which player has keys. + if (wallp->keys & Players[Player_num].flags) + return 1; + } + } + } + return 0; +} + +// ----------------------------------------------------------------------------------------------------------- +// Return side of openable door in segment, if any. If none, return -1. +int openable_doors_in_segment(int segnum) +{ + int i; + + if ((segnum < 0) || (segnum > Highest_segment_index)) + return -1; + + for (i=0; i> 15; +// -- +// -- while (!(WALL_IS_DOORWAY(segp, sidenum) & WID_FLY_FLAG)) +// -- sidenum = (rand() * 6) >> 15; +// -- +// -- segnum = segp->children[sidenum]; +// -- +// -- return segnum; +// -- } + +// -------------------------------------------------------------------------------------------------------------------- +// Return true if placing an object of size size at pos *pos intersects a (player or robot or control center) in segment *segp. +int check_object_object_intersection(vms_vector *pos, fix size, segment *segp) +{ + int curobjnum; + + // If this would intersect with another object (only check those in this segment), then try to move. + curobjnum = segp->objects; + while (curobjnum != -1) { + object *curobjp = &Objects[curobjnum]; + if ((curobjp->type == OBJ_PLAYER) || (curobjp->type == OBJ_ROBOT) || (curobjp->type == OBJ_CNTRLCEN)) { + if (vm_vec_dist_quick(pos, &curobjp->pos) < size + curobjp->size) + return 1; + } + curobjnum = curobjp->next; + } + + return 0; + +} + +// -------------------------------------------------------------------------------------------------------------------- +// Return objnum if object created, else return -1. +// If pos == NULL, pick random spot in segment. +int create_gated_robot( int segnum, int object_id, vms_vector *pos) +{ + int objnum; + object *objp; + segment *segp = &Segments[segnum]; + vms_vector object_pos; + robot_info *robptr = &Robot_info[object_id]; + int i, count=0; + fix objsize = Polygon_models[robptr->model_num].rad; + int default_behavior; + + if (GameTime - Last_gate_time < Gate_interval) + return -1; + + for (i=0; i<=Highest_object_index; i++) + if (Objects[i].type == OBJ_ROBOT) + if (Objects[i].matcen_creator == BOSS_GATE_MATCEN_NUM) + count++; + + if (count > 2*Difficulty_level + 6) { + //mprintf((0, "Cannot gate in a robot until you kill one.\n")); + Last_gate_time = GameTime - 3*Gate_interval/4; + return -1; + } + + compute_segment_center(&object_pos, segp); + if (pos == NULL) + pick_random_point_in_seg(&object_pos, segp-Segments); + else + object_pos = *pos; + + // See if legal to place object here. If not, move about in segment and try again. + if (check_object_object_intersection(&object_pos, objsize, segp)) { + //mprintf((0, "Can't get in because object collides with something.\n")); + Last_gate_time = GameTime - 3*Gate_interval/4; + return -1; + } + + objnum = obj_create(OBJ_ROBOT, object_id, segnum, &object_pos, &vmd_identity_matrix, objsize, CT_AI, MT_PHYSICS, RT_POLYOBJ); + + if ( objnum < 0 ) { + // mprintf((1, "Can't get object to gate in robot. Not gating in.\n")); + Last_gate_time = GameTime - 3*Gate_interval/4; + return -1; + } + + //mprintf((0, "Gating in object %i in segment %i\n", objnum, segp-Segments)); + + Objects[objnum].lifeleft = F1_0*30; // Gated in robots only live 30 seconds. + +#ifdef NETWORK + Net_create_objnums[0] = objnum; // A convenient global to get objnum back to caller for multiplayer +#endif + + objp = &Objects[objnum]; + + //Set polygon-object-specific data + + objp->rtype.pobj_info.model_num = robptr->model_num; + objp->rtype.pobj_info.subobj_flags = 0; + + //set Physics info + + objp->mtype.phys_info.mass = robptr->mass; + objp->mtype.phys_info.drag = robptr->drag; + + objp->mtype.phys_info.flags |= (PF_LEVELLING); + + objp->shields = robptr->strength; + objp->matcen_creator = BOSS_GATE_MATCEN_NUM; // flag this robot as having been created by the boss. + + default_behavior = Robot_info[objp->id].behavior; + init_ai_object(objp-Objects, default_behavior, -1 ); // Note, -1 = segment this robot goes to to hide, should probably be something useful + + object_create_explosion(segnum, &object_pos, i2f(10), VCLIP_MORPHING_ROBOT ); + digi_link_sound_to_pos( Vclip[VCLIP_MORPHING_ROBOT].sound_num, segnum, 0, &object_pos, 0 , F1_0); + morph_start(objp); + + Last_gate_time = GameTime; + + Players[Player_num].num_robots_level++; + Players[Player_num].num_robots_total++; + + return objp-Objects; +} + +#define MAX_SPEW_BOT 3 + +int Spew_bots[NUM_D2_BOSSES][MAX_SPEW_BOT] = { + {38, 40, -1}, + {37, -1, -1}, + {43, 57, -1}, + {26, 27, 58}, + {59, 58, 54}, + {60, 61, 54}, + + {69, 29, 24}, + {72, 60, 73} +}; + +int Max_spew_bots[NUM_D2_BOSSES] = {2, 1, 2, 3, 3, 3, 3, 3}; + +// ---------------------------------------------------------------------------------------------------------- +// objp points at a boss. He was presumably just hit and he's supposed to create a bot at the hit location *pos. +int boss_spew_robot(object *objp, vms_vector *pos) +{ + int objnum, segnum; + int boss_index; + + boss_index = Robot_info[objp->id].boss_flag - BOSS_D2; + + Assert((boss_index >= 0) && (boss_index < NUM_D2_BOSSES)); + + segnum = find_point_seg(pos, objp->segnum); + if (segnum == -1) { + mprintf((0, "Tried to spew a bot outside the mine! Aborting!\n")); + return -1; + } + + objnum = create_gated_robot( segnum, Spew_bots[boss_index][(Max_spew_bots[boss_index] * d_rand()) >> 15], pos); + + // Make spewed robot come tumbling out as if blasted by a flash missile. + if (objnum != -1) { + object *newobjp = &Objects[objnum]; + int force_val; + + force_val = F1_0/FrameTime; + + if (force_val) { + newobjp->ctype.ai_info.SKIP_AI_COUNT += force_val; + newobjp->mtype.phys_info.rotthrust.x = ((d_rand() - 16384) * force_val)/16; + newobjp->mtype.phys_info.rotthrust.y = ((d_rand() - 16384) * force_val)/16; + newobjp->mtype.phys_info.rotthrust.z = ((d_rand() - 16384) * force_val)/16; + newobjp->mtype.phys_info.flags |= PF_USES_THRUST; + + // Now, give a big initial velocity to get moving away from boss. + vm_vec_sub(&newobjp->mtype.phys_info.velocity, pos, &objp->pos); + vm_vec_normalize_quick(&newobjp->mtype.phys_info.velocity); + vm_vec_scale(&newobjp->mtype.phys_info.velocity, F1_0*128); + } + } + + return objnum; +} + +// -------------------------------------------------------------------------------------------------------------------- +// Call this each time the player starts a new ship. +void init_ai_for_ship(void) +{ + int i; + + for (i=0; isegnum; + Ai_cloak_info[i].last_position = ConsoleObject->pos; + } +} + +// -------------------------------------------------------------------------------------------------------------------- +// Make object objp gate in a robot. +// The process of him bringing in a robot takes one second. +// Then a robot appears somewhere near the player. +// Return objnum if robot successfully created, else return -1 +int gate_in_robot(int type, int segnum) +{ + if (segnum < 0) + segnum = Boss_gate_segs[(d_rand() * Num_boss_gate_segs) >> 15]; + + Assert((segnum >= 0) && (segnum <= Highest_segment_index)); + + return create_gated_robot(segnum, type, NULL); +} + +// -------------------------------------------------------------------------------------------------------------------- +int boss_fits_in_seg(object *boss_objp, int segnum) +{ + vms_vector segcenter; + int boss_objnum = boss_objp-Objects; + int posnum; + + compute_segment_center(&segcenter, &Segments[segnum]); + + for (posnum=0; posnum<9; posnum++) { + if (posnum > 0) { + vms_vector vertex_pos; + + Assert((posnum-1 >= 0) && (posnum-1 < 8)); + vertex_pos = Vertices[Segments[segnum].verts[posnum-1]]; + vm_vec_avg(&boss_objp->pos, &vertex_pos, &segcenter); + } else + boss_objp->pos = segcenter; + + obj_relink(boss_objnum, segnum); + if (!object_intersects_wall(boss_objp)) + return 1; + } + + return 0; +} + +// -------------------------------------------------------------------------------------------------------------------- +void teleport_boss(object *objp) +{ + int rand_segnum, rand_index; + vms_vector boss_dir; + Assert(Num_boss_teleport_segs > 0); + + // Pick a random segment from the list of boss-teleportable-to segments. + rand_index = (d_rand() * Num_boss_teleport_segs) >> 15; + rand_segnum = Boss_teleport_segs[rand_index]; + Assert((rand_segnum >= 0) && (rand_segnum <= Highest_segment_index)); + + //mprintf((0, "Frame %i: Boss teleporting to segment #%i, pos = {%8x %8x %8x}.\n", FrameCount, rand_segnum, objp->pos.x, objp->pos.y, objp->pos.z)); + +#ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_boss_actions(objp-Objects, 1, rand_segnum, 0); +#endif + + compute_segment_center(&objp->pos, &Segments[rand_segnum]); + obj_relink(objp-Objects, rand_segnum); + + Last_teleport_time = GameTime; + + // make boss point right at player + vm_vec_sub(&boss_dir, &Objects[Players[Player_num].objnum].pos, &objp->pos); + vm_vector_2_matrix(&objp->orient, &boss_dir, NULL, NULL); + + digi_link_sound_to_pos( Vclip[VCLIP_MORPHING_ROBOT].sound_num, rand_segnum, 0, &objp->pos, 0 , F1_0); + digi_kill_sound_linked_to_object( objp-Objects); + digi_link_sound_to_object2( Robot_info[objp->id].see_sound, objp-Objects, 1, F1_0, F1_0*512 ); // F1_0*512 means play twice as loud + + // After a teleport, boss can fire right away. + Ai_local_info[objp-Objects].next_fire = 0; + Ai_local_info[objp-Objects].next_fire2 = 0; + +} + +// ---------------------------------------------------------------------- +void start_boss_death_sequence(object *objp) +{ + if (Robot_info[objp->id].boss_flag) { + Boss_dying = 1; + Boss_dying_start_time = GameTime; + } + +} + +// ---------------------------------------------------------------------- +// General purpose robot-dies-with-death-roll-and-groan code. +// Return true if object just died. +// scale: F1_0*4 for boss, much smaller for much smaller guys +int do_robot_dying_frame(object *objp, fix start_time, fix roll_duration, byte *dying_sound_playing, int death_sound, fix expl_scale, fix sound_scale) +{ + fix roll_val, temp; + fix sound_duration; + + if (!roll_duration) + roll_duration = F1_0/4; + + roll_val = fixdiv(GameTime - start_time, roll_duration); + + fix_sincos(fixmul(roll_val, roll_val), &temp, &objp->mtype.phys_info.rotvel.x); + fix_sincos(roll_val, &temp, &objp->mtype.phys_info.rotvel.y); + fix_sincos(roll_val-F1_0/8, &temp, &objp->mtype.phys_info.rotvel.z); + + objp->mtype.phys_info.rotvel.x = (GameTime - start_time)/9; + objp->mtype.phys_info.rotvel.y = (GameTime - start_time)/5; + objp->mtype.phys_info.rotvel.z = (GameTime - start_time)/7; + + if (digi_sample_rate) + sound_duration = fixdiv(GameSounds[digi_xlat_sound(death_sound)].length,digi_sample_rate); + else + sound_duration = F1_0; + + if (start_time + roll_duration - sound_duration < GameTime) { + if (!*dying_sound_playing) { + mprintf((0, "Starting death sound!\n")); + *dying_sound_playing = 1; + digi_link_sound_to_object2( death_sound, objp-Objects, 0, sound_scale, sound_scale*256 ); // F1_0*512 means play twice as loud + } else if (d_rand() < FrameTime*16) + create_small_fireball_on_object(objp, (F1_0 + d_rand()) * (16 * expl_scale/F1_0)/8, 0); + } else if (d_rand() < FrameTime*8) + create_small_fireball_on_object(objp, (F1_0/2 + d_rand()) * (16 * expl_scale/F1_0)/8, 1); + + if (start_time + roll_duration < GameTime) + return 1; + else + return 0; +} + +// ---------------------------------------------------------------------- +void start_robot_death_sequence(object *objp) +{ + objp->ctype.ai_info.dying_start_time = GameTime; + objp->ctype.ai_info.dying_sound_playing = 0; + objp->ctype.ai_info.SKIP_AI_COUNT = 0; + +} + +// ---------------------------------------------------------------------- +void do_boss_dying_frame(object *objp) +{ + int rval; + + rval = do_robot_dying_frame(objp, Boss_dying_start_time, BOSS_DEATH_DURATION, &Boss_dying_sound_playing, Robot_info[objp->id].deathroll_sound, F1_0*4, F1_0*4); + + if (rval) { + do_controlcen_destroyed_stuff(NULL); + explode_object(objp, F1_0/4); + digi_link_sound_to_object2(SOUND_BADASS_EXPLOSION, objp-Objects, 0, F2_0, F1_0*512); + } +} + +extern void recreate_thief(object *objp); + +// ---------------------------------------------------------------------- +int do_any_robot_dying_frame(object *objp) +{ + if (objp->ctype.ai_info.dying_start_time) { + int rval, death_roll; + + death_roll = Robot_info[objp->id].death_roll; + rval = do_robot_dying_frame(objp, objp->ctype.ai_info.dying_start_time, min(death_roll/2+1,6)*F1_0, &objp->ctype.ai_info.dying_sound_playing, Robot_info[objp->id].deathroll_sound, death_roll*F1_0/8, death_roll*F1_0/2); + + if (rval) { + explode_object(objp, F1_0/4); + digi_link_sound_to_object2(SOUND_BADASS_EXPLOSION, objp-Objects, 0, F2_0, F1_0*512); + if ((Current_level_num < 0) && (Robot_info[objp->id].thief)) + recreate_thief(objp); + } + + return 1; + } + + return 0; +} + +// -------------------------------------------------------------------------------------------------------------------- +// Called for an AI object if it is fairly aware of the player. +// awareness_level is in 0..100. Larger numbers indicate greater awareness (eg, 99 if firing at player). +// In a given frame, might not get called for an object, or might be called more than once. +// The fact that this routine is not called for a given object does not mean that object is not interested in the player. +// Objects are moved by physics, so they can move even if not interested in a player. However, if their velocity or +// orientation is changing, this routine will be called. +// Return value: +// 0 this player IS NOT allowed to move this robot. +// 1 this player IS allowed to move this robot. +int ai_multiplayer_awareness(object *objp, int awareness_level) +{ + int rval=1; + +#ifdef NETWORK + if (Game_mode & GM_MULTI) { + if (awareness_level == 0) + return 0; + rval = multi_can_move_robot(objp-Objects, awareness_level); + } +#endif + + return rval; + +} + +#ifndef NDEBUG +fix Prev_boss_shields = -1; +#endif + +// -------------------------------------------------------------------------------------------------------------------- +// Do special stuff for a boss. +void do_boss_stuff(object *objp, int player_visibility) +{ + int boss_id, boss_index; + + boss_id = Robot_info[objp->id].boss_flag; + + Assert((boss_id >= BOSS_D2) && (boss_id < BOSS_D2 + NUM_D2_BOSSES)); + + boss_index = boss_id - BOSS_D2; + +#ifndef NDEBUG + if (objp->shields != Prev_boss_shields) { + mprintf((0, "Boss shields = %7.3f, object %i\n", f2fl(objp->shields), objp-Objects)); + Prev_boss_shields = objp->shields; + } +#endif + + // New code, fixes stupid bug which meant boss never gated in robots if > 32767 seconds played. + if (Last_teleport_time > GameTime) + Last_teleport_time = GameTime; + + if (Last_gate_time > GameTime) + Last_gate_time = GameTime; + + // @mk, 10/13/95: Reason: + // Level 4 boss behind locked door. But he's allowed to teleport out of there. So he + // teleports out of there right away, and blasts player right after first door. + if (!player_visibility && (GameTime - Boss_hit_time > F1_0*2)) + return; + + if (!Boss_dying && Boss_teleports[boss_index]) { + if (objp->ctype.ai_info.CLOAKED == 1) { + Boss_hit_time = GameTime; // Keep the cloak:teleport process going. + if ((GameTime - Boss_cloak_start_time > BOSS_CLOAK_DURATION/3) && (Boss_cloak_end_time - GameTime > BOSS_CLOAK_DURATION/3) && (GameTime - Last_teleport_time > Boss_teleport_interval)) { + if (ai_multiplayer_awareness(objp, 98)) + teleport_boss(objp); + } else if (GameTime - Boss_hit_time > F1_0*2) { + Last_teleport_time -= Boss_teleport_interval/4; + } + + if (GameTime > Boss_cloak_end_time || GameTime < Boss_cloak_start_time) + objp->ctype.ai_info.CLOAKED = 0; + } else if ((GameTime - Boss_cloak_end_time > Boss_cloak_interval) || (GameTime - Boss_cloak_end_time < -Boss_cloak_duration)) { + if (ai_multiplayer_awareness(objp, 95)) { + Boss_cloak_start_time = GameTime; + Boss_cloak_end_time = GameTime+Boss_cloak_duration; + objp->ctype.ai_info.CLOAKED = 1; +#ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_boss_actions(objp-Objects, 2, 0, 0); +#endif + } + } + } + +} + +#define BOSS_TO_PLAYER_GATE_DISTANCE (F1_0*200) + +// -- Obsolete D1 code -- // -------------------------------------------------------------------------------------------------------------------- +// -- Obsolete D1 code -- // Do special stuff for a boss. +// -- Obsolete D1 code -- void do_super_boss_stuff(object *objp, fix dist_to_player, int player_visibility) +// -- Obsolete D1 code -- { +// -- Obsolete D1 code -- static int eclip_state = 0; +// -- Obsolete D1 code -- +// -- Obsolete D1 code -- do_boss_stuff(objp, player_visibility); +// -- Obsolete D1 code -- +// -- Obsolete D1 code -- // Only master player can cause gating to occur. +// -- Obsolete D1 code -- if ((Game_mode & GM_MULTI) && !network_i_am_master()) +// -- Obsolete D1 code -- return; +// -- Obsolete D1 code -- +// -- Obsolete D1 code -- if ((dist_to_player < BOSS_TO_PLAYER_GATE_DISTANCE) || player_visibility || (Game_mode & GM_MULTI)) { +// -- Obsolete D1 code -- if (GameTime - Last_gate_time > Gate_interval/2) { +// -- Obsolete D1 code -- restart_effect(BOSS_ECLIP_NUM); +// -- Obsolete D1 code -- if (eclip_state == 0) { +// -- Obsolete D1 code -- multi_send_boss_actions(objp-Objects, 4, 0, 0); +// -- Obsolete D1 code -- eclip_state = 1; +// -- Obsolete D1 code -- } +// -- Obsolete D1 code -- } +// -- Obsolete D1 code -- else { +// -- Obsolete D1 code -- stop_effect(BOSS_ECLIP_NUM); +// -- Obsolete D1 code -- if (eclip_state == 1) { +// -- Obsolete D1 code -- multi_send_boss_actions(objp-Objects, 5, 0, 0); +// -- Obsolete D1 code -- eclip_state = 0; +// -- Obsolete D1 code -- } +// -- Obsolete D1 code -- } +// -- Obsolete D1 code -- +// -- Obsolete D1 code -- if (GameTime - Last_gate_time > Gate_interval) +// -- Obsolete D1 code -- if (ai_multiplayer_awareness(objp, 99)) { +// -- Obsolete D1 code -- int rtval; +// -- Obsolete D1 code -- int randtype = (d_rand() * MAX_GATE_INDEX) >> 15; +// -- Obsolete D1 code -- +// -- Obsolete D1 code -- Assert(randtype < MAX_GATE_INDEX); +// -- Obsolete D1 code -- randtype = Super_boss_gate_list[randtype]; +// -- Obsolete D1 code -- Assert(randtype < N_robot_types); +// -- Obsolete D1 code -- +// -- Obsolete D1 code -- rtval = gate_in_robot(randtype, -1); +// -- Obsolete D1 code -- if ((rtval != -1) && (Game_mode & GM_MULTI)) +// -- Obsolete D1 code -- { +// -- Obsolete D1 code -- multi_send_boss_actions(objp-Objects, 3, randtype, Net_create_objnums[0]); +// -- Obsolete D1 code -- map_objnum_local_to_local(Net_create_objnums[0]); +// -- Obsolete D1 code -- } +// -- Obsolete D1 code -- } +// -- Obsolete D1 code -- } +// -- Obsolete D1 code -- } + +//int multi_can_move_robot(object *objp, int awareness_level) +//{ +// return 0; +//} + +void ai_multi_send_robot_position(int objnum, int force) +{ +#ifdef NETWORK + if (Game_mode & GM_MULTI) + { + if (force != -1) + multi_send_robot_position(objnum, 1); + else + multi_send_robot_position(objnum, 0); + } +#endif + return; +} + +// -------------------------------------------------------------------------------------------------------------------- +// Returns true if this object should be allowed to fire at the player. +int maybe_ai_do_actual_firing_stuff(object *obj, ai_static *aip) +{ +#ifdef NETWORK + if (Game_mode & GM_MULTI) + if ((aip->GOAL_STATE != AIS_FLIN) && (obj->id != ROBOT_BRAIN)) + if (aip->CURRENT_STATE == AIS_FIRE) + return 1; +#endif + + return 0; +} + +vms_vector Last_fired_upon_player_pos; + +// -------------------------------------------------------------------------------------------------------------------- +// If fire_anyway, fire even if player is not visible. We're firing near where we believe him to be. Perhaps he's +// lurking behind a corner. +void ai_do_actual_firing_stuff(object *obj, ai_static *aip, ai_local *ailp, robot_info *robptr, vms_vector *vec_to_player, fix dist_to_player, vms_vector *gun_point, int player_visibility, int object_animates, int gun_num) +{ + fix dot; + + if ((player_visibility == 2) || (Dist_to_last_fired_upon_player_pos < FIRE_AT_NEARBY_PLAYER_THRESHOLD )) { + vms_vector fire_pos; + + fire_pos = Believed_player_pos; + + // Hack: If visibility not == 2, we're here because we're firing at a nearby player. + // So, fire at Last_fired_upon_player_pos instead of the player position. + if (!robptr->attack_type && (player_visibility != 2)) + fire_pos = Last_fired_upon_player_pos; + + // Changed by mk, 01/04/95, onearm would take about 9 seconds until he can fire at you. + // Above comment corrected. Date changed from 1994, to 1995. Should fix some very subtle bugs, as well as not cause me to wonder, in the future, why I was writing AI code for onearm ten months before he existed. + if (!object_animates || ready_to_fire(robptr, ailp)) { + dot = vm_vec_dot(&obj->orient.fvec, vec_to_player); + if ((dot >= 7*F1_0/8) || ((dot > F1_0/4) && robptr->boss_flag)) { + + if (gun_num < Robot_info[obj->id].n_guns) { + if (robptr->attack_type == 1) { + if (!Player_exploded && (dist_to_player < obj->size + ConsoleObject->size + F1_0*2)) { // robptr->circle_distance[Difficulty_level] + ConsoleObject->size) { + if (!ai_multiplayer_awareness(obj, ROBOT_FIRE_AGITATION-2)) + return; + do_ai_robot_hit_attack(obj, ConsoleObject, &obj->pos); + } else { + // mprintf((0, "Green won't fire: Too far: dist = %7.3f, threshold = %7.3f\n", f2fl(dist_to_player), f2fl(obj->size + ConsoleObject->size + F1_0*2))); + return; + } + } else { + if ((gun_point->x == 0) && (gun_point->y == 0) && (gun_point->z == 0)) { + ; //mprintf((0, "Would like to fire gun, but gun not selected.\n")); + } else { + if (!ai_multiplayer_awareness(obj, ROBOT_FIRE_AGITATION)) + return; + // New, multi-weapon-type system, 06/05/95 (life is slipping away...) + if (gun_num != 0) { + if (ailp->next_fire <= 0) { + ai_fire_laser_at_player(obj, gun_point, gun_num, &fire_pos); + Last_fired_upon_player_pos = fire_pos; + } + + if ((ailp->next_fire2 <= 0) && (robptr->weapon_type2 != -1)) { + calc_gun_point(gun_point, obj, 0); + ai_fire_laser_at_player(obj, gun_point, 0, &fire_pos); + Last_fired_upon_player_pos = fire_pos; + } + + } else if (ailp->next_fire <= 0) { + ai_fire_laser_at_player(obj, gun_point, gun_num, &fire_pos); + Last_fired_upon_player_pos = fire_pos; + } + } + } + + // Wants to fire, so should go into chase mode, probably. + if ( (aip->behavior != AIB_RUN_FROM) + && (aip->behavior != AIB_STILL) + && (aip->behavior != AIB_SNIPE) + && (aip->behavior != AIB_FOLLOW) + && (!robptr->attack_type) + && ((ailp->mode == AIM_FOLLOW_PATH) || (ailp->mode == AIM_STILL))) + ailp->mode = AIM_CHASE_OBJECT; + } + + aip->GOAL_STATE = AIS_RECO; + ailp->goal_state[aip->CURRENT_GUN] = AIS_RECO; + + // Switch to next gun for next fire. If has 2 gun types, select gun #1, if exists. + aip->CURRENT_GUN++; + if (aip->CURRENT_GUN >= Robot_info[obj->id].n_guns) + { + if ((Robot_info[obj->id].n_guns == 1) || (Robot_info[obj->id].weapon_type2 == -1)) + aip->CURRENT_GUN = 0; + else + aip->CURRENT_GUN = 1; + } + } + } + } else if ( ((!robptr->attack_type) && (Weapon_info[Robot_info[obj->id].weapon_type].homing_flag == 1)) || (((Robot_info[obj->id].weapon_type2 != -1) && (Weapon_info[Robot_info[obj->id].weapon_type2].homing_flag == 1))) ) { + // Robots which fire homing weapons might fire even if they don't have a bead on the player. + if (((!object_animates) || (ailp->achieved_state[aip->CURRENT_GUN] == AIS_FIRE)) + && (((ailp->next_fire <= 0) && (aip->CURRENT_GUN != 0)) || ((ailp->next_fire2 <= 0) && (aip->CURRENT_GUN == 0))) + && (vm_vec_dist_quick(&Hit_pos, &obj->pos) > F1_0*40)) { + if (!ai_multiplayer_awareness(obj, ROBOT_FIRE_AGITATION)) + return; + ai_fire_laser_at_player(obj, gun_point, gun_num, &Believed_player_pos); + + aip->GOAL_STATE = AIS_RECO; + ailp->goal_state[aip->CURRENT_GUN] = AIS_RECO; + + // Switch to next gun for next fire. + aip->CURRENT_GUN++; + if (aip->CURRENT_GUN >= Robot_info[obj->id].n_guns) + aip->CURRENT_GUN = 0; + } else { + // Switch to next gun for next fire. + aip->CURRENT_GUN++; + if (aip->CURRENT_GUN >= Robot_info[obj->id].n_guns) + aip->CURRENT_GUN = 0; + } + } else { + + + // --------------------------------------------------------------- + + vms_vector vec_to_last_pos; + + if (d_rand()/2 < fixmul(FrameTime, (Difficulty_level << 12) + 0x4000)) { + if ((!object_animates || ready_to_fire(robptr, ailp)) && (Dist_to_last_fired_upon_player_pos < FIRE_AT_NEARBY_PLAYER_THRESHOLD)) { + vm_vec_normalized_dir_quick(&vec_to_last_pos, &Believed_player_pos, &obj->pos); + dot = vm_vec_dot(&obj->orient.fvec, &vec_to_last_pos); + if (dot >= 7*F1_0/8) { + + if (aip->CURRENT_GUN < Robot_info[obj->id].n_guns) { + if (robptr->attack_type == 1) { + if (!Player_exploded && (dist_to_player < obj->size + ConsoleObject->size + F1_0*2)) { // robptr->circle_distance[Difficulty_level] + ConsoleObject->size) { + if (!ai_multiplayer_awareness(obj, ROBOT_FIRE_AGITATION-2)) + return; + do_ai_robot_hit_attack(obj, ConsoleObject, &obj->pos); + } else { + // mprintf((0, "Green won't fire: Too far: dist = %7.3f, threshold = %7.3f\n", f2fl(dist_to_player), f2fl(obj->size + ConsoleObject->size + F1_0*2))); + return; + } + } else { + if ((gun_point->x == 0) && (gun_point->y == 0) && (gun_point->z == 0)) { + ; //mprintf((0, "Would like to fire gun, but gun not selected.\n")); + } else { + if (!ai_multiplayer_awareness(obj, ROBOT_FIRE_AGITATION)) + return; + // New, multi-weapon-type system, 06/05/95 (life is slipping away...) + if (gun_num != 0) { + if (ailp->next_fire <= 0) + ai_fire_laser_at_player(obj, gun_point, gun_num, &Last_fired_upon_player_pos); + + if ((ailp->next_fire2 <= 0) && (robptr->weapon_type2 != -1)) { + calc_gun_point(gun_point, obj, 0); + ai_fire_laser_at_player(obj, gun_point, 0, &Last_fired_upon_player_pos); + } + + } else if (ailp->next_fire <= 0) + ai_fire_laser_at_player(obj, gun_point, gun_num, &Last_fired_upon_player_pos); + } + } + + // Wants to fire, so should go into chase mode, probably. + if ( (aip->behavior != AIB_RUN_FROM) && (aip->behavior != AIB_STILL) && (aip->behavior != AIB_SNIPE) && (aip->behavior != AIB_FOLLOW) && ((ailp->mode == AIM_FOLLOW_PATH) || (ailp->mode == AIM_STILL))) + ailp->mode = AIM_CHASE_OBJECT; + } + aip->GOAL_STATE = AIS_RECO; + ailp->goal_state[aip->CURRENT_GUN] = AIS_RECO; + + // Switch to next gun for next fire. + aip->CURRENT_GUN++; + if (aip->CURRENT_GUN >= Robot_info[obj->id].n_guns) + { + if (Robot_info[obj->id].n_guns == 1) + aip->CURRENT_GUN = 0; + else + aip->CURRENT_GUN = 1; + } + } + } + } + + + // --------------------------------------------------------------- + + + } + +} + + diff --git a/main/aipath.c b/main/aipath.c new file mode 100644 index 00000000..6aa355aa --- /dev/null +++ b/main/aipath.c @@ -0,0 +1,1843 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#include +#include // for printf() +#include // for rand() and qsort() +#include // for memset() + +#include "inferno.h" +#include "mono.h" +#include "fix.h" +#include "vecmat.h" +#include "gr.h" +#include "3d.h" + +#include "object.h" +#include "error.h" +#include "ai.h" +#include "robot.h" +#include "fvi.h" +#include "physics.h" +#include "wall.h" +#include "player.h" +#include "fireball.h" +#include "game.h" +#include "maths.h" + +#ifdef EDITOR +#include "editor\editor.h" +#endif + +#define PARALLAX 0 // If !0, then special debugging for Parallax eyes enabled. + +// Length in segments of avoidance path +#define AVOID_SEG_LENGTH 7 + +#define PATH_VALIDATION 0 + +// LINT: Function prototypes +int validate_path(int debug_flag, point_seg* psegs, int num_points); +void validate_all_paths(void); +void ai_path_set_orient_and_vel(object *objp, vms_vector* goal_point, int player_visibility, vms_vector *vec_to_player); +void maybe_ai_path_garbage_collect(void); + +void ai_path_garbage_collect(void); + +// ------------------------------------------------------------------------ +void create_random_xlate(byte *xt) +{ + int i; + + for (i=0; i= 0) && (j < MAX_SIDES_PER_SEGMENT)); + + temp_byte = xt[j]; + xt[j] = xt[i]; + xt[i] = temp_byte; + } + +} + +// ----------------------------------------------------------------------------------------------------------- +// Insert the point at the center of the side connecting two segments between the two points. +// This is messy because we must insert into the list. The simplest (and not too slow) way to do this is to start +// at the end of the list and go backwards. +void insert_center_points(point_seg *psegs, int *num_points) +{ + int i, j, last_point; + int count=*num_points; + + last_point = *num_points-1; + + for (i=last_point; i>0; i--) { + int connect_side, temp_segnum; + vms_vector center_point, new_point; + + psegs[2*i] = psegs[i]; + connect_side = find_connect_side(&Segments[psegs[i].segnum], &Segments[psegs[i-1].segnum]); + Assert(connect_side != -1); // Impossible! These two segments must be connected, they were created by create_path_points (which was created by mk!) + if (connect_side == -1) // Try to blow past the assert, this should at least prevent a hang. + connect_side = 0; + compute_center_point_on_side(¢er_point, &Segments[psegs[i-1].segnum], connect_side); + vm_vec_sub(&new_point, &psegs[i-1].point, ¢er_point); + new_point.x /= 16; + new_point.y /= 16; + new_point.z /= 16; + vm_vec_sub(&psegs[2*i-1].point, ¢er_point, &new_point); + temp_segnum = find_point_seg(&psegs[2*i-1].point, psegs[2*i].segnum); + if (temp_segnum == -1) { + mprintf((1, "Warning: point not in ANY segment in aipath.c/insert_center_points.\n")); + psegs[2*i-1].point = center_point; + find_point_seg(&psegs[2*i-1].point, psegs[2*i].segnum); + } + + psegs[2*i-1].segnum = psegs[2*i].segnum; + count++; + } + + // Now, remove unnecessary center points. + // A center point is unnecessary if it is close to the line between the two adjacent points. + // MK, OPTIMIZE! Can get away with about half the math since every vector gets computed twice. + for (i=1; i fixmul(vm_vec_mag(&temp1), vm_vec_mag(&temp2))) + psegs[i].segnum = -1; + + } + + // Now, scan for points with segnum == -1 + j = 0; + for (i=0; i 3*F1_0/4 ) { + if (abs(a.z) < F1_0/2) { + if (rand_flag) { + e.x = (d_rand()-16384)/2; + e.y = (d_rand()-16384)/2; + e.z = abs(e.x) + abs(e.y) + 1; + vm_vec_normalize_quick(&e); + } else { + e.x = 0; + e.y = 0; + e.z = F1_0; + } + } else { + if (rand_flag) { + e.y = (d_rand()-16384)/2; + e.z = (d_rand()-16384)/2; + e.x = abs(e.y) + abs(e.z) + 1; + vm_vec_normalize_quick(&e); + } else { + e.x = F1_0; + e.y = 0; + e.z = 0; + } + } + } else { + vm_vec_cross(&d, &a, &b); + vm_vec_cross(&e, &c, &d); + vm_vec_normalize_quick(&e); + } + +if (vm_vec_mag_quick(&e) < F1_0/2) + Int3(); + +//mprintf((0, "(%i) Moving to side: %6.3f %6.3f %6.3f\n", i, f2fl(e.x), f2fl(e.y), f2fl(e.z))); + + segment_size = vm_vec_dist_quick(&Vertices[Segments[segnum].verts[0]], &Vertices[Segments[segnum].verts[6]]); + if (segment_size > F1_0*40) + segment_size = F1_0*40; + + vm_vec_scale_add(&goal_pos, &psegs[i].point, &e, segment_size/4); + + count = 3; + while (count) { + fvi_query fq; + fvi_info hit_data; + int hit_type; + + fq.p0 = &psegs[i].point; + fq.startseg = psegs[i].segnum; + fq.p1 = &goal_pos; + fq.rad = objp->size; + fq.thisobjnum = objp-Objects; + fq.ignore_obj_list = NULL; + fq.flags = 0; + + hit_type = find_vector_intersection(&fq, &hit_data); + + if (hit_type == HIT_NONE) + count = 0; + else { + if ((count == 3) && (hit_type == HIT_BAD_P0)) + Int3(); + goal_pos.x = (fq.p0->x + hit_data.hit_pnt.x)/2; + goal_pos.y = (fq.p0->y + hit_data.hit_pnt.y)/2; + goal_pos.z = (fq.p0->z + hit_data.hit_pnt.z)/2; + count--; + if (count == 0) { // Couldn't move towards outside, that's ok, sometimes things can't be moved. + goal_pos = psegs[i].point; + } + } + } + + // Only move towards outside if remained inside segment. + new_segnum = find_point_seg(&goal_pos, psegs[i].segnum); + if (new_segnum == psegs[i].segnum) { + new_psegs[i].point = goal_pos; + new_psegs[i].segnum = new_segnum; + } else { + new_psegs[i].point = psegs[i].point; + new_psegs[i].segnum = psegs[i].segnum; + } + + } + + for (i=1; i<*num_points-1; i++) + psegs[i] = new_psegs[i]; +} + + +// ----------------------------------------------------------------------------------------------------------- +// Create a path from objp->pos to the center of end_seg. +// Return a list of (segment_num, point_locations) at psegs +// Return number of points in *num_points. +// if max_depth == -1, then there is no maximum depth. +// If unable to create path, return -1, else return 0. +// If random_flag !0, then introduce randomness into path by looking at sides in random order. This means +// that a path between two segments won't always be the same, unless it is unique. +// If safety_flag is set, then additional points are added to "make sure" that points are reachable. I would +// like to say that it ensures that the object can move between the points, but that would require knowing what +// the object is (which isn't passed, right?) and making fvi calls (slow, right?). So, consider it the more_or_less_safe_flag. +// If end_seg == -2, then end seg will never be found and this routine will drop out due to depth (probably called by create_n_segment_path). +int create_path_points(object *objp, int start_seg, int end_seg, point_seg *psegs, short *num_points, int max_depth, int random_flag, int safety_flag, int avoid_seg) +{ + int cur_seg; + int sidenum; + int qtail = 0, qhead = 0; + int i; + byte visited[MAX_SEGMENTS]; + seg_seg seg_queue[MAX_SEGMENTS]; + short depth[MAX_SEGMENTS]; + int cur_depth; + byte random_xlate[MAX_SIDES_PER_SEGMENT]; + point_seg *original_psegs = psegs; + int l_num_points; + +// -- mprintf((0, "cpp: frame = %4i obj %3i, psegs = %5i\n", FrameCount, objp-Objects, psegs-Point_segs)); +#if PATH_VALIDATION + validate_all_paths(); +#endif + +if ((objp->type == OBJ_ROBOT) && (objp->ctype.ai_info.behavior == AIB_RUN_FROM)) { + random_flag = 1; + avoid_seg = ConsoleObject->segnum; + // Int3(); +} + + if (max_depth == -1) + max_depth = MAX_PATH_LENGTH; + + l_num_points = 0; +//random_flag = Random_flag_override; //!! debug!! +//safety_flag = Safety_flag_override; //!! debug!! + +// for (i=0; i<=Highest_segment_index; i++) { +// visited[i] = 0; +// depth[i] = 0; +// } + memset(visited, 0, sizeof(visited[0])*(Highest_segment_index+1)); + memset(depth, 0, sizeof(depth[0])*(Highest_segment_index+1)); + + // If there is a segment we're not allowed to visit, mark it. + if (avoid_seg != -1) { + Assert(avoid_seg <= Highest_segment_index); + if ((start_seg != avoid_seg) && (end_seg != avoid_seg)) { + visited[avoid_seg] = 1; + depth[avoid_seg] = 0; + } else + ; // -- mprintf((0, "Start/End/Avoid = %i %i %i\n", start_seg, end_seg, avoid_seg)); + } + + if (random_flag) + create_random_xlate(random_xlate); + + cur_seg = start_seg; + visited[cur_seg] = 1; + cur_depth = 0; + + while (cur_seg != end_seg) { + segment *segp = &Segments[cur_seg]; + + if (random_flag) + if (d_rand() < 8192) + create_random_xlate(random_xlate); + + // mprintf((0, "\n")); + for (sidenum = 0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++) { + + int snum = sidenum; + + if (random_flag) + snum = random_xlate[sidenum]; + + if (IS_CHILD(segp->children[snum]) && ((WALL_IS_DOORWAY(segp, snum) & WID_FLY_FLAG) || (ai_door_is_openable(objp, segp, snum)))) { + int this_seg = segp->children[snum]; + Assert(this_seg != -1); + if (((cur_seg == avoid_seg) || (this_seg == avoid_seg)) && (ConsoleObject->segnum == avoid_seg)) { + vms_vector center_point; + + fvi_query fq; + fvi_info hit_data; + int hit_type; + + compute_center_point_on_side(¢er_point, segp, snum); + + fq.p0 = &objp->pos; + fq.startseg = objp->segnum; + fq.p1 = ¢er_point; + fq.rad = objp->size; + fq.thisobjnum = objp-Objects; + fq.ignore_obj_list = NULL; + fq.flags = 0; + + hit_type = find_vector_intersection(&fq, &hit_data); + if (hit_type != HIT_NONE) { + // -- mprintf((0, "hit_type = %i, object = %i\n", hit_type, hit_data.hit_object)); + goto dont_add; + } + } + + if (!visited[this_seg]) { + seg_queue[qtail].start = cur_seg; + seg_queue[qtail].end = this_seg; + visited[this_seg] = 1; + depth[qtail++] = cur_depth+1; + if (depth[qtail-1] == max_depth) { + // mprintf((0, "\ndepth == max_depth == %i\n", max_depth)); + end_seg = seg_queue[qtail-1].end; + goto cpp_done1; + } // end if (depth[... + } // end if (!visited... + } // if (WALL_IS_DOORWAY(... +dont_add: ; + } // for (sidenum... + + if (qhead >= qtail) { + // Couldn't get to goal, return a path as far as we got, which probably acceptable to the unparticular caller. + end_seg = seg_queue[qtail-1].end; + break; + } + + cur_seg = seg_queue[qhead].end; + cur_depth = depth[qhead]; + qhead++; + +cpp_done1: ; + } // while (cur_seg ... + + // Set qtail to the segment which ends at the goal. + while (seg_queue[--qtail].end != end_seg) + if (qtail < 0) { + // mprintf((0, "\nNo path!\n")); + // printf("UNABLE TO FORM PATH"); + // Int3(); + *num_points = l_num_points; + return -1; + } + + #ifdef EDITOR + // -- N_selected_segs = 0; + #endif +//printf("Object #%3i, start: %3i ", objp-Objects, psegs-Point_segs); + while (qtail >= 0) { + int parent_seg, this_seg; + + this_seg = seg_queue[qtail].end; + parent_seg = seg_queue[qtail].start; + Assert((this_seg >= 0) && (this_seg <= Highest_segment_index)); + psegs->segnum = this_seg; +//printf("%3i ", this_seg); + compute_segment_center(&psegs->point,&Segments[this_seg]); + psegs++; + l_num_points++; + #ifdef EDITOR + // -- Selected_segs[N_selected_segs++] = this_seg; + #endif + + if (parent_seg == start_seg) + break; + + while (seg_queue[--qtail].end != parent_seg) + Assert(qtail >= 0); + } + + Assert((start_seg >= 0) && (start_seg <= Highest_segment_index)); + psegs->segnum = start_seg; +//printf("%3i\n", start_seg); + compute_segment_center(&psegs->point,&Segments[start_seg]); + psegs++; + l_num_points++; + +#if PATH_VALIDATION + validate_path(1, original_psegs, l_num_points); +#endif + + // Now, reverse point_segs in place. + for (i=0; i< l_num_points/2; i++) { + point_seg temp_point_seg = *(original_psegs + i); + *(original_psegs + i) = *(original_psegs + l_num_points - i - 1); + *(original_psegs + l_num_points - i - 1) = temp_point_seg; + } +#if PATH_VALIDATION + validate_path(2, original_psegs, l_num_points); +#endif + + // Now, if safety_flag set, then insert the point at the center of the side connecting two segments + // between the two points. This is messy because we must insert into the list. The simplest (and not too slow) + // way to do this is to start at the end of the list and go backwards. + if (safety_flag) { + if (psegs - Point_segs + l_num_points + 2 > MAX_POINT_SEGS) { + // Ouch! Cannot insert center points in path. So return unsafe path. +// Int3(); // Contact Mike: This is impossible. +// force_dump_ai_objects_all("Error in create_path_points"); + mprintf((0, "Resetting all paths because of safety_flag.\n")); + ai_reset_all_paths(); + *num_points = l_num_points; + return -1; + } else { + // int old_num_points = l_num_points; + insert_center_points(original_psegs, &l_num_points); + // mprintf((0, "Saved %i/%i points.\n", 2*old_num_points - l_num_points - 1, old_num_points-1)); + } + } + +#if PATH_VALIDATION + validate_path(3, original_psegs, l_num_points); +#endif + +// -- MK, 10/30/95 -- This code causes apparent discontinuities in the path, moving a point +// into a new segment. It is not necessarily bad, but it makes it hard to track down actual +// discontinuity problems. + if (objp->type == OBJ_ROBOT) + if (Robot_info[objp->id].companion) + move_towards_outside(original_psegs, &l_num_points, objp, 0); + +#if PATH_VALIDATION + validate_path(4, original_psegs, l_num_points); +#endif + + *num_points = l_num_points; + return 0; +} + +int Last_buddy_polish_path_frame; + +// ------------------------------------------------------------------------------------------------------- +// polish_path +// Takes an existing path and makes it nicer. +// Drops as many leading points as possible still maintaining direct accessibility +// from current position to first point. +// Will not shorten path to fewer than 3 points. +// Returns number of points. +// Starting position in psegs doesn't change. +// Changed, MK, 10/18/95. I think this was causing robots to get hung up on walls. +// Only drop up to the first three points. +int polish_path(object *objp, point_seg *psegs, int num_points) +{ + int i, first_point=0; + + if (num_points <= 4) + return num_points; + + // Prevent the buddy from polishing his path twice in one frame, which can cause him to get hung up. Pretty ugly, huh? + if (Robot_info[objp->id].companion) + { + if (FrameCount == Last_buddy_polish_path_frame) + return num_points; + else + Last_buddy_polish_path_frame = FrameCount; + } + + // -- MK: 10/18/95: for (i=0; ipos; + fq.startseg = objp->segnum; + fq.p1 = &psegs[i].point; + fq.rad = objp->size; + fq.thisobjnum = objp-Objects; + fq.ignore_obj_list = NULL; + fq.flags = 0; + + hit_type = find_vector_intersection(&fq, &hit_data); + + if (hit_type == HIT_NONE) + first_point = i+1; + else + break; + } + + if (first_point) { + // Scrunch down all the psegs. + for (i=first_point; isegnum; + if ((curseg < 0) || (curseg > Highest_segment_index)) { + mprintf((0, "Path beginning at index %i, length=%i is bogus!\n", psegs-Point_segs, num_points)); + Int3(); // Contact Mike: Debug trap for elusive, nasty bug. + return 0; + } + +if (debug_flag == 999) + mprintf((0, "That's curious...\n")); + +if (num_points == 0) + return 1; + +// printf("(%i) Validating path at psegs=%i, num_points=%i, segments = %3i ", debug_flag, psegs-Point_segs, num_points, psegs[0].segnum); + for (i=1; i Highest_segment_index)) { + mprintf((0, "Path beginning at index %i, length=%i is bogus!\n", psegs-Point_segs, num_points)); + Int3(); // Contact Mike: Debug trap for elusive, nasty bug. + return 0; + } + +// printf("%3i ", nextseg); + if (curseg != nextseg) { + for (sidenum=0; sidenumctype.ai_info; + //ai_local *ailp = &Ai_local_info[i]; + + if (objp->control_type == CT_AI) { + if ((aip->hide_index != -1) && (aip->path_length > 0)) + if (!validate_path(4, &Point_segs[aip->hide_index], aip->path_length)) { + Int3(); // This path is bogus! Who corrupted it! Danger! Danger! + // Contact Mike, he caused this mess. + //force_dump_ai_objects_all("Error in validate_all_paths"); + aip->path_length=0; // This allows people to resume without harm... + } + } + } + } +#endif + +} +#endif + +// -- // ------------------------------------------------------------------------------------------------------- +// -- // Creates a path from the objects current segment (objp->segnum) to the specified segment for the object to +// -- // hide in Ai_local_info[objnum].goal_segment. +// -- // Sets objp->ctype.ai_info.hide_index, a pointer into Point_segs, the first point_seg of the path. +// -- // objp->ctype.ai_info.path_length, length of path +// -- // Point_segs_free_ptr global pointer into Point_segs array +// -- void create_path(object *objp) +// -- { +// -- ai_static *aip = &objp->ctype.ai_info; +// -- ai_local *ailp = &Ai_local_info[objp-Objects]; +// -- int start_seg, end_seg; +// -- +// -- start_seg = objp->segnum; +// -- end_seg = ailp->goal_segment; +// -- +// -- if (end_seg == -1) +// -- create_n_segment_path(objp, 3, -1); +// -- +// -- if (end_seg == -1) { +// -- ; //mprintf((0, "Object %i, hide_segment = -1, not creating path.\n", objp-Objects)); +// -- } else { +// -- create_path_points(objp, start_seg, end_seg, Point_segs_free_ptr, &aip->path_length, -1, 0, 0, -1); +// -- aip->hide_index = Point_segs_free_ptr - Point_segs; +// -- aip->cur_path_index = 0; +// -- #if PATH_VALIDATION +// -- validate_path(5, Point_segs_free_ptr, aip->path_length); +// -- #endif +// -- Point_segs_free_ptr += aip->path_length; +// -- if (Point_segs_free_ptr - Point_segs + MAX_PATH_LENGTH*2 > MAX_POINT_SEGS) { +// -- //Int3(); // Contact Mike: This is curious, though not deadly. /eip++;g +// -- //force_dump_ai_objects_all("Error in create_path"); +// -- ai_reset_all_paths(); +// -- } +// -- aip->PATH_DIR = 1; // Initialize to moving forward. +// -- aip->SUBMODE = AISM_HIDING; // Pretend we are hiding, so we sit here until bothered. +// -- } +// -- +// -- maybe_ai_path_garbage_collect(); +// -- +// -- } + +// ------------------------------------------------------------------------------------------------------- +// Creates a path from the objects current segment (objp->segnum) to the specified segment for the object to +// hide in Ai_local_info[objnum].goal_segment. +// Sets objp->ctype.ai_info.hide_index, a pointer into Point_segs, the first point_seg of the path. +// objp->ctype.ai_info.path_length, length of path +// Point_segs_free_ptr global pointer into Point_segs array +// Change, 10/07/95: Used to create path to ConsoleObject->pos. Now creates path to Believed_player_pos. +void create_path_to_player(object *objp, int max_length, int safety_flag) +{ + ai_static *aip = &objp->ctype.ai_info; + ai_local *ailp = &Ai_local_info[objp-Objects]; + int start_seg, end_seg; + +//mprintf((0, "Creating path to player.\n")); + if (max_length == -1) + max_length = MAX_DEPTH_TO_SEARCH_FOR_PLAYER; + + ailp->time_player_seen = GameTime; // Prevent from resetting path quickly. + ailp->goal_segment = Believed_player_seg; + + start_seg = objp->segnum; + end_seg = ailp->goal_segment; + + // mprintf((0, "Creating path for object #%i, from segment #%i to #%i\n", objp-Objects, start_seg, end_seg)); + + if (end_seg == -1) { + ; //mprintf((0, "Object %i, hide_segment = -1, not creating path.\n", objp-Objects)); + } else { + create_path_points(objp, start_seg, end_seg, Point_segs_free_ptr, &aip->path_length, max_length, 1, safety_flag, -1); + aip->path_length = polish_path(objp, Point_segs_free_ptr, aip->path_length); + aip->hide_index = Point_segs_free_ptr - Point_segs; + aip->cur_path_index = 0; + Point_segs_free_ptr += aip->path_length; + if (Point_segs_free_ptr - Point_segs + MAX_PATH_LENGTH*2 > MAX_POINT_SEGS) { + //Int3(); // Contact Mike: This is stupid. Should call maybe_ai_garbage_collect before the add. + //force_dump_ai_objects_all("Error in create_path_to_player"); + ai_reset_all_paths(); + return; + } +// Assert(Point_segs_free_ptr - Point_segs + MAX_PATH_LENGTH*2 < MAX_POINT_SEGS); + aip->PATH_DIR = 1; // Initialize to moving forward. + // -- UNUSED! aip->SUBMODE = AISM_GOHIDE; // This forces immediate movement. + ailp->mode = AIM_FOLLOW_PATH; + ailp->player_awareness_type = 0; // If robot too aware of player, will set mode to chase + // mprintf((0, "Created %i segment path to player.\n", aip->path_length)); + } + + maybe_ai_path_garbage_collect(); + +} + +// ------------------------------------------------------------------------------------------------------- +// Creates a path from the object's current segment (objp->segnum) to segment goalseg. +void create_path_to_segment(object *objp, int goalseg, int max_length, int safety_flag) +{ + ai_static *aip = &objp->ctype.ai_info; + ai_local *ailp = &Ai_local_info[objp-Objects]; + int start_seg, end_seg; + + if (max_length == -1) + max_length = MAX_DEPTH_TO_SEARCH_FOR_PLAYER; + + ailp->time_player_seen = GameTime; // Prevent from resetting path quickly. + ailp->goal_segment = goalseg; + + start_seg = objp->segnum; + end_seg = ailp->goal_segment; + + if (end_seg == -1) { + ; + } else { + create_path_points(objp, start_seg, end_seg, Point_segs_free_ptr, &aip->path_length, max_length, 1, safety_flag, -1); + aip->hide_index = Point_segs_free_ptr - Point_segs; + aip->cur_path_index = 0; + Point_segs_free_ptr += aip->path_length; + if (Point_segs_free_ptr - Point_segs + MAX_PATH_LENGTH*2 > MAX_POINT_SEGS) { + ai_reset_all_paths(); + return; + } + + aip->PATH_DIR = 1; // Initialize to moving forward. + // -- UNUSED! aip->SUBMODE = AISM_GOHIDE; // This forces immediate movement. + ailp->player_awareness_type = 0; // If robot too aware of player, will set mode to chase + } + + maybe_ai_path_garbage_collect(); + +} + +// ------------------------------------------------------------------------------------------------------- +// Creates a path from the objects current segment (objp->segnum) to the specified segment for the object to +// hide in Ai_local_info[objnum].goal_segment +// Sets objp->ctype.ai_info.hide_index, a pointer into Point_segs, the first point_seg of the path. +// objp->ctype.ai_info.path_length, length of path +// Point_segs_free_ptr global pointer into Point_segs array +void create_path_to_station(object *objp, int max_length) +{ + ai_static *aip = &objp->ctype.ai_info; + ai_local *ailp = &Ai_local_info[objp-Objects]; + int start_seg, end_seg; + + if (max_length == -1) + max_length = MAX_DEPTH_TO_SEARCH_FOR_PLAYER; + + ailp->time_player_seen = GameTime; // Prevent from resetting path quickly. + + start_seg = objp->segnum; + end_seg = aip->hide_segment; + + //1001: mprintf((0, "Back to station for object #%i, from segment #%i to #%i\n", objp-Objects, start_seg, end_seg)); + + if (end_seg == -1) { + ; //mprintf((0, "Object %i, hide_segment = -1, not creating path.\n", objp-Objects)); + } else { + create_path_points(objp, start_seg, end_seg, Point_segs_free_ptr, &aip->path_length, max_length, 1, 1, -1); + aip->path_length = polish_path(objp, Point_segs_free_ptr, aip->path_length); + aip->hide_index = Point_segs_free_ptr - Point_segs; + aip->cur_path_index = 0; + + Point_segs_free_ptr += aip->path_length; + if (Point_segs_free_ptr - Point_segs + MAX_PATH_LENGTH*2 > MAX_POINT_SEGS) { + //Int3(); // Contact Mike: Stupid. + //force_dump_ai_objects_all("Error in create_path_to_station"); + ai_reset_all_paths(); + return; + } +// Assert(Point_segs_free_ptr - Point_segs + MAX_PATH_LENGTH*2 < MAX_POINT_SEGS); + aip->PATH_DIR = 1; // Initialize to moving forward. + // aip->SUBMODE = AISM_GOHIDE; // This forces immediate movement. + ailp->mode = AIM_FOLLOW_PATH; + ailp->player_awareness_type = 0; + } + + + maybe_ai_path_garbage_collect(); + +} + + +// ------------------------------------------------------------------------------------------------------- +// Create a path of length path_length for an object, stuffing info in ai_info field. +void create_n_segment_path(object *objp, int path_length, int avoid_seg) +{ + ai_static *aip=&objp->ctype.ai_info; + ai_local *ailp = &Ai_local_info[objp-Objects]; + +//mprintf((0, "Creating %i segment path.\n", path_length)); + + if (create_path_points(objp, objp->segnum, -2, Point_segs_free_ptr, &aip->path_length, path_length, 1, 0, avoid_seg) == -1) { + Point_segs_free_ptr += aip->path_length; + while ((create_path_points(objp, objp->segnum, -2, Point_segs_free_ptr, &aip->path_length, --path_length, 1, 0, -1) == -1)) { + //mprintf((0, "R")); + Assert(path_length); + } + } + + aip->hide_index = Point_segs_free_ptr - Point_segs; + aip->cur_path_index = 0; +#if PATH_VALIDATION + validate_path(8, Point_segs_free_ptr, aip->path_length); +#endif + Point_segs_free_ptr += aip->path_length; + if (Point_segs_free_ptr - Point_segs + MAX_PATH_LENGTH*2 > MAX_POINT_SEGS) { + //Int3(); // Contact Mike: This is curious, though not deadly. /eip++;g + //force_dump_ai_objects_all("Error in crete_n_segment_path 2"); + ai_reset_all_paths(); + } + + aip->PATH_DIR = 1; // Initialize to moving forward. + // -- UNUSED! aip->SUBMODE = -1; // Don't know what this means. + ailp->mode = AIM_FOLLOW_PATH; + + // If this robot is visible (player_visibility is not available) and it's running away, move towards outside with + // randomness to prevent a stream of bots from going away down the center of a corridor. + if (Ai_local_info[objp-Objects].previous_visibility) { + if (aip->path_length) { + int t_num_points = aip->path_length; + move_towards_outside(&Point_segs[aip->hide_index], &t_num_points, objp, 1); + aip->path_length = t_num_points; + } + } + //mprintf((0, "\n")); + + maybe_ai_path_garbage_collect(); + +} + +// ------------------------------------------------------------------------------------------------------- +void create_n_segment_path_to_door(object *objp, int path_length, int avoid_seg) +{ + create_n_segment_path(objp, path_length, avoid_seg); +} + +extern int Connected_segment_distance; + +#define Int3_if(cond) if (!cond) Int3(); + +// ---------------------------------------------------------------------------------------------------- +void move_object_to_goal(object *objp, vms_vector *goal_point, int goal_seg) +{ + ai_static *aip = &objp->ctype.ai_info; + int segnum; + + if (aip->path_length < 2) + return; + + Assert(objp->segnum != -1); + + // mprintf((0, "[%i -> %i]\n", objp-Objects, goal_seg)); + +#ifndef NDEBUG + if (objp->segnum != goal_seg) + if (find_connect_side(&Segments[objp->segnum], &Segments[goal_seg]) == -1) { + fix dist; + dist = find_connected_distance(&objp->pos, objp->segnum, goal_point, goal_seg, 30, WID_FLY_FLAG); + if (Connected_segment_distance > 2) { // This global is set in find_connected_distance + // -- Int3(); + mprintf((1, "Warning: Object %i hopped across %i segments, a distance of %7.3f.\n", objp-Objects, Connected_segment_distance, f2fl(dist))); + } + } +#endif + + Assert(aip->path_length >= 2); + + if (aip->cur_path_index <= 0) { + if (aip->behavior == AIB_STATION) { + // mprintf((0, "Object #%i, creating path back to station.\n", objp-Objects)); + create_path_to_station(objp, 15); + return; + } + aip->cur_path_index = 1; + aip->PATH_DIR = 1; + } else if (aip->cur_path_index >= aip->path_length - 1) { + if (aip->behavior == AIB_STATION) { + // mprintf((0, "Object #%i, creating path back to station.\n", objp-Objects)); + create_path_to_station(objp, 15); + if (aip->path_length == 0) { + ai_local *ailp = &Ai_local_info[objp-Objects]; + ailp->mode = AIM_STILL; + } + return; + } + Assert(aip->path_length != 0); + aip->cur_path_index = aip->path_length-2; + aip->PATH_DIR = -1; + } else + aip->cur_path_index += aip->PATH_DIR; + + //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); + + objp->pos = *goal_point; + segnum = find_object_seg(objp); + if (segnum != goal_seg) + mprintf((1, "Object #%i goal supposed to be in segment #%i, but in segment #%i\n", objp-Objects, goal_seg, segnum)); + + if (segnum == -1) { + Int3(); // Oops, object is not in any segment. + // Contact Mike: This is impossible. + // Hack, move object to center of segment it used to be in. + compute_segment_center(&objp->pos, &Segments[objp->segnum]); + } else + obj_relink(objp-Objects, segnum); +} + +// -- too much work -- // ---------------------------------------------------------------------------------------------------------- +// -- too much work -- // Return true if the object the companion wants to kill is reachable. +// -- too much work -- int attack_kill_object(object *objp) +// -- too much work -- { +// -- too much work -- object *kill_objp; +// -- too much work -- fvi_info hit_data; +// -- too much work -- int fate; +// -- too much work -- fvi_query fq; +// -- too much work -- +// -- too much work -- if (Escort_kill_object == -1) +// -- too much work -- return 0; +// -- too much work -- +// -- too much work -- kill_objp = &Objects[Escort_kill_object]; +// -- too much work -- +// -- too much work -- fq.p0 = &objp->pos; +// -- too much work -- fq.startseg = objp->segnum; +// -- too much work -- fq.p1 = &kill_objp->pos; +// -- too much work -- fq.rad = objp->size; +// -- too much work -- fq.thisobjnum = objp-Objects; +// -- too much work -- fq.ignore_obj_list = NULL; +// -- too much work -- fq.flags = 0; +// -- too much work -- +// -- too much work -- fate = find_vector_intersection(&fq,&hit_data); +// -- too much work -- +// -- too much work -- if (fate == HIT_NONE) +// -- too much work -- return 1; +// -- too much work -- else +// -- too much work -- return 0; +// -- too much work -- } + +// ---------------------------------------------------------------------------------------------------------- +// Optimization: If current velocity will take robot near goal, don't change velocity +void ai_follow_path(object *objp, int player_visibility, int previous_visibility, vms_vector *vec_to_player) +{ + ai_static *aip = &objp->ctype.ai_info; + + vms_vector goal_point, new_goal_point; + fix dist_to_goal; + robot_info *robptr = &Robot_info[objp->id]; + int forced_break, original_dir, original_index; + fix dist_to_player; + int goal_seg; + ai_local *ailp = &Ai_local_info[objp-Objects]; + fix threshold_distance; + + +// mprintf((0, "Obj %i, dist=%6.1f index=%i len=%i seg=%i pos = %6.1f %6.1f %6.1f.\n", objp-Objects, f2fl(vm_vec_dist_quick(&objp->pos, &ConsoleObject->pos)), aip->cur_path_index, aip->path_length, objp->segnum, f2fl(objp->pos.x), f2fl(objp->pos.y), f2 + + if ((aip->hide_index == -1) || (aip->path_length == 0)) + { + if (ailp->mode == AIM_RUN_FROM_OBJECT) { + create_n_segment_path(objp, 5, -1); + //--Int3_if((aip->path_length != 0)); + ailp->mode = AIM_RUN_FROM_OBJECT; + } else { + // -- mprintf((0, "Object %i creating path for no apparent reason.\n", objp-Objects)); + create_n_segment_path(objp, 5, -1); + //--Int3_if((aip->path_length != 0)); + } + } + + if ((aip->hide_index + aip->path_length > Point_segs_free_ptr - Point_segs) && (aip->path_length>0)) { + Int3(); // Contact Mike: Bad. Path goes into what is believed to be free space. + // This is debugging code. Figure out why garbage collection + // didn't compress this object's path information. + ai_path_garbage_collect(); + //force_dump_ai_objects_all("Error in ai_follow_path"); + ai_reset_all_paths(); + } + + if (aip->path_length < 2) { + if ((aip->behavior == AIB_SNIPE) || (ailp->mode == AIM_RUN_FROM_OBJECT)) { + if (ConsoleObject->segnum == objp->segnum) { + create_n_segment_path(objp, AVOID_SEG_LENGTH, -1); // Can't avoid segment player is in, robot is already in it! (That's what the -1 is for) + //--Int3_if((aip->path_length != 0)); + } else { + create_n_segment_path(objp, AVOID_SEG_LENGTH, ConsoleObject->segnum); + //--Int3_if((aip->path_length != 0)); + } + if (aip->behavior == AIB_SNIPE) { + if (robptr->thief) + ailp->mode = AIM_THIEF_ATTACK; // It gets bashed in create_n_segment_path + else + ailp->mode = AIM_SNIPE_FIRE; // It gets bashed in create_n_segment_path + } else { + ailp->mode = AIM_RUN_FROM_OBJECT; // It gets bashed in create_n_segment_path + } + } else if (robptr->companion == 0) { + ailp->mode = AIM_STILL; + aip->path_length = 0; + return; + } + } + + //--Int3_if(((aip->PATH_DIR == -1) || (aip->PATH_DIR == 1))); + //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); + + goal_point = Point_segs[aip->hide_index + aip->cur_path_index].point; + goal_seg = Point_segs[aip->hide_index + aip->cur_path_index].segnum; + dist_to_goal = vm_vec_dist_quick(&goal_point, &objp->pos); + + if (Player_is_dead) + dist_to_player = vm_vec_dist_quick(&objp->pos, &Viewer->pos); + else + dist_to_player = vm_vec_dist_quick(&objp->pos, &ConsoleObject->pos); + + // Efficiency hack: If far away from player, move in big quantized jumps. + if (!(player_visibility || previous_visibility) && (dist_to_player > F1_0*200) && !(Game_mode & GM_MULTI)) { + if (dist_to_goal < F1_0*2) { + move_object_to_goal(objp, &goal_point, goal_seg); + return; + } else { + robot_info *robptr = &Robot_info[objp->id]; + fix cur_speed = robptr->max_speed[Difficulty_level]/2; + fix distance_travellable = fixmul(FrameTime, cur_speed); + + // int connect_side = find_connect_side(objp->segnum, goal_seg); + // Only move to goal if allowed to fly through the side. + // Buddy-bot can create paths he can't fly, waiting for player. + // -- bah, this isn't good enough, buddy will fail to get through any door! if (WALL_IS_DOORWAY(&Segments]objp->segnum], connect_side) & WID_FLY_FLAG) { + if (!Robot_info[objp->id].companion && !Robot_info[objp->id].thief) { + if (distance_travellable >= dist_to_goal) { + move_object_to_goal(objp, &goal_point, goal_seg); + } else { + fix prob = fixdiv(distance_travellable, dist_to_goal); + + int rand_num = d_rand(); + if ( (rand_num >> 1) < prob) { + move_object_to_goal(objp, &goal_point, goal_seg); + } + } + return; + } + } + + } + + // If running from player, only run until can't be seen. + if (ailp->mode == AIM_RUN_FROM_OBJECT) { + if ((player_visibility == 0) && (ailp->player_awareness_type == 0)) { + fix vel_scale; + + vel_scale = F1_0 - FrameTime/2; + if (vel_scale < F1_0/2) + vel_scale = F1_0/2; + + vm_vec_scale(&objp->mtype.phys_info.velocity, vel_scale); + + return; + } else if (!(FrameCount ^ ((objp-Objects) & 0x07))) { // Done 1/8 frames. + // If player on path (beyond point robot is now at), then create a new path. + point_seg *curpsp = &Point_segs[aip->hide_index]; + int player_segnum = ConsoleObject->segnum; + int i; + + // This is probably being done every frame, which is wasteful. + for (i=aip->cur_path_index; ipath_length; i++) { + if (curpsp[i].segnum == player_segnum) { + if (player_segnum != objp->segnum) { + create_n_segment_path(objp, AVOID_SEG_LENGTH, player_segnum); + } else { + create_n_segment_path(objp, AVOID_SEG_LENGTH, -1); + } + Assert(aip->path_length != 0); + ailp->mode = AIM_RUN_FROM_OBJECT; // It gets bashed in create_n_segment_path + break; + } + } + if (player_visibility) { + ailp->player_awareness_type = 1; + ailp->player_awareness_time = F1_0; + } + } + } + + //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); + + if (aip->cur_path_index < 0) { + aip->cur_path_index = 0; + } else if (aip->cur_path_index >= aip->path_length) { + if (ailp->mode == AIM_RUN_FROM_OBJECT) { + create_n_segment_path(objp, AVOID_SEG_LENGTH, ConsoleObject->segnum); + ailp->mode = AIM_RUN_FROM_OBJECT; // It gets bashed in create_n_segment_path + Assert(aip->path_length != 0); + } else { + aip->cur_path_index = aip->path_length-1; + } + } + + goal_point = Point_segs[aip->hide_index + aip->cur_path_index].point; + + // If near goal, pick another goal point. + forced_break = 0; // Gets set for short paths. + original_dir = aip->PATH_DIR; + original_index = aip->cur_path_index; + threshold_distance = fixmul(vm_vec_mag_quick(&objp->mtype.phys_info.velocity), FrameTime)*2 + F1_0*2; + + new_goal_point = Point_segs[aip->hide_index + aip->cur_path_index].point; + + //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); + + while ((dist_to_goal < threshold_distance) && !forced_break) { + + // Advance to next point on path. + aip->cur_path_index += aip->PATH_DIR; + + // See if next point wraps past end of path (in either direction), and if so, deal with it based on mode. + if ((aip->cur_path_index >= aip->path_length) || (aip->cur_path_index < 0)) { + + //mprintf((0, "Object %i reached end of the line!\n", objp-Objects)); + // If mode = hiding, then stay here until get bonked or hit by player. + // -- if (ailp->mode == AIM_BEHIND) { + // -- ailp->mode = AIM_STILL; + // -- return; // Stay here until bonked or hit by player. + // -- } else + + // Buddy bot. If he's in mode to get away from player and at end of line, + // if player visible, then make a new path, else just return. + if (robptr->companion) { + if (Escort_special_goal == ESCORT_GOAL_SCRAM) + { + if (player_visibility) { + create_n_segment_path(objp, 16 + d_rand() * 16, -1); + aip->path_length = polish_path(objp, &Point_segs[aip->hide_index], aip->path_length); + Assert(aip->path_length != 0); + // -- mprintf((0, "Buddy: Creating new path!\n")); + ailp->mode = AIM_WANDER; // Special buddy mode. + //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); + return; + } else { + ailp->mode = AIM_WANDER; // Special buddy mode. + vm_vec_zero(&objp->mtype.phys_info.velocity); + vm_vec_zero(&objp->mtype.phys_info.rotvel); + // -- mprintf((0, "Buddy: I'm hidden!\n")); + //!!Assert((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length)); + return; + } + } + } + + if (aip->behavior == AIB_FOLLOW) { + // mprintf((0, "AIB_FOLLOW: Making new path.\n")); + create_n_segment_path(objp, 10, ConsoleObject->segnum); + //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); + } else if (aip->behavior == AIB_STATION) { + // mprintf((0, "Object %i reached end of line, creating path back to station.\n", objp-Objects)); + create_path_to_station(objp, 15); + if ((aip->hide_segment != Point_segs[aip->hide_index+aip->path_length-1].segnum) || (aip->path_length == 0)) { + ailp->mode = AIM_STILL; + } else { + //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); + } + return; + } else if (ailp->mode == AIM_FOLLOW_PATH) { + create_path_to_player(objp, 10, 1); + if (aip->hide_segment != Point_segs[aip->hide_index+aip->path_length-1].segnum) { + ailp->mode = AIM_STILL; + return; + } else { + //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); + } + } else if (ailp->mode == AIM_RUN_FROM_OBJECT) { + create_n_segment_path(objp, AVOID_SEG_LENGTH, ConsoleObject->segnum); + ailp->mode = AIM_RUN_FROM_OBJECT; // It gets bashed in create_n_segment_path + if (aip->path_length < 1) { + create_n_segment_path(objp, AVOID_SEG_LENGTH, ConsoleObject->segnum); + ailp->mode = AIM_RUN_FROM_OBJECT; // It gets bashed in create_n_segment_path + if (aip->path_length < 1) { + aip->behavior = AIB_NORMAL; + ailp->mode = AIM_STILL; + return; + } + } + //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); + } else { + // Reached end of the line. First see if opposite end point is reachable, and if so, go there. + // If not, turn around. + int opposite_end_index; + vms_vector *opposite_end_point; + fvi_info hit_data; + int fate; + fvi_query fq; + + // See which end we're nearer and look at the opposite end point. + if (abs(aip->cur_path_index - aip->path_length) < aip->cur_path_index) { + // Nearer to far end (ie, index not 0), so try to reach 0. + opposite_end_index = 0; + } else { + // Nearer to 0 end, so try to reach far end. + opposite_end_index = aip->path_length-1; + } + + //--Int3_if(((opposite_end_index >= 0) && (opposite_end_index < aip->path_length))); + + opposite_end_point = &Point_segs[aip->hide_index + opposite_end_index].point; + + fq.p0 = &objp->pos; + fq.startseg = objp->segnum; + fq.p1 = opposite_end_point; + fq.rad = objp->size; + fq.thisobjnum = objp-Objects; + fq.ignore_obj_list = NULL; + fq.flags = 0; //what about trans walls??? + + fate = find_vector_intersection(&fq,&hit_data); + + if (fate != HIT_WALL) { + // We can be circular! Do it! + // Path direction is unchanged. + aip->cur_path_index = opposite_end_index; + } else { + aip->PATH_DIR = -aip->PATH_DIR; + aip->cur_path_index += aip->PATH_DIR; + } + //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); + } + break; + } else { + new_goal_point = Point_segs[aip->hide_index + aip->cur_path_index].point; + goal_point = new_goal_point; + dist_to_goal = vm_vec_dist_quick(&goal_point, &objp->pos); + //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); + } + + // If went all the way around to original point, in same direction, then get out of here! + if ((aip->cur_path_index == original_index) && (aip->PATH_DIR == original_dir)) { + create_path_to_player(objp, 3, 1); + //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); + forced_break = 1; + } + //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); + } // end while + + // Set velocity (objp->mtype.phys_info.velocity) and orientation (objp->orient) for this object. + //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); + ai_path_set_orient_and_vel(objp, &goal_point, player_visibility, vec_to_player); + //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); + +} + +typedef struct { + short path_start, objnum; +} obj_path; + +int path_index_compare(obj_path *i1, obj_path *i2) +{ + if (i1->path_start < i2->path_start) + return -1; + else if (i1->path_start == i2->path_start) + return 0; + else + return 1; +} + +// ---------------------------------------------------------------------------------------------------------- +// Set orientation matrix and velocity for objp based on its desire to get to a point. +void ai_path_set_orient_and_vel(object *objp, vms_vector *goal_point, int player_visibility, vms_vector *vec_to_player) +{ + vms_vector cur_vel = objp->mtype.phys_info.velocity; + vms_vector norm_cur_vel; + vms_vector norm_vec_to_goal; + vms_vector cur_pos = objp->pos; + vms_vector norm_fvec; + fix speed_scale; + fix dot; + robot_info *robptr = &Robot_info[objp->id]; + fix max_speed; + + // If evading player, use highest difficulty level speed, plus something based on diff level + max_speed = robptr->max_speed[Difficulty_level]; + if ((Ai_local_info[objp-Objects].mode == AIM_RUN_FROM_OBJECT) || (objp->ctype.ai_info.behavior == AIB_SNIPE)) + max_speed = max_speed*3/2; + + vm_vec_sub(&norm_vec_to_goal, goal_point, &cur_pos); + vm_vec_normalize_quick(&norm_vec_to_goal); + + norm_cur_vel = cur_vel; + vm_vec_normalize_quick(&norm_cur_vel); + + norm_fvec = objp->orient.fvec; + vm_vec_normalize_quick(&norm_fvec); + + dot = vm_vec_dot(&norm_vec_to_goal, &norm_fvec); + + // If very close to facing opposite desired vector, perturb vector + if (dot < -15*F1_0/16) { + //mprintf((0, "Facing away from goal, abruptly turning\n")); + norm_cur_vel = norm_vec_to_goal; + } else { + norm_cur_vel.x += norm_vec_to_goal.x/2; + norm_cur_vel.y += norm_vec_to_goal.y/2; + norm_cur_vel.z += norm_vec_to_goal.z/2; + } + + vm_vec_normalize_quick(&norm_cur_vel); + + // Set speed based on this robot type's maximum allowed speed and how hard it is turning. + // How hard it is turning is based on the dot product of (vector to goal) and (current velocity vector) + // Note that since 3*F1_0/4 is added to dot product, it is possible for the robot to back up. + + // Set speed and orientation. + if (dot < 0) + dot /= -4; + + // If in snipe mode, can move fast even if not facing that direction. + if (objp->ctype.ai_info.behavior == AIB_SNIPE) + if (dot < F1_0/2) + dot = (dot + F1_0)/2; + + speed_scale = fixmul(max_speed, dot); + vm_vec_scale(&norm_cur_vel, speed_scale); + objp->mtype.phys_info.velocity = norm_cur_vel; + + if ((Ai_local_info[objp-Objects].mode == AIM_RUN_FROM_OBJECT) || (robptr->companion == 1) || (objp->ctype.ai_info.behavior == AIB_SNIPE)) { + if (Ai_local_info[objp-Objects].mode == AIM_SNIPE_RETREAT_BACKWARDS) { + if ((player_visibility) && (vec_to_player != NULL)) + norm_vec_to_goal = *vec_to_player; + else + vm_vec_negate(&norm_vec_to_goal); + } + ai_turn_towards_vector(&norm_vec_to_goal, objp, robptr->turn_time[NDL-1]/2); + } else + ai_turn_towards_vector(&norm_vec_to_goal, objp, robptr->turn_time[Difficulty_level]); + +} + +int Last_frame_garbage_collected = 0; + +// ---------------------------------------------------------------------------------------------------------- +// Garbage colledion -- Free all unused records in Point_segs and compress all paths. +void ai_path_garbage_collect(void) +{ + int free_path_index = 0; + int num_path_objects = 0; + int objnum; + int objind; + obj_path object_list[MAX_OBJECTS]; + +#ifndef NDEBUG + force_dump_ai_objects_all("***** Start ai_path_garbage_collect *****"); +#endif + + // -- mprintf((0, "Garbage collection frame %i, last frame %i! Old free index = %i ", FrameCount, Last_frame_garbage_collected, Point_segs_free_ptr - Point_segs)); + + Last_frame_garbage_collected = FrameCount; + +#if PATH_VALIDATION + validate_all_paths(); +#endif + // Create a list of objects which have paths of length 1 or more. + for (objnum=0; objnum <= Highest_object_index; objnum++) { + object *objp = &Objects[objnum]; + + if ((objp->type == OBJ_ROBOT) && ((objp->control_type == CT_AI) || (objp->control_type == CT_MORPH))) { + ai_static *aip = &objp->ctype.ai_info; + + if (aip->path_length) { + object_list[num_path_objects].path_start = aip->hide_index; + object_list[num_path_objects++].objnum = objnum; + } + } + } + + qsort(object_list, num_path_objects, sizeof(object_list[0]), + (int (*)(void const *,void const *))path_index_compare); + + for (objind=0; objind < num_path_objects; objind++) { + object *objp; + ai_static *aip; + int i; + int old_index; + + objnum = object_list[objind].objnum; + objp = &Objects[objnum]; + aip = &objp->ctype.ai_info; + old_index = aip->hide_index; + + aip->hide_index = free_path_index; + for (i=0; ipath_length; i++) + Point_segs[free_path_index++] = Point_segs[old_index++]; + } + + Point_segs_free_ptr = &Point_segs[free_path_index]; + + // mprintf((0, "new = %i\n", free_path_index)); +//printf("After garbage collection, free index = %i\n", Point_segs_free_ptr - Point_segs); +#ifndef NDEBUG + { + int i; + + force_dump_ai_objects_all("***** Finish ai_path_garbage_collect *****"); + + for (i=0; i<=Highest_object_index; i++) { + ai_static *aip = &Objects[i].ctype.ai_info; + + if ((Objects[i].type == OBJ_ROBOT) && (Objects[i].control_type == CT_AI)) + if ((aip->hide_index + aip->path_length > Point_segs_free_ptr - Point_segs) && (aip->path_length>0)) + Int3(); // Contact Mike: Debug trap for nasty, elusive bug. + } + + validate_all_paths(); + } +#endif + +} + +// ----------------------------------------------------------------------------- +// Do garbage collection if not been done for awhile, or things getting really critical. +void maybe_ai_path_garbage_collect(void) +{ + if (Point_segs_free_ptr - Point_segs > MAX_POINT_SEGS - MAX_PATH_LENGTH) { + if (Last_frame_garbage_collected+1 >= FrameCount) { + // This is kind of bad. Garbage collected last frame or this frame. + // Just destroy all paths. Too bad for the robots. They are memory wasteful. + ai_reset_all_paths(); + mprintf((1, "Warning: Resetting all paths. Point_segs buffer nearly exhausted.\n")); + } else { + // We are really close to full, but didn't just garbage collect, so maybe this is recoverable. + mprintf((1, "Warning: Almost full garbage collection being performed: ")); + ai_path_garbage_collect(); + mprintf((1, "Free records = %i/%i\n", MAX_POINT_SEGS - (Point_segs_free_ptr - Point_segs), MAX_POINT_SEGS)); + } + } else if (Point_segs_free_ptr - Point_segs > 3*MAX_POINT_SEGS/4) { + if (Last_frame_garbage_collected + 16 < FrameCount) { + ai_path_garbage_collect(); + } + } else if (Point_segs_free_ptr - Point_segs > MAX_POINT_SEGS/2) { + if (Last_frame_garbage_collected + 256 < FrameCount) { + ai_path_garbage_collect(); + } + } +} + +// ----------------------------------------------------------------------------- +// Reset all paths. Do garbage collection. +// Should be called at the start of each level. +void ai_reset_all_paths(void) +{ + int i; + + for (i=0; i<=Highest_object_index; i++) + if (Objects[i].control_type == CT_AI) { + Objects[i].ctype.ai_info.hide_index = -1; + Objects[i].ctype.ai_info.path_length = 0; + } + + ai_path_garbage_collect(); + +} + +// --------------------------------------------------------------------------------------------------------- +// Probably called because a robot bashed a wall, getting a bunch of retries. +// Try to resume path. +void attempt_to_resume_path(object *objp) +{ + //int objnum = objp-Objects; + ai_static *aip = &objp->ctype.ai_info; +// int goal_segnum, object_segnum, + int abs_index, new_path_index; + + // mprintf((0, "Object %i trying to resume path at index %i\n", objp-Objects, aip->cur_path_index)); + + if ((aip->behavior == AIB_STATION) && (Robot_info[objp->id].companion != 1)) + if (d_rand() > 8192) { + ai_local *ailp = &Ai_local_info[objp-Objects]; + + aip->hide_segment = objp->segnum; +//Int3(); + ailp->mode = AIM_STILL; + mprintf((1, "Note: Bashing hide segment of robot %i to current segment because he's lost.\n", objp-Objects)); + } + +// object_segnum = objp->segnum; + abs_index = aip->hide_index+aip->cur_path_index; +// goal_segnum = Point_segs[abs_index].segnum; + +// if (object_segnum == goal_segnum) +// mprintf((0, "Very peculiar, goal segnum = object's segnum = %i.\n", goal_segnum)); + + new_path_index = aip->cur_path_index - aip->PATH_DIR; + + if ((new_path_index >= 0) && (new_path_index < aip->path_length)) { + // mprintf((0, "Trying path index of %i\n", new_path_index)); + aip->cur_path_index = new_path_index; + } else { + // At end of line and have nowhere to go. + // mprintf((0, "At end of line and can't get to goal. Creating new path. Frame %i\n", FrameCount)); + move_towards_segment_center(objp); + create_path_to_station(objp, 15); + } + +} + +// ---------------------------------------------------------------------------------------------------------- +// DEBUG FUNCTIONS FOLLOW +// ---------------------------------------------------------------------------------------------------------- + +#ifdef EDITOR +int Test_size = 1000; + +void test_create_path_many(void) +{ + point_seg point_segs[200]; + short num_points; + + int i; + + for (i=0; i Anchor_distance) +//--anchor-- create_new_anchor(segnum); +//--anchor-- } +//--anchor-- } +//--anchor-- +//--anchor-- // Set selected segs. +//--anchor-- for (i=0; imtype.phys_info.velocity; + vms_vector norm_cur_vel; + vms_vector norm_vec_to_goal; + vms_vector cur_pos = objp->pos; + vms_vector norm_fvec; + fix speed_scale; + fix dot; + fix max_speed; + + max_speed = Robot_info[objp->id].max_speed[Difficulty_level]; + + vm_vec_sub(&norm_vec_to_goal, goal_point, &cur_pos); + vm_vec_normalize_quick(&norm_vec_to_goal); + + norm_cur_vel = cur_vel; + vm_vec_normalize_quick(&norm_cur_vel); + + norm_fvec = objp->orient.fvec; + vm_vec_normalize_quick(&norm_fvec); + + dot = vm_vec_dot(&norm_vec_to_goal, &norm_fvec); + if (Ai_local_info[objp-Objects].mode == AIM_SNIPE_RETREAT_BACKWARDS) { + dot = -dot; + } + + // If very close to facing opposite desired vector, perturb vector + if (dot < -15*F1_0/16) { + //mprintf((0, "Facing away from goal, abruptly turning\n")); + norm_cur_vel = norm_vec_to_goal; + } else { + norm_cur_vel.x += norm_vec_to_goal.x/2; + norm_cur_vel.y += norm_vec_to_goal.y/2; + norm_cur_vel.z += norm_vec_to_goal.z/2; + } + + vm_vec_normalize_quick(&norm_cur_vel); + + // Set speed based on this robot type's maximum allowed speed and how hard it is turning. + // How hard it is turning is based on the dot product of (vector to goal) and (current velocity vector) + // Note that since 3*F1_0/4 is added to dot product, it is possible for the robot to back up. + + // Set speed and orientation. + if (dot < 0) + dot /= 4; + + speed_scale = fixmul(max_speed, dot); + vm_vec_scale(&norm_cur_vel, speed_scale); + objp->mtype.phys_info.velocity = norm_cur_vel; + ai_turn_towards_vector(&norm_vec_to_goal, objp, F1_0); + +} + +// ---------------------------------------------------------------------------------------------------------- +// Optimization: If current velocity will take robot near goal, don't change velocity +void player_follow_path(object *objp) +{ + vms_vector goal_point; + fix dist_to_goal; + int count, forced_break, original_index; + int goal_seg; + fix threshold_distance; + + if (!Player_following_path_flag) + return; + + if (Player_hide_index == -1) + return; + + if (Player_path_length < 2) + return; + + goal_point = Point_segs[Player_hide_index + Player_cur_path_index].point; + goal_seg = Point_segs[Player_hide_index + Player_cur_path_index].segnum; + Assert((goal_seg >= 0) && (goal_seg <= Highest_segment_index)); + dist_to_goal = vm_vec_dist_quick(&goal_point, &objp->pos); + + if (Player_cur_path_index < 0) + Player_cur_path_index = 0; + else if (Player_cur_path_index >= Player_path_length) + Player_cur_path_index = Player_path_length-1; + + goal_point = Point_segs[Player_hide_index + Player_cur_path_index].point; + + count=0; + + // If near goal, pick another goal point. + forced_break = 0; // Gets set for short paths. + //original_dir = 1; + original_index = Player_cur_path_index; + threshold_distance = fixmul(vm_vec_mag_quick(&objp->mtype.phys_info.velocity), FrameTime)*2 + F1_0*2; + + while ((dist_to_goal < threshold_distance) && !forced_break) { + +// -- if (count > 1) +// -- mprintf((0, ".")); + + // ----- Debug stuff ----- + if (count++ > 20) { + mprintf((1,"Problem following path for player. Aborting.\n")); + break; + } + + // Advance to next point on path. + Player_cur_path_index += 1; + + // See if next point wraps past end of path (in either direction), and if so, deal with it based on mode. + if ((Player_cur_path_index >= Player_path_length) || (Player_cur_path_index < 0)) { + Player_following_path_flag = 0; + forced_break = 1; + } + + // If went all the way around to original point, in same direction, then get out of here! + if (Player_cur_path_index == original_index) { + mprintf((0, "Forcing break because player path wrapped, count = %i.\n", count)); + Player_following_path_flag = 0; + forced_break = 1; + } + + goal_point = Point_segs[Player_hide_index + Player_cur_path_index].point; + dist_to_goal = vm_vec_dist_quick(&goal_point, &objp->pos); + + } // end while + + // Set velocity (objp->mtype.phys_info.velocity) and orientation (objp->orient) for this object. + player_path_set_orient_and_vel(objp, &goal_point); + +} + + +// ------------------------------------------------------------------------------------------------------------------ +// Create path for player from current segment to goal segment. +void create_player_path_to_segment(int segnum) +{ + object *objp = ConsoleObject; + + Player_path_length=0; + Player_hide_index=-1; + Player_cur_path_index=0; + Player_following_path_flag=0; + + if (create_path_points(objp, objp->segnum, segnum, Point_segs_free_ptr, &Player_path_length, 100, 0, 0, -1) == -1) + mprintf((0, "Unable to form path of length %i for myself\n", 100)); + + Player_following_path_flag = 1; + + Player_hide_index = Point_segs_free_ptr - Point_segs; + Player_cur_path_index = 0; + Point_segs_free_ptr += Player_path_length; + if (Point_segs_free_ptr - Point_segs + MAX_PATH_LENGTH*2 > MAX_POINT_SEGS) { + //Int3(); // Contact Mike: This is curious, though not deadly. /eip++;g + ai_reset_all_paths(); + } + +} + +int Player_goal_segment = -1; + +void check_create_player_path(void) +{ + if (Player_goal_segment != -1) + create_player_path_to_segment(Player_goal_segment); + + Player_goal_segment = -1; +} + +#endif + +// ---------------------------------------------------------------------------------------------------------- +// DEBUG FUNCTIONS ENDED +// ---------------------------------------------------------------------------------------------------------- + diff --git a/main/aistruct.h b/main/aistruct.h new file mode 100644 index 00000000..1da7fec4 --- /dev/null +++ b/main/aistruct.h @@ -0,0 +1,199 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + +#ifndef _AISTRUCT_H +#define _AISTRUCT_H + +#include "inferno.h" +//#include "polyobj.h" + +#define GREEN_GUY 1 + +#define MAX_SEGMENTS_PER_PATH 20 + +#define PA_WEAPON_WALL_COLLISION 2 // Level of robot awareness after player weapon hits nearby wall +//#define PA_PLAYER_VISIBLE 2 // Level of robot awareness if robot is looking towards player, and player not hidden +#define PA_NEARBY_ROBOT_FIRED 1 // Level of robot awareness after nearby robot fires a weapon +#define PA_PLAYER_COLLISION 3 // Level of robot awareness after player bumps into robot +#define PA_WEAPON_ROBOT_COLLISION 4 // Level of robot awareness after player weapon hits nearby robot + +// #define PAE_WEAPON_HIT_WALL 1 // weapon hit wall, create player awareness +// #define PAE_WEAPON_HIT_ROBOT 2 // weapon hit wall, create player awareness + +// Constants indicating currently moving forward or backward through path. +// Note that you can add aip->direction to aip_path_index to get next segment on path. +#define AI_DIR_FORWARD 1 +#define AI_DIR_BACKWARD (-AI_DIR_FORWARD) + +// Behaviors +#define AIB_STILL 0x80 +#define AIB_NORMAL 0x81 +#define AIB_BEHIND 0x82 +#define AIB_RUN_FROM 0x83 +#define AIB_SNIPE 0x84 +#define AIB_STATION 0x85 +#define AIB_FOLLOW 0x86 + +#define MIN_BEHAVIOR 0x80 +#define MAX_BEHAVIOR 0x86 + +// Modes +#define AIM_STILL 0 +#define AIM_WANDER 1 +#define AIM_FOLLOW_PATH 2 +#define AIM_CHASE_OBJECT 3 +#define AIM_RUN_FROM_OBJECT 4 +#define AIM_BEHIND 5 +#define AIM_FOLLOW_PATH_2 6 +#define AIM_OPEN_DOOR 7 +#define AIM_GOTO_PLAYER 8 // Only for escort behavior +#define AIM_GOTO_OBJECT 9 // Only for escort behavior + +#define AIM_SNIPE_ATTACK 10 +#define AIM_SNIPE_FIRE 11 +#define AIM_SNIPE_RETREAT 12 +#define AIM_SNIPE_RETREAT_BACKWARDS 13 +#define AIM_SNIPE_WAIT 14 + +#define AIM_THIEF_ATTACK 15 +#define AIM_THIEF_RETREAT 16 +#define AIM_THIEF_WAIT 17 + +#define AISM_GOHIDE 0 +#define AISM_HIDING 1 + +#define AI_MAX_STATE 7 +#define AI_MAX_EVENT 4 + +#define AIS_NONE 0 +#define AIS_REST 1 +#define AIS_SRCH 2 +#define AIS_LOCK 3 +#define AIS_FLIN 4 +#define AIS_FIRE 5 +#define AIS_RECO 6 +#define AIS_ERR_ 7 + +#define AIE_FIRE 0 +#define AIE_HITT 1 +#define AIE_COLL 2 +#define AIE_HURT 3 + +//typedef struct opath { +// byte path_index; // current index of path +// byte path_direction; // current path direction +// byte path_length; // length of current path +// byte nothing; +// short path[MAX_SEGMENTS_PER_PATH]; +// short always_0xabc; // If this is ever not 0xabc, then someone overwrote +//} opath; +// +//typedef struct oai_state { +// short mode; // +// short counter; // kind of a hack, frame countdown until switch modes +// opath paths[2]; +// vms_vector movement_vector; // movement vector for one second +//} oai_state; + +#define SUB_FLAGS_GUNSEG 0x01 +#define SUB_FLAGS_SPROX 0x02 // If set, then this bot drops a super prox, not a prox, when it's time to drop something +#define SUB_FLAGS_CAMERA_AWAKE 0x04 // If set, a camera (on a missile) woke this robot up, so don't fire at player. Can look real stupid! + +// Constants defining meaning of flags in ai_state +#define MAX_AI_FLAGS 11 // This MUST cause word (4 bytes) alignment in ai_static, allowing for one byte mode + +#define CURRENT_GUN flags[0] // This is the last gun the object fired from +#define CURRENT_STATE flags[1] // current behavioral state +#define GOAL_STATE flags[2] // goal state +#define PATH_DIR flags[3] // direction traveling path, 1 = forward, -1 = backward, other = error! +#define SUB_FLAGS flags[4] // bit 0: Set -> Robot's current gun in different segment than robot's center. +#define GOALSIDE flags[5] // for guys who open doors, this is the side they are going after. +#define CLOAKED flags[6] // Cloaked now. +#define SKIP_AI_COUNT flags[7] // Skip AI this frame, but decrement in do_ai_frame. +#define REMOTE_OWNER flags[8] // Who is controlling this remote AI object (multiplayer use only) +#define REMOTE_SLOT_NUM flags[9] // What slot # is this robot in for remote control purposes (multiplayer use only) +#define MULTI_ANGER flags[10] // How angry is a robot in multiplayer mode + +// This is the stuff that is permanent for an AI object and is therefore saved to disk. +typedef struct ai_static { + ubyte behavior; // + byte flags[MAX_AI_FLAGS]; // various flags, meaning defined by constants + short hide_segment; // Segment to go to for hiding. + short hide_index; // Index in Path_seg_points + short path_length; // Length of hide path. + byte cur_path_index; // Current index in path. + byte dying_sound_playing; // !0 if this robot is playing its dying sound. + +// -- not needed! -- short follow_path_start_seg; // Start segment for robot which follows path. +// -- not needed! -- short follow_path_end_seg; // End segment for robot which follows path. + + short danger_laser_num; + int danger_laser_signature; + fix dying_start_time; // Time at which this robot started dying. + +// byte extras[28]; // 32 extra bytes for storing stuff so we don't have to change versions on disk +} __pack__ ai_static; + +// This is the stuff which doesn't need to be saved to disk. +typedef struct ai_local { +// These used to be bytes, changed to ints so I could set watchpoints on them. +// player_awareness_type..rapidfire_count used to be bytes +// goal_segment used to be short. + int player_awareness_type; // type of awareness of player + int retry_count; // number of retries in physics last time this object got moved. + int consecutive_retries; // number of retries in consecutive frames (ie, without a retry_count of 0) + int mode; // current mode within behavior + int previous_visibility; // Visibility of player last time we checked. + int rapidfire_count; // number of shots fired rapidly + int goal_segment; // goal segment for current path + + // -- MK, 10/21/95, unused -- fix last_see_time, last_attack_time; // For sound effects, time at which player last seen, attacked + + fix next_action_time; // time in seconds until something happens, mode dependent + fix next_fire; // time in seconds until can fire again + fix next_fire2; // time in seconds until can fire again from second weapon + fix player_awareness_time; // time in seconds robot will be aware of player, 0 means not aware of player + fix time_player_seen; // absolute time in seconds at which player was last seen, might cause to go into follow_path mode + fix time_player_sound_attacked; // absolute time in seconds at which player was last seen with visibility of 2. + fix next_misc_sound_time; // absolute time in seconds at which this robot last made an angry or lurking sound. + fix time_since_processed; // time since this robot last processed in do_ai_frame + vms_angvec goal_angles[MAX_SUBMODELS]; //angles for each subobject + vms_angvec delta_angles[MAX_SUBMODELS]; //angles for each subobject + byte goal_state[MAX_SUBMODELS]; // Goal state for this sub-object + byte achieved_state[MAX_SUBMODELS]; // Last achieved state +} ai_local; + +typedef struct { + int segnum; + vms_vector point; +} point_seg; + +typedef struct { + short start, end; +} seg_seg; + +#define MAX_POINT_SEGS 2500 + +extern point_seg Point_segs[MAX_POINT_SEGS]; +extern point_seg *Point_segs_free_ptr; +extern int Overall_agitation; + +// These are the information for a robot describing the location of the player last time he wasn't cloaked, +// and the time at which he was uncloaked. We should store this for each robot, but that's memory expensive. +//extern fix Last_uncloaked_time; +//extern vms_vector Last_uncloaked_position; + +extern void ai_do_cloak_stuff(void); + +#endif diff --git a/main/automap.c b/main/automap.c new file mode 100644 index 00000000..1142dcb8 --- /dev/null +++ b/main/automap.c @@ -0,0 +1,1913 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + +#include +#include +#include +#include + +#include "pa_enabl.h" //$$POLY_ACC +#include "error.h" +#include "fix.h" +#include "vecmat.h" +#include "gr.h" +#include "3d.h" +#include "inferno.h" +#include "u_mem.h" +#include "render.h" +#include "object.h" +#include "vclip.h" +#include "game.h" +#include "mono.h" +#include "polyobj.h" +#include "sounds.h" +#include "player.h" +#include "bm.h" +#include "key.h" +#include "newmenu.h" +#include "menu.h" +#include "screens.h" +#include "textures.h" +#include "mouse.h" +#include "timer.h" +#include "segpoint.h" +#include "joy.h" +#include "iff.h" +#include "pcx.h" +#include "palette.h" +#include "wall.h" +#include "gameseq.h" +#include "gamefont.h" +#include "network.h" +#include "kconfig.h" +#include "multi.h" +#include "endlevel.h" +#include "text.h" +#include "gauges.h" +#include "songs.h" +#include "powerup.h" +#include "network.h" +#include "switch.h" +#include "automap.h" +#include "cntrlcen.h" + +#if defined(POLY_ACC) +#include "poly_acc.h" +#endif + +#define EF_USED 1 // This edge is used +#define EF_DEFINING 2 // A structure defining edge that should always draw. +#define EF_FRONTIER 4 // An edge between the known and the unknown. +#define EF_SECRET 8 // An edge that is part of a secret wall. +#define EF_GRATE 16 // A grate... draw it all the time. +#define EF_NO_FADE 32 // An edge that doesn't fade with distance +#define EF_TOO_FAR 64 // An edge that is too far away + +void modex_printf(int x,int y,char *s,grs_font *font,int color); + +typedef struct Edge_info { + short verts[2]; // 4 bytes + ubyte sides[4]; // 4 bytes + short segnum[4]; // 8 bytes // This might not need to be stored... If you can access the normals of a side. + ubyte flags; // 1 bytes // See the EF_??? defines above. + ubyte color; // 1 bytes + ubyte num_faces; // 1 bytes // 19 bytes... +} Edge_info; + +//OLD BUT GOOD -- #define MAX_EDGES_FROM_VERTS(v) ((v*5)/2) +// THE following was determined by John by loading levels 1-14 and recording +// numbers on 10/26/94. +//#define MAX_EDGES_FROM_VERTS(v) (((v)*21)/10) +#define MAX_EDGES_FROM_VERTS(v) ((v)*4) +//#define MAX_EDGES (MAX_EDGES_FROM_VERTS(MAX_VERTICES)) + +#define MAX_EDGES 6000 // Determined by loading all the levels by John & Mike, Feb 9, 1995 + +#define K_WALL_NORMAL_COLOR BM_XRGB( 29, 29, 29 ) +#define K_WALL_DOOR_COLOR BM_XRGB( 5, 27, 5 ) +#define K_WALL_DOOR_BLUE BM_XRGB( 0, 0, 31) +#define K_WALL_DOOR_GOLD BM_XRGB( 31, 31, 0) +#define K_WALL_DOOR_RED BM_XRGB( 31, 0, 0) +#define K_WALL_REVEALED_COLOR BM_XRGB( 0, 0, 25 ) //what you see when you have the full map powerup +#define K_HOSTAGE_COLOR BM_XRGB( 0, 31, 0 ) +#define K_FONT_COLOR_20 BM_XRGB( 20, 20, 20 ) +#define K_GREEN_31 BM_XRGB(0, 31, 0) + +int Wall_normal_color; +int Wall_door_color; +int Wall_door_blue; +int Wall_door_gold; +int Wall_door_red; +int Wall_revealed_color; +int Hostage_color; +int Font_color_20; +int Green_31; +int White_63; +int Blue_48; +int Red_48; + +void init_automap_colors(void) +{ + Wall_normal_color = K_WALL_NORMAL_COLOR; + Wall_door_color = K_WALL_DOOR_COLOR; + Wall_door_blue = K_WALL_DOOR_BLUE; + Wall_door_gold = K_WALL_DOOR_GOLD; + Wall_door_red = K_WALL_DOOR_RED; + Wall_revealed_color = K_WALL_REVEALED_COLOR; + Hostage_color = K_HOSTAGE_COLOR; + Font_color_20 = K_FONT_COLOR_20; + Green_31 = K_GREEN_31; + + White_63 = gr_find_closest_color_current(63,63,63); + Blue_48 = gr_find_closest_color_current(0,0,48); + Red_48 = gr_find_closest_color_current(48,0,0); +} + +// Segment visited list +ubyte Automap_visited[MAX_SEGMENTS]; + +// Edge list variables +static int Num_edges=0; +static int Max_edges; //set each frame +static int Highest_edge_index = -1; +static Edge_info Edges[MAX_EDGES]; +static short DrawingListBright[MAX_EDGES]; + +//static short DrawingListBright[MAX_EDGES]; +//static short Edge_used_list[MAX_EDGES]; //which entries in edge_list have been used + +// Map movement defines +#define PITCH_DEFAULT 9000 +#define ZOOM_DEFAULT i2f(20*10) +#define ZOOM_MIN_VALUE i2f(20*5) +#define ZOOM_MAX_VALUE i2f(20*100) + +#define SLIDE_SPEED (350) +#define ZOOM_SPEED_FACTOR 500 //(1500) +#define ROT_SPEED_DIVISOR (115000) + +// Screen anvas variables +static int current_page=0; +#ifdef WINDOWS +static dd_grs_canvas ddPages[2]; +static dd_grs_canvas ddDrawingPages[2]; + +#define ddPage ddPages[0] +#define ddDrawingPage ddDrawingPages[0] + +#endif + +#if defined(MACINTOSH) && defined(POLY_ACC) + grs_canvas Pages[2]; // non static under rave so the backbuffer callback function can get at them + grs_canvas DrawingPages[2]; // non static under rave so the backbuffer callback function can get at them +#else + static grs_canvas Pages[2]; + static grs_canvas DrawingPages[2]; +#endif + +#define Page Pages[0] +#define DrawingPage DrawingPages[0] + +// Flags +static int Automap_cheat = 0; // If set, show everything + +// Rendering variables +static fix Automap_zoom = 0x9000; +static vms_vector view_target; +static fix Automap_farthest_dist = (F1_0 * 20 * 50); // 50 segments away +static vms_matrix ViewMatrix; +static fix ViewDist=0; + +// Function Prototypes +void adjust_segment_limit(int SegmentLimit); +void draw_all_edges(void); +void automap_build_edge_list(void); + +#define MAX_DROP_MULTI 2 +#define MAX_DROP_SINGLE 9 + +vms_vector MarkerPoint[NUM_MARKERS]; //these are only used in multi.c, and I'd get rid of them there, but when I tried to do that once, I caused some horrible bug. -MT +int HighlightMarker=-1; +char MarkerMessage[NUM_MARKERS][MARKER_MESSAGE_LEN]; +char MarkerOwner[NUM_MARKERS][CALLSIGN_LEN+1]; +float MarkerScale=2.0; +int MarkerObject[NUM_MARKERS]; + +extern vms_vector Matrix_scale; //how the matrix is currently scaled + +// ------------------------------------------------------------- + +void DrawMarkerNumber (int num) + { + int i; + g3s_point BasePoint,FromPoint,ToPoint; + + float ArrayX[10][20]={ {-.25, 0.0, 0.0, 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.0, 1.0, -1.0, 1.0, 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.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.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.0, -1.0, 1.0, -1.0, -1.0} + + }; + float ArrayY[10][20]={ {.75, 1.0, 1.0, -1.0, -1.0, -1.0}, + {1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, -1.0, -1.0}, + {1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 0.0, 0.0}, + {1.0, 0.0, 0.0, 0.0, 1.0, -1.0}, + {1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, -1.0, -1.0}, + {1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 0.0, 0.0, 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, 0.0, 0.0}, + {1.0, 1.0, 1.0, -1.0, 0.0, 0.0, 0.0, 1.0} + }; + int NumOfPoints[]={6,10,8,6,10,10,4,10,8}; + + for (i=0;ipos; + + if (MarkerObject[marker_num] != -1) + obj_delete(MarkerObject[marker_num]); + + MarkerObject[marker_num] = drop_marker_object(&playerp->pos,playerp->segnum,&playerp->orient,marker_num); + +#ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_drop_marker (Player_num,playerp->pos,player_marker_num,MarkerMessage[marker_num]); +#endif + +} + +extern char guidebot_name[]; + +void DropBuddyMarker(object *objp) +{ + int marker_num; + + // Find spare marker slot. "if" code below should be an assert, but what if someone changes NUM_MARKERS or MAX_CROP_SINGLE and it never gets hit? + marker_num = MAX_DROP_SINGLE+1; + if (marker_num > NUM_MARKERS-1) + marker_num = NUM_MARKERS-1; + + sprintf(MarkerMessage[marker_num], "RIP: %s",guidebot_name); + + MarkerPoint[marker_num] = objp->pos; + + if (MarkerObject[marker_num] != -1 && MarkerObject[marker_num] !=0) + obj_delete(MarkerObject[marker_num]); + + MarkerObject[marker_num] = drop_marker_object(&objp->pos, objp->segnum, &objp->orient, marker_num); + +} + +#define MARKER_SPHERE_SIZE 0x58000 + +void DrawMarkers () + { + int i,maxdrop; + static int cyc=10,cycdir=1; + g3s_point sphere_point; + + if (Game_mode & GM_MULTI) + maxdrop=2; + else + maxdrop=9; + + for (i=0;i43) + { + cyc=43; + cycdir=0; + } + else if (cyc<10) + { + cyc=10; + cycdir=1; + } + + } + +void ClearMarkers() + { + int i; + + for (i=0;ipos); + g3_draw_sphere(&sphere_point,obj->size); + + // Draw shaft of arrow + vm_vec_scale_add( &arrow_pos, &obj->pos, &obj->orient.fvec, obj->size*3 ); + g3_rotate_point(&arrow_point,&arrow_pos); + #if defined(MACINTOSH) && defined(POLY_ACC) + { + int savePAEnabledState = PAEnabled; // icky hack. automap draw context is no longer valid when this is called. + // so we can not use the pa_draw_line function for rave + + PAEnabled = 0; + g3_draw_line( &sphere_point, &arrow_point ); + PAEnabled = savePAEnabledState; + } + #else + g3_draw_line( &sphere_point, &arrow_point ); + #endif + + // Draw right head of arrow + vm_vec_scale_add( &head_pos, &obj->pos, &obj->orient.fvec, obj->size*2 ); + vm_vec_scale_add2( &head_pos, &obj->orient.rvec, obj->size*1 ); + g3_rotate_point(&head_point,&head_pos); + #if defined(MACINTOSH) && defined(POLY_ACC) + { + int savePAEnabledState = PAEnabled; + PAEnabled = 0; + g3_draw_line( &arrow_point, &head_point ); + PAEnabled = savePAEnabledState; + } + #else + g3_draw_line( &arrow_point, &head_point ); + #endif + + // Draw left head of arrow + vm_vec_scale_add( &head_pos, &obj->pos, &obj->orient.fvec, obj->size*2 ); + vm_vec_scale_add2( &head_pos, &obj->orient.rvec, obj->size*(-1) ); + g3_rotate_point(&head_point,&head_pos); + #if defined(MACINTOSH) && defined(POLY_ACC) + { + int savePAEnabledState = PAEnabled; + PAEnabled = 0; + g3_draw_line( &arrow_point, &head_point ); + PAEnabled = savePAEnabledState; + } + #else + g3_draw_line( &arrow_point, &head_point ); + #endif + + // Draw player's up vector + vm_vec_scale_add( &arrow_pos, &obj->pos, &obj->orient.uvec, obj->size*2 ); + g3_rotate_point(&arrow_point,&arrow_pos); + #if defined(MACINTOSH) && defined(POLY_ACC) + { + int savePAEnabledState = PAEnabled; + PAEnabled = 0; + g3_draw_line( &sphere_point, &arrow_point ); + PAEnabled = savePAEnabledState; + } + #else + g3_draw_line( &sphere_point, &arrow_point ); + #endif + + +} + +int AutomapHires; +#if defined(MACINTOSH) && defined(POLY_ACC) + + void pa_mac_draw_automap_extras(void) + { + int i; + int color; + object * objp; + g3s_point sphere_point; + + AutomapHires = 1; // always on the mac + + // Draw player... + #ifdef NETWORK + if (Game_mode & GM_TEAM) + color = get_team(Player_num); + else + #endif + color = Player_num; // Note link to above if! + + gr_setcolor(gr_getcolor(player_rgb[color].r,player_rgb[color].g,player_rgb[color].b)); + draw_player(&Objects[Players[Player_num].objnum]); + + DrawMarkers(); + + if (HighlightMarker>-1 && MarkerMessage[HighlightMarker][0]!=0) + { + char msg[10+MARKER_MESSAGE_LEN+1]; + + sprintf(msg,"Marker %d: %s",HighlightMarker+1,MarkerMessage[(Player_num*2)+HighlightMarker]); + + gr_setcolor (Red_48); + + modex_printf(5,20,msg,SMALL_FONT,Font_color_20); + } + + // Draw player(s)... + #ifdef NETWORK + if ( (Game_mode & (GM_TEAM | GM_MULTI_COOP)) || (Netgame.game_flags & NETGAME_FLAG_SHOW_MAP) ) + { + for (i=0; itype ) + { + case OBJ_HOSTAGE: + gr_setcolor(Hostage_color); + g3_rotate_point(&sphere_point,&objp->pos); + g3_draw_sphere(&sphere_point,objp->size); + break; + case OBJ_POWERUP: + if ( Automap_visited[objp->segnum] ) + { + if ( (objp->id==POW_KEY_RED) || (objp->id==POW_KEY_BLUE) || (objp->id==POW_KEY_GOLD) ) + { + switch (objp->id) + { + case POW_KEY_RED: gr_setcolor(gr_getcolor(63, 5, 5)); break; + case POW_KEY_BLUE: gr_setcolor(gr_getcolor(5, 5, 63)); break; + case POW_KEY_GOLD: gr_setcolor(gr_getcolor(63, 63, 10)); break; + default: + Error("Illegal key type: %i", objp->id); + } + g3_rotate_point(&sphere_point,&objp->pos); + g3_draw_sphere(&sphere_point,objp->size*4); + } + } + break; + } + } + + gr_bitmapm(AutomapHires?10:AutomapHires?10:5,5,&name_canv_left->cv_bitmap); + gr_bitmapm(grd_curcanv->cv_bitmap.bm_w-(AutomapHires?10:5)-name_canv_right->cv_bitmap.bm_w,AutomapHires?10:5,&name_canv_right->cv_bitmap); + } + + void pa_mac_draw_automap(void) + { + vms_vector viewer_position; + + g3_start_frame(); + render_start_frame(); + pa_set_context(kAutoMapDrawContextID, NULL); + pa_render_start(); + + vm_vec_scale_add(&viewer_position,&view_target,&ViewMatrix.fvec,-ViewDist ); + g3_set_view_matrix(&viewer_position,&ViewMatrix,Automap_zoom); + + draw_all_edges(); + + g3_end_frame(); + pa_render_end(); + } +#endif + +void draw_automap() +{ + int i; + int color; + object * objp; + vms_vector viewer_position; + g3s_point sphere_point; + + #ifdef MACINTOSH + #ifdef POLY_ACC + if (PAEnabled) + { + pa_mac_draw_automap(); + return; + } + #endif + #endif + + if (!AutomapHires) { + WIN(mprintf((1, "Can't do lores automap in Windows!\n"))); + WIN(Int3()); + current_page ^= 1; + gr_set_current_canvas(&DrawingPages[current_page]); + } + else { + WINDOS( + dd_gr_set_current_canvas(&ddDrawingPage), + gr_set_current_canvas(&DrawingPage) + ); + } + +#if defined(POLY_ACC) + pa_flush(); +#endif + + WINDOS( + dd_gr_clear_canvas(BM_XRGB(0,0,0)), + gr_clear_canvas(BM_XRGB(0,0,0)) + ); + +WIN(DDGRLOCK(dd_grd_curcanv)); +{ + g3_start_frame(); + render_start_frame(); + + vm_vec_scale_add(&viewer_position,&view_target,&ViewMatrix.fvec,-ViewDist ); + + g3_set_view_matrix(&viewer_position,&ViewMatrix,Automap_zoom); + +// mprintf((0, "dd_grd_curcanv->canvas.cv_bitmap.bm_data= %x\n", dd_grd_curcanv->canvas.cv_bitmap.bm_data)); +// mprintf((0, "grd_curcanv->cv_bitmap.bm_data= %x\n", grd_curcanv->cv_bitmap.bm_data)); + + draw_all_edges(); + + // Draw player... +#ifdef NETWORK + if (Game_mode & GM_TEAM) + color = get_team(Player_num); + else +#endif + color = Player_num; // Note link to above if! + + gr_setcolor(gr_getcolor(player_rgb[color].r,player_rgb[color].g,player_rgb[color].b)); + draw_player(&Objects[Players[Player_num].objnum]); + + DrawMarkers(); + + if (HighlightMarker>-1 && MarkerMessage[HighlightMarker][0]!=0) + { + char msg[10+MARKER_MESSAGE_LEN+1]; + + sprintf(msg,"Marker %d: %s",HighlightMarker+1,MarkerMessage[(Player_num*2)+HighlightMarker]); + + gr_setcolor (Red_48); + + modex_printf(5,20,msg,SMALL_FONT,Font_color_20); + } + + // Draw player(s)... +#ifdef NETWORK + if ( (Game_mode & (GM_TEAM | GM_MULTI_COOP)) || (Netgame.game_flags & NETGAME_FLAG_SHOW_MAP) ) { + for (i=0; itype ) { + case OBJ_HOSTAGE: + gr_setcolor(Hostage_color); + g3_rotate_point(&sphere_point,&objp->pos); + g3_draw_sphere(&sphere_point,objp->size); + break; + case OBJ_POWERUP: + if ( Automap_visited[objp->segnum] ) { + if ( (objp->id==POW_KEY_RED) || (objp->id==POW_KEY_BLUE) || (objp->id==POW_KEY_GOLD) ) { + switch (objp->id) { + case POW_KEY_RED: gr_setcolor(gr_getcolor(63, 5, 5)); break; + case POW_KEY_BLUE: gr_setcolor(gr_getcolor(5, 5, 63)); break; + case POW_KEY_GOLD: gr_setcolor(gr_getcolor(63, 63, 10)); break; + default: + Error("Illegal key type: %i", objp->id); + } + g3_rotate_point(&sphere_point,&objp->pos); + g3_draw_sphere(&sphere_point,objp->size*4); + } + } + break; + } + } + + g3_end_frame(); + + gr_bitmapm(AutomapHires?10:AutomapHires?10:5,5,&name_canv_left->cv_bitmap); + gr_bitmapm(grd_curcanv->cv_bitmap.bm_w-(AutomapHires?10:5)-name_canv_right->cv_bitmap.bm_w,AutomapHires?10:5,&name_canv_right->cv_bitmap); +} +WIN(DDGRUNLOCK(dd_grd_curcanv)); + + if (!AutomapHires) + gr_show_canvas( &Pages[current_page] ); + else { + #ifndef WINDOWS + //gr_bm_ubitblt( Page.cv_bitmap.bm_w, Page.cv_bitmap.bm_h, Page.cv_bitmap.bm_x, Page.cv_bitmap.bm_y, 0, 0, &Page.cv_bitmap, &VR_screen_pages[0].cv_bitmap ); + gr_bm_ubitblt( Page.cv_bitmap.bm_w, Page.cv_bitmap.bm_h, Page.cv_bitmap.bm_x, Page.cv_bitmap.bm_y, 0, 0, &Page.cv_bitmap, &grd_curscreen->sc_canvas.cv_bitmap ); + #else + dd_gr_blt_screen(&ddPage, 0,0,0,0,0,0,0,0); + #endif + } + gr_update(); + +} + +#ifdef WINDOWS +#define LEAVE_TIME 0x00010000 +#else +#define LEAVE_TIME 0x4000 +#endif + +#define WINDOW_WIDTH 288 + + +//print to canvas & double height +grs_canvas *print_to_canvas(char *s,grs_font *font, int fc, int bc, int double_flag) +{ + int y; + ubyte *data; + int rs; + grs_canvas *temp_canv; + grs_font *save_font; + int w,h,aw; + +WINDOS( + dd_grs_canvas *save_canv, + grs_canvas *save_canv +); + +WINDOS( + save_canv = dd_grd_curcanv, + save_canv = grd_curcanv +); + + save_font = grd_curcanv->cv_font; + gr_set_curfont(font); //set the font we're going to use + gr_get_string_size(s,&w,&h,&aw); //now get the string size + gr_set_curfont(save_font); //restore real font + + //temp_canv = gr_create_canvas(font->ft_w*strlen(s),font->ft_h*2); + temp_canv = gr_create_canvas(w,font->ft_h*2); + + gr_set_current_canvas(temp_canv); + gr_set_curfont(font); + gr_clear_canvas(TRANSPARENCY_COLOR); //trans color + gr_set_fontcolor(fc,bc); + gr_printf(0,0,s); + + //now double it, since we're drawing to 400-line modex screen + + if (double_flag) { + data = temp_canv->cv_bitmap.bm_data; + rs = temp_canv->cv_bitmap.bm_rowsize; + + for (y=temp_canv->cv_bitmap.bm_h/2;y--;) { + memcpy(data+(rs*y*2),data+(rs*y),temp_canv->cv_bitmap.bm_w); + memcpy(data+(rs*(y*2+1)),data+(rs*y),temp_canv->cv_bitmap.bm_w); + } + } + +WINDOS( + dd_gr_set_current_canvas(save_canv), + gr_set_current_canvas(save_canv) +); + + return temp_canv; +} + +//print to buffer, double heights, and blit bitmap to screen +void modex_printf(int x,int y,char *s,grs_font *font,int color) +{ + grs_canvas *temp_canv; + + temp_canv = print_to_canvas(s, font, color, -1, !AutomapHires); + + gr_bitmapm(x,y,&temp_canv->cv_bitmap); + + gr_free_canvas(temp_canv); +} + +//name for each group. maybe move somewhere else +char *system_name[] = { + "Zeta Aquilae", + "Quartzon System", + "Brimspark System", + "Limefrost Spiral", + "Baloris Prime", + "Omega System"}; + +void create_name_canv() +{ + char name_level_left[128],name_level_right[128]; + + if (Current_level_num > 0) + sprintf(name_level_left, "%s %i",TXT_LEVEL, Current_level_num); + else + sprintf(name_level_left, "Secret Level %i",-Current_level_num); + + if (Current_mission_num == 0 && Current_level_num>0) //built-in mission + sprintf(name_level_right,"%s %d: ",system_name[(Current_level_num-1)/4],((Current_level_num-1)%4)+1); + else + strcpy(name_level_right, " "); + + strcat(name_level_right, Current_level_name); + + gr_set_fontcolor(Green_31,-1); + name_canv_left = print_to_canvas(name_level_left, SMALL_FONT, Green_31, -1, !AutomapHires); + name_canv_right = print_to_canvas(name_level_right,SMALL_FONT, Green_31, -1, !AutomapHires); + +} + +void modex_print_message(int x, int y, char *str) +{ + if (!AutomapHires) { + int i; + + for (i=0; i<2; i++ ) { + gr_set_current_canvas(&Pages[i]); + modex_printf(x, y, str, MEDIUM1_FONT,Font_color_20); + } + gr_set_current_canvas(&DrawingPages[current_page]); + } + else { + gr_set_current_canvas(&Page); + modex_printf(x, y, str, MEDIUM1_FONT,Font_color_20); + gr_set_current_canvas(&DrawingPage); + } +} + +extern void GameLoop(int, int ); +extern int set_segment_depths(int start_seg, ubyte *segbuf); + +int Automap_active = 0; + +#ifdef RELEASE +#define MAP_BACKGROUND_FILENAME (AutomapHires?"\x01MAPB.PCX":"\x01MAP.PCX") //load only from hog file +#else +#define MAP_BACKGROUND_FILENAME (AutomapHires?"MAPB.PCX":"MAP.PCX") +#endif + +int Automap_always_hires=0; +extern int MenuHiresAvailable; + +extern int Current_display_mode; + +void do_automap( int key_code ) { + int done=0; + vms_matrix tempm; + vms_angvec tangles; + int leave_mode=0; + int first_time=1; + int pcx_error; + int i; + int c, marker_num; + fix entry_time; + int pause_game=1; // Set to 1 if everything is paused during automap...No pause during net. + fix t1, t2; + control_info saved_control_info; + grs_bitmap Automap_background; + int Max_segments_away = 0; + int SegmentLimit = 1; + ubyte pal[256*3]; + char maxdrop; + int must_free_canvas=0; + + WIN(int dd_VR_screen_mode_save); + WIN(int redraw_screen=0); + + Automap_active = 1; + + init_automap_colors(); + + key_code = key_code; // disable warning... + + if ((Game_mode & GM_MULTI) && (Function_mode == FMODE_GAME) && (!Endlevel_sequence)) + pause_game = 0; + + if (pause_game) { + stop_time(); + digi_pause_digi_sounds(); + } + + Max_edges = min(MAX_EDGES_FROM_VERTS(Num_vertices),MAX_EDGES); //make maybe smaller than max + + mprintf( (0, "Num_vertices=%d, Max_edges=%d, (MAX:%d)\n", Num_vertices, Max_edges, MAX_EDGES )); + mprintf( (0, "Allocated %d K for automap edge list\n", (sizeof(Edge_info)+sizeof(short))*Max_edges/1024 )); + + #if !defined (WINDOWS) && !defined(MACINTOSH) + if ((Current_display_mode!=0 && Current_display_mode!=2) || (Automap_always_hires && MenuHiresAvailable)) { +#if !defined(POLY_ACC) + gr_set_mode( SM(640, 480) ); +#endif + PA_DFX (pa_set_frontbuffer_current()); + AutomapHires = 1; + } + else { + gr_set_mode( SM(320, 400)); + AutomapHires = 0; + } + #else + AutomapHires = 1; //Mac & Windows(?) always in hires + #endif + + #ifdef WINDOWS + dd_VR_screen_mode_save = VR_screen_mode; + VR_screen_mode = SM95_640x480x8; // HACK! Forcing reinit of 640x480 + set_screen_mode(SCREEN_GAME); + #endif + + FontHires = AutomapHires; + + create_name_canv(); + + gr_palette_clear(); + +WIN(AutomapRedraw:) + if (!AutomapHires) { + #ifndef MACINTOSH + gr_init_sub_canvas(&Pages[0],grd_curcanv,0,0,320,400); + gr_init_sub_canvas(&Pages[1],grd_curcanv,0,401,320,400); + gr_init_sub_canvas(&DrawingPages[0],&Pages[0],16,69,WINDOW_WIDTH,272); + gr_init_sub_canvas(&DrawingPages[1],&Pages[1],16,69,WINDOW_WIDTH,272); + + Automap_background.bm_data = NULL; + pcx_error = pcx_read_bitmap(MAP_BACKGROUND_FILENAME,&Automap_background,BM_LINEAR,pal); + if ( pcx_error != PCX_ERROR_NONE ) + Error("File %s - PCX error: %s",MAP_BACKGROUND_FILENAME,pcx_errormsg(pcx_error)); + gr_remap_bitmap_good( &Automap_background, pal, -1, -1 ); + + for (i=0; i<2; i++ ) { + gr_set_current_canvas(&Pages[i]); + gr_bitmap( 0, 0, &Automap_background ); + modex_printf( 40, 22,TXT_AUTOMAP,HUGE_FONT,Font_color_20); + modex_printf( 30,353,TXT_TURN_SHIP,SMALL_FONT,Font_color_20); + modex_printf( 30,369,TXT_SLIDE_UPDOWN,SMALL_FONT,Font_color_20); + modex_printf( 30,385,TXT_VIEWING_DISTANCE,SMALL_FONT,Font_color_20); + } + if ( Automap_background.bm_data ) + d_free( Automap_background.bm_data ); + Automap_background.bm_data = NULL; + + gr_set_current_canvas(&DrawingPages[current_page]); + #endif + } + else { + if (VR_render_buffer[0].cv_w >= 640 && VR_render_buffer[0].cv_h >= 480) + { + WIN(dd_gr_init_sub_canvas(&ddPage, &dd_VR_render_buffer[0], 0, 0, 640,480)); + + #if defined(MACINTOSH) && defined(POLY_ACC) + if (PAEnabled) + { + // we want all the automap border stuff to be drawn straight to the screen + gr_init_sub_canvas(&Page,&(grd_curscreen->sc_canvas),0, 0, 640, 480); + } + else + { + gr_init_sub_canvas(&Page,&VR_render_buffer[0],0, 0, 640, 480); + } + #else + gr_init_sub_canvas(&Page,&VR_render_buffer[0],0, 0, 640, 480); + #endif + + } + else { + #ifndef WINDOWS + void *raw_data; + MALLOC(raw_data,ubyte,640*480); + gr_init_canvas(&Page,raw_data,BM_LINEAR,640,480); + #else + dd_gr_init_canvas(&ddPage, BM_LINEAR, 640,480); + gr_init_canvas(&Page,NULL,BM_LINEAR,640,480); + #endif + must_free_canvas = 1; + } + + WIN(dd_gr_init_sub_canvas(&ddDrawingPage, &ddPage, 27,80,582,334)); + gr_init_sub_canvas(&DrawingPage,&Page,27,80,582,334); + + WINDOS( + dd_gr_set_current_canvas(&ddPage), + gr_set_current_canvas(&Page) + ); + +#if defined(POLY_ACC) + + #ifndef MACINTOSH + pcx_error = pcx_read_bitmap(MAP_BACKGROUND_FILENAME,&(grd_curcanv->cv_bitmap),BM_LINEAR15,pal); + #else + if ( PAEnabled ) + { + pcx_error = pcx_read_bitmap(MAP_BACKGROUND_FILENAME,&(grd_curcanv->cv_bitmap),BM_LINEAR15,pal); + if ( pcx_error != PCX_ERROR_NONE ) + { + Error("File %s - PCX error: %s",MAP_BACKGROUND_FILENAME,pcx_errormsg(pcx_error)); + return; + } + } + else + { + pcx_error = pcx_read_bitmap(MAP_BACKGROUND_FILENAME,&(grd_curcanv->cv_bitmap),BM_LINEAR,pal); + if ( pcx_error != PCX_ERROR_NONE ) + { + Error("File %s - PCX error: %s",MAP_BACKGROUND_FILENAME,pcx_errormsg(pcx_error)); + return; + } + + gr_remap_bitmap_good( &(grd_curcanv->cv_bitmap), pal, -1, -1 ); + } + #endif +#else + + WIN(DDGRLOCK(dd_grd_curcanv)); + pcx_error = pcx_read_bitmap(MAP_BACKGROUND_FILENAME,&(grd_curcanv->cv_bitmap),BM_LINEAR,pal); + if ( pcx_error != PCX_ERROR_NONE ) { + //printf("File %s - PCX error: %s",MAP_BACKGROUND_FILENAME,pcx_errormsg(pcx_error)); + Error("File %s - PCX error: %s",MAP_BACKGROUND_FILENAME,pcx_errormsg(pcx_error)); + return; + } + + gr_remap_bitmap_good( &(grd_curcanv->cv_bitmap), pal, -1, -1 ); +#endif + + gr_set_curfont(HUGE_FONT); + gr_set_fontcolor(BM_XRGB(20, 20, 20), -1); + gr_printf( 80, 36,TXT_AUTOMAP,HUGE_FONT); + gr_set_curfont(SMALL_FONT); + gr_set_fontcolor(BM_XRGB(20, 20, 20), -1); + gr_printf( 60, 426,TXT_TURN_SHIP); + gr_printf( 60, 443,TXT_SLIDE_UPDOWN); + gr_printf( 60, 460,TXT_VIEWING_DISTANCE); + WIN(DDGRUNLOCK(dd_grd_curcanv)); + + WINDOS( + dd_gr_set_current_canvas(&ddDrawingPage), + gr_set_current_canvas(&DrawingPage) + ); + } + + +WIN(if (!redraw_screen) {) + automap_build_edge_list(); + + if ( ViewDist==0 ) + ViewDist = ZOOM_DEFAULT; + ViewMatrix = Objects[Players[Player_num].objnum].orient; + + tangles.p = PITCH_DEFAULT; + tangles.h = 0; + tangles.b = 0; + + done = 0; + + view_target = Objects[Players[Player_num].objnum].pos; + + t1 = entry_time = timer_get_fixed_seconds(); + t2 = t1; + + //Fill in Automap_visited from Objects[Players[Player_num].objnum].segnum + Max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited); + SegmentLimit = Max_segments_away; + + adjust_segment_limit(SegmentLimit); +WIN(}) + +WIN(if (redraw_screen) redraw_screen = 0); + + while(!done) { + if ( leave_mode==0 && Controls.automap_state && (timer_get_fixed_seconds()-entry_time)>LEAVE_TIME) + leave_mode = 1; + + if ( !Controls.automap_state && (leave_mode==1) ) + done=1; + + if (!pause_game) { + ushort old_wiggle; + saved_control_info = Controls; // Save controls so we can zero them + memset(&Controls,0,sizeof(control_info)); // Clear everything... + old_wiggle = ConsoleObject->mtype.phys_info.flags & PF_WIGGLE; // Save old wiggle + ConsoleObject->mtype.phys_info.flags &= ~PF_WIGGLE; // Turn off wiggle + #ifdef NETWORK + if (multi_menu_poll()) + done = 1; + #endif +// GameLoop( 0, 0 ); // Do game loop with no rendering and no reading controls. + ConsoleObject->mtype.phys_info.flags |= old_wiggle; // Restore wiggle + Controls = saved_control_info; + } + + #ifndef WINDOWS + controls_read_all(); + #else + controls_read_all_win(); + #endif + + if ( Controls.automap_down_count ) { + if (leave_mode==0) + done = 1; + c = 0; + } + + //see if redbook song needs to be restarted + songs_check_redbook_repeat(); + + #ifdef WINDOWS + { + MSG msg; + DoMessageStuff(&msg); + if (_RedrawScreen) { + _RedrawScreen = FALSE; + redraw_screen = 1; + goto AutomapRedraw; + } + + if (msg.message == WM_QUIT) exit(1); + + DDGRRESTORE; + } + #endif + + + while( (c=key_inkey()) ) { + switch( c ) { + #ifndef NDEBUG + case KEY_BACKSP: Int3(); break; + #endif + + case KEY_PRINT_SCREEN: { + if (AutomapHires) { + WINDOS( + dd_gr_set_current_canvas(NULL), + gr_set_current_canvas(NULL) + ); + } + else + gr_set_current_canvas(&Pages[current_page]); + save_screen_shot(1); + break; + } + + case KEY_ESC: + if (leave_mode==0) + done = 1; + break; + + #ifndef NDEBUG + case KEY_DEBUGGED+KEY_F: { + for (i=0; i<=Highest_segment_index; i++ ) + Automap_visited[i] = 1; + automap_build_edge_list(); + Max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited); + SegmentLimit = Max_segments_away; + adjust_segment_limit(SegmentLimit); + } + break; + #endif + + case KEY_MINUS: + if (SegmentLimit > 1) { + SegmentLimit--; + adjust_segment_limit(SegmentLimit); + } + break; + case KEY_EQUAL: + if (SegmentLimit < Max_segments_away) { + SegmentLimit++; + adjust_segment_limit(SegmentLimit); + } + break; + case KEY_1: + case KEY_2: + case KEY_3: + case KEY_4: + case KEY_5: + case KEY_6: + case KEY_7: + case KEY_8: + case KEY_9: + case KEY_0: + if (Game_mode & GM_MULTI) + maxdrop=2; + else + maxdrop=9; + + #ifndef MACINTOSH + marker_num = c-KEY_1; + #else + switch(c) { // god this is stupid..... + case KEY_1: marker_num = 0; break; + case KEY_2: marker_num = 1; break; + case KEY_3: marker_num = 2; break; + case KEY_4: marker_num = 3; break; + case KEY_5: marker_num = 4; break; + case KEY_6: marker_num = 5; break; + case KEY_7: marker_num = 6; break; + case KEY_8: marker_num = 7; break; + case KEY_9: marker_num = 8; break; + case KEY_0: marker_num = 9; break; + } + #endif + if (marker_num<=maxdrop) + { + if (MarkerObject[marker_num] != -1) + HighlightMarker=marker_num; + } + break; + + case KEY_D+KEY_CTRLED: + if (current_page) //menu will only work on page 0 + draw_automap(); //..so switch from 1 to 0 + + if (HighlightMarker > -1 && MarkerObject[HighlightMarker] != -1) { + WINDOS( + dd_gr_set_current_canvas(&ddPages[current_page]), + gr_set_current_canvas(&Pages[current_page]) + ); + + if (nm_messagebox( NULL, 2, TXT_YES, TXT_NO, "Delete Marker?" ) == 0) { + obj_delete(MarkerObject[HighlightMarker]); + MarkerObject[HighlightMarker]=-1; + MarkerMessage[HighlightMarker][0]=0; + HighlightMarker = -1; + } + } + break; + + #ifndef RELEASE + case KEY_COMMA: + if (MarkerScale>.5) + MarkerScale-=.5; + break; + case KEY_PERIOD: + if (MarkerScale<30.0) + MarkerScale+=.5; + #endif + + } + } + + if ( Controls.fire_primary_down_count ) { + // Reset orientation + ViewDist = ZOOM_DEFAULT; + tangles.p = PITCH_DEFAULT; + tangles.h = 0; + tangles.b = 0; + view_target = Objects[Players[Player_num].objnum].pos; + } + + ViewDist -= Controls.forward_thrust_time*ZOOM_SPEED_FACTOR; + + tangles.p += fixdiv( Controls.pitch_time, ROT_SPEED_DIVISOR ); + tangles.h += fixdiv( Controls.heading_time, ROT_SPEED_DIVISOR ); + tangles.b += fixdiv( Controls.bank_time, ROT_SPEED_DIVISOR*2 ); + + if ( Controls.vertical_thrust_time || Controls.sideways_thrust_time ) { + vms_angvec tangles1; + vms_vector old_vt; + old_vt = view_target; + tangles1 = tangles; + vm_angles_2_matrix(&tempm,&tangles1); + vm_matrix_x_matrix(&ViewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm); + vm_vec_scale_add2( &view_target, &ViewMatrix.uvec, Controls.vertical_thrust_time*SLIDE_SPEED ); + vm_vec_scale_add2( &view_target, &ViewMatrix.rvec, Controls.sideways_thrust_time*SLIDE_SPEED ); + if ( vm_vec_dist_quick( &view_target, &Objects[Players[Player_num].objnum].pos) > i2f(1000) ) { + view_target = old_vt; + } + } + + vm_angles_2_matrix(&tempm,&tangles); + vm_matrix_x_matrix(&ViewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm); + + if ( ViewDist < ZOOM_MIN_VALUE ) ViewDist = ZOOM_MIN_VALUE; + if ( ViewDist > ZOOM_MAX_VALUE ) ViewDist = ZOOM_MAX_VALUE; + + draw_automap(); + + if ( first_time ) { + first_time = 0; + gr_palette_load( gr_palette ); + } + + t2 = timer_get_fixed_seconds(); + if (pause_game) + FrameTime=t2-t1; + t1 = t2; + } + + //d_free(Edges); + //d_free(DrawingListBright); + + gr_free_canvas(name_canv_left); name_canv_left=NULL; + gr_free_canvas(name_canv_right); name_canv_right=NULL; + + if (must_free_canvas) { + WINDOS( + DDFreeSurface(ddPages[0].lpdds), + d_free(Page.cv_bitmap.bm_data) + ); + } + + mprintf( (0, "Automap memory freed\n" )); + + game_flush_inputs(); + + #if defined(POLY_ACC) && defined(MACINTOSH) + if (PAEnabled) + { + pa_set_context(kGamePlayDrawContextID, NULL); + } + #endif + + if (pause_game) + { + start_time(); + digi_resume_digi_sounds(); + } + +#ifdef WINDOWS + VR_screen_mode = dd_VR_screen_mode_save; +#endif + + Automap_active = 0; +} + +void adjust_segment_limit(int SegmentLimit) +{ + int i,e1; + Edge_info * e; + + mprintf(( 0, "Seglimit: %d\n", SegmentLimit )); + + for (i=0; i<=Highest_edge_index; i++ ) { + e = &Edges[i]; + e->flags |= EF_TOO_FAR; + for (e1=0; e1num_faces; e1++ ) { + if ( Automap_visited[e->segnum[e1]] <= SegmentLimit ) { + e->flags &= (~EF_TOO_FAR); + break; + } + } + } + +} + +void draw_all_edges() +{ + g3s_codes cc; + int i,j,nbright; + ubyte nfacing,nnfacing; + Edge_info *e; + vms_vector *tv1; + fix distance; + fix min_distance = 0x7fffffff; + g3s_point *p1, *p2; + + + nbright=0; + + for (i=0; i<=Highest_edge_index; i++ ) { + //e = &Edges[Edge_used_list[i]]; + e = &Edges[i]; + if (!(e->flags & EF_USED)) continue; + + if ( e->flags & EF_TOO_FAR) continue; + + if (e->flags&EF_FRONTIER) { // A line that is between what we have seen and what we haven't + if ( (!(e->flags&EF_SECRET))&&(e->color==Wall_normal_color)) + continue; // If a line isn't secret and is normal color, then don't draw it + } + + cc=rotate_list(2,e->verts); + distance = Segment_points[e->verts[1]].p3_z; + + if (min_distance>distance ) + min_distance = distance; + + if (!cc.and) { //all off screen? + nfacing = nnfacing = 0; + tv1 = &Vertices[e->verts[0]]; + j = 0; + while( jnum_faces && (nfacing==0 || nnfacing==0) ) { + #ifdef COMPACT_SEGS + vms_vector temp_v; + get_side_normal(&Segments[e->segnum[j]], e->sides[j], 0, &temp_v ); + if (!g3_check_normal_facing( tv1, &temp_v ) ) + #else + if (!g3_check_normal_facing( tv1, &Segments[e->segnum[j]].sides[e->sides[j]].normals[0] ) ) + #endif + nfacing++; + else + nnfacing++; + j++; + } + + if ( nfacing && nnfacing ) { + // a contour line + DrawingListBright[nbright++] = e-Edges; + } else if ( e->flags&(EF_DEFINING|EF_GRATE) ) { + if ( nfacing == 0 ) { + if ( e->flags & EF_NO_FADE ) + gr_setcolor( e->color ); + else + gr_setcolor( gr_fade_table[e->color+256*8] ); + g3_draw_line( &Segment_points[e->verts[0]], &Segment_points[e->verts[1]] ); + } else { + DrawingListBright[nbright++] = e-Edges; + } + } + } + } + +/// mprintf( (0, "Min distance=%.2f, ViewDist=%.2f, Delta=%.2f\n", f2fl(min_distance), f2fl(ViewDist), f2fl(min_distance)- f2fl(ViewDist) )); + + if ( min_distance < 0 ) min_distance = 0; + + // Sort the bright ones using a shell sort + { + int t; + int i, j, incr, v1, v2; + + incr = nbright / 2; + while( incr > 0 ) { + for (i=incr; i=0 ) { + // compare element j and j+incr + v1 = Edges[DrawingListBright[j]].verts[0]; + v2 = Edges[DrawingListBright[j+incr]].verts[0]; + + if (Segment_points[v1].p3_z < Segment_points[v2].p3_z) { + // If not in correct order, them swap 'em + t=DrawingListBright[j+incr]; + DrawingListBright[j+incr]=DrawingListBright[j]; + DrawingListBright[j]=t; + j -= incr; + } + else + break; + } + } + incr = incr / 2; + } + } + + // Draw the bright ones + for (i=0; iverts[0]]; + p2 = &Segment_points[e->verts[1]]; + dist = p1->p3_z - min_distance; + // Make distance be 1.0 to 0.0, where 0.0 is 10 segments away; + if ( dist < 0 ) dist=0; + if ( dist >= Automap_farthest_dist ) continue; + + if ( e->flags & EF_NO_FADE ) { + gr_setcolor( e->color ); + } else { + dist = F1_0 - fixdiv( dist, Automap_farthest_dist ); + color = f2i( dist*31 ); + gr_setcolor( gr_fade_table[e->color+color*256] ); + } + g3_draw_line( p1, p2 ); + } + +} + + +//================================================================== +// +// All routines below here are used to build the Edge list +// +//================================================================== + + +//finds edge, filling in edge_ptr. if found old edge, returns index, else return -1 +static int automap_find_edge(int v0,int v1,Edge_info **edge_ptr) +{ + long vv, evv; + short hash,oldhash; + int ret, ev0, ev1; + + vv = (v1<<16) + v0; + + oldhash = hash = ((v0*5+v1) % Max_edges); + + ret = -1; + + while (ret==-1) { + ev0 = (int)(Edges[hash].verts[0]); + ev1 = (int)(Edges[hash].verts[1]); + evv = (ev1<<16)+ev0; + if (Edges[hash].num_faces == 0 ) ret=0; + else if (evv == vv) ret=1; + else { + if (++hash==Max_edges) hash=0; + if (hash==oldhash) Error("Edge list full!"); + } + } + + *edge_ptr = &Edges[hash]; + + if (ret == 0) + return -1; + else + return hash; + +} + + +void add_one_edge( short va, short vb, ubyte color, ubyte side, short segnum, int hidden, int grate, int no_fade ) { + int found; + Edge_info *e; + short tmp; + + if ( Num_edges >= Max_edges) { + // GET JOHN! (And tell him that his + // MAX_EDGES_FROM_VERTS formula is hosed.) + // If he's not around, save the mine, + // and send him mail so he can look + // at the mine later. Don't modify it. + // This is important if this happens. + Int3(); // LOOK ABOVE!!!!!! + return; + } + + if ( va > vb ) { + tmp = va; + va = vb; + vb = tmp; + } + + found = automap_find_edge(va,vb,&e); + + if (found == -1) { + e->verts[0] = va; + e->verts[1] = vb; + e->color = color; + e->num_faces = 1; + e->flags = EF_USED | EF_DEFINING; // Assume a normal line + e->sides[0] = side; + e->segnum[0] = segnum; + //Edge_used_list[Num_edges] = e-Edges; + if ( (e-Edges) > Highest_edge_index ) + Highest_edge_index = e - Edges; + Num_edges++; + } else { + //Assert(e->num_faces < 8 ); + + if ( color != Wall_normal_color ) + if (color != Wall_revealed_color) + e->color = color; + + if ( e->num_faces < 4 ) { + e->sides[e->num_faces] = side; + e->segnum[e->num_faces] = segnum; + e->num_faces++; + } + } + + if ( grate ) + e->flags |= EF_GRATE; + + if ( hidden ) + e->flags|=EF_SECRET; // Mark this as a hidden edge + if ( no_fade ) + e->flags |= EF_NO_FADE; +} + +void add_one_unknown_edge( short va, short vb ) { + int found; + Edge_info *e; + short tmp; + + if ( va > vb ) { + tmp = va; + va = vb; + vb = tmp; + } + + found = automap_find_edge(va,vb,&e); + if (found != -1) + e->flags|=EF_FRONTIER; // Mark as a border edge +} + +#ifndef _GAMESEQ_H +extern obj_position Player_init[]; +#endif + +void add_segment_edges(segment *seg) +{ + int is_grate, no_fade; + ubyte color; + int sn; + int segnum = seg-Segments; + int hidden_flag; + int ttype,trigger_num; + + for (sn=0;snchildren[sn] == -1) { + color = Wall_normal_color; + } + + switch( Segment2s[segnum].special ) { + case SEGMENT_IS_FUELCEN: + color = BM_XRGB( 29, 27, 13 ); + break; + case SEGMENT_IS_CONTROLCEN: + if (Control_center_present) + color = BM_XRGB( 29, 0, 0 ); + break; + case SEGMENT_IS_ROBOTMAKER: + color = BM_XRGB( 29, 0, 31 ); + break; + } + + if (seg->sides[sn].wall_num > -1) { + + trigger_num = Walls[seg->sides[sn].wall_num].trigger; + ttype = Triggers[trigger_num].type; + if (ttype==TT_SECRET_EXIT) + { + color = BM_XRGB( 29, 0, 31 ); + no_fade=1; + goto Here; + } + + switch( Walls[seg->sides[sn].wall_num].type ) { + case WALL_DOOR: + if (Walls[seg->sides[sn].wall_num].keys == KEY_BLUE) { + no_fade = 1; + color = Wall_door_blue; + //mprintf((0, "Seg %i, side %i has BLUE wall\n", segnum, sn)); + } else if (Walls[seg->sides[sn].wall_num].keys == KEY_GOLD) { + no_fade = 1; + color = Wall_door_gold; + //mprintf((0, "Seg %i, side %i has GOLD wall\n", segnum, sn)); + } else if (Walls[seg->sides[sn].wall_num].keys == KEY_RED) { + no_fade = 1; + color = Wall_door_red; + //mprintf((0, "Seg %i, side %i has RED wall\n", segnum, sn)); + } else if (!(WallAnims[Walls[seg->sides[sn].wall_num].clip_num].flags & WCF_HIDDEN)) { + int connected_seg = seg->children[sn]; + if (connected_seg != -1) { + int connected_side = find_connect_side(seg, &Segments[connected_seg]); + int keytype = Walls[Segments[connected_seg].sides[connected_side].wall_num].keys; + if ((keytype != KEY_BLUE) && (keytype != KEY_GOLD) && (keytype != KEY_RED)) + color = Wall_door_color; + else { + switch (Walls[Segments[connected_seg].sides[connected_side].wall_num].keys) { + case KEY_BLUE: color = Wall_door_blue; no_fade = 1; break; + case KEY_GOLD: color = Wall_door_gold; no_fade = 1; break; + case KEY_RED: color = Wall_door_red; no_fade = 1; break; + default: Error("Inconsistent data. Supposed to be a colored wall, but not blue, gold or red.\n"); + } + //mprintf((0, "Seg %i, side %i has a colored door on the other side.\n", segnum, sn)); + } + + } + } else { + color = Wall_normal_color; + hidden_flag = 1; + //mprintf((0, "Wall at seg:side %i:%i is hidden.\n", seg-Segments, sn)); + } + break; + case WALL_CLOSED: + // Make grates draw properly + if (WALL_IS_DOORWAY(seg,sn) & WID_RENDPAST_FLAG) + is_grate = 1; + else + hidden_flag = 1; + color = Wall_normal_color; + break; + case WALL_BLASTABLE: + // Hostage doors + color = Wall_door_color; + break; + } + } + + if (segnum==Player_init[Player_num].segnum) + color = BM_XRGB(31,0,31); + + if ( color != 255 ) { + // If they have a map powerup, draw unvisited areas in dark blue. + if (Players[Player_num].flags & PLAYER_FLAGS_MAP_ALL && (!Automap_visited[segnum])) + color = Wall_revealed_color; + + + Here: + + get_side_verts(vertex_list,segnum,sn); + add_one_edge( vertex_list[0], vertex_list[1], color, sn, segnum, hidden_flag, 0, no_fade ); + add_one_edge( vertex_list[1], vertex_list[2], color, sn, segnum, hidden_flag, 0, no_fade ); + add_one_edge( vertex_list[2], vertex_list[3], color, sn, segnum, hidden_flag, 0, no_fade ); + add_one_edge( vertex_list[3], vertex_list[0], color, sn, segnum, hidden_flag, 0, no_fade ); + + if ( is_grate ) { + add_one_edge( vertex_list[0], vertex_list[2], color, sn, segnum, hidden_flag, 1, no_fade ); + add_one_edge( vertex_list[1], vertex_list[3], color, sn, segnum, hidden_flag, 1, no_fade ); + } + } + } + +} + + +// Adds all the edges from a segment we haven't visited yet. + +void add_unknown_segment_edges(segment *seg) +{ + int sn; + int segnum = seg-Segments; + + for (sn=0;snchildren[sn] == -1) { + get_side_verts(vertex_list,segnum,sn); + + add_one_unknown_edge( vertex_list[0], vertex_list[1] ); + add_one_unknown_edge( vertex_list[1], vertex_list[2] ); + add_one_unknown_edge( vertex_list[2], vertex_list[3] ); + add_one_unknown_edge( vertex_list[3], vertex_list[0] ); + } + + + } + +} + +void automap_build_edge_list() +{ + int i,e1,e2,s; + Edge_info * e; + + Automap_cheat = 0; + + if ( Players[Player_num].flags & PLAYER_FLAGS_MAP_ALL_CHEAT ) + Automap_cheat = 1; // Damn cheaters... + + // clear edge list + for (i=0; iflags&EF_USED)) continue; + + for (e1=0; e1num_faces; e1++ ) { + for (e2=1; e2num_faces; e2++ ) { + if ( (e1 != e2) && (e->segnum[e1] != e->segnum[e2]) ) { + #ifdef COMPACT_SEGS + vms_vector v1, v2; + get_side_normal(&Segments[e->segnum[e1]], e->sides[e1], 0, &v1 ); + get_side_normal(&Segments[e->segnum[e2]], e->sides[e2], 0, &v2 ); + if ( vm_vec_dot(&v1,&v2) > (F1_0-(F1_0/10)) ) { + #else + if ( vm_vec_dot( &Segments[e->segnum[e1]].sides[e->sides[e1]].normals[0], &Segments[e->segnum[e2]].sides[e->sides[e2]].normals[0] ) > (F1_0-(F1_0/10)) ) { + #endif + e->flags &= (~EF_DEFINING); + break; + } + } + } + if (!(e->flags & EF_DEFINING)) + break; + } + } + + mprintf( (0, "Automap used %d / %d edges\n", Num_edges, Max_edges )); + +} + +char Marker_input [40]; +int Marker_index=0; +ubyte DefiningMarkerMessage=0; +ubyte MarkerBeingDefined; +ubyte LastMarkerDropped; + +void InitMarkerInput () + { + int maxdrop,i; + + //find free marker slot + + if (Game_mode & GM_MULTI) + maxdrop=MAX_DROP_MULTI; + else + maxdrop=MAX_DROP_SINGLE; + + for (i=0;i 0) + Marker_index--; + Marker_input[Marker_index] = 0; + break; + case KEY_ENTER: + strcpy (MarkerMessage[(Player_num*2)+MarkerBeingDefined],Marker_input); + if (Game_mode & GM_MULTI) + strcpy (MarkerOwner[(Player_num*2)+MarkerBeingDefined],Players[Player_num].callsign); + DropMarker(MarkerBeingDefined); + LastMarkerDropped = MarkerBeingDefined; + game_flush_inputs(); + DefiningMarkerMessage = 0; + break; + default: + if ( key > 0 ) + { + int ascii = key_to_ascii(key); + if ((ascii < 255 )) + if (Marker_index < 38 ) + { + Marker_input[Marker_index++] = ascii; + Marker_input[Marker_index] = 0; + } + } + break; + + } + } + + + + diff --git a/main/automap.h b/main/automap.h new file mode 100644 index 00000000..e4d99bcd --- /dev/null +++ b/main/automap.h @@ -0,0 +1,36 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + + +#ifndef _AUTOMAP_H +#define _AUTOMAP_H + +#include "player.h" + +extern void do_automap(int key_code); +extern void automap_clear_visited(); +extern ubyte Automap_visited[MAX_SEGMENTS]; +extern void modex_print_message(int x, int y, char *str); +void DropBuddyMarker(object *objp); + +extern int Automap_active; + +#define NUM_MARKERS 16 +#define MARKER_MESSAGE_LEN 40 + +extern char MarkerMessage[NUM_MARKERS][MARKER_MESSAGE_LEN]; +extern char MarkerOwner[NUM_MARKERS][CALLSIGN_LEN+1]; +extern int MarkerObject[NUM_MARKERS]; + +#endif diff --git a/main/bm.c b/main/bm.c new file mode 100644 index 00000000..bff5642f --- /dev/null +++ b/main/bm.c @@ -0,0 +1,942 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifdef RCS +static char rcsid[] = "$Id: bm.c,v 1.1.1.1 2001-01-19 03:30:01 bradleyb Exp $"; +#endif + +#include +#include +#include + +#include "pstypes.h" +#include "inferno.h" +#include "gr.h" +#include "bm.h" +#include "u_mem.h" +#include "mono.h" +#include "error.h" +#include "object.h" +#include "vclip.h" +#include "effects.h" +#include "polyobj.h" +#include "wall.h" +#include "textures.h" +#include "game.h" +#include "multi.h" +#include "iff.h" +#include "cfile.h" +#include "powerup.h" +#include "sounds.h" +#include "piggy.h" +#include "aistruct.h" +#include "robot.h" +#include "weapon.h" +#include "gauges.h" +#include "player.h" +#include "endlevel.h" +#include "cntrlcen.h" +#include "byteswap.h" + +ubyte Sounds[MAX_SOUNDS]; +ubyte AltSounds[MAX_SOUNDS]; + +#ifdef EDITOR +int Num_total_object_types; +byte ObjType[MAX_OBJTYPE]; +byte ObjId[MAX_OBJTYPE]; +fix ObjStrength[MAX_OBJTYPE]; +#endif + +//for each model, a model number for dying & dead variants, or -1 if none +int Dying_modelnums[MAX_POLYGON_MODELS]; +int Dead_modelnums[MAX_POLYGON_MODELS]; + +//the polygon model number to use for the marker +int Marker_model_num = -1; + +//right now there's only one player ship, but we can have another by +//adding an array and setting the pointer to the active ship. +player_ship only_player_ship,*Player_ship=&only_player_ship; + +//----------------- Miscellaneous bitmap pointers --------------- +int Num_cockpits = 0; +bitmap_index cockpit_bitmap[N_COCKPIT_BITMAPS]; + +//---------------- Variables for wall textures ------------------ +int Num_tmaps; +tmap_info TmapInfo[MAX_TEXTURES]; + +//---------------- Variables for object textures ---------------- + +int First_multi_bitmap_num=-1; + +bitmap_index ObjBitmaps[MAX_OBJ_BITMAPS]; +ushort ObjBitmapPtrs[MAX_OBJ_BITMAPS]; // These point back into ObjBitmaps, since some are used twice. + +#ifdef MACINTOSH +void read_tmap_info(CFILE *fp, int inNumTexturesToRead, int inOffset) +{ + int i; + + for (i = inOffset; i < (inNumTexturesToRead + inOffset); i++) + { + TmapInfo[i].flags = cfile_read_byte(fp); + TmapInfo[i].pad[0] = cfile_read_byte(fp); + TmapInfo[i].pad[1] = cfile_read_byte(fp); + TmapInfo[i].pad[2] = cfile_read_byte(fp); + TmapInfo[i].lighting = cfile_read_fix(fp); + TmapInfo[i].damage = cfile_read_fix(fp); + TmapInfo[i].eclip_num = cfile_read_short(fp); + TmapInfo[i].destroyed = cfile_read_short(fp); + TmapInfo[i].slide_u = cfile_read_short(fp); + TmapInfo[i].slide_v = cfile_read_short(fp); + } +} + +void read_vclip_info(CFILE *fp, int inNumVClipsToRead, int inOffset) +{ + int i, j; + + for (i = inOffset; i < (inNumVClipsToRead + inOffset); i++) + { + Vclip[i].play_time = cfile_read_fix(fp); + Vclip[i].num_frames = cfile_read_int(fp); + Vclip[i].frame_time = cfile_read_fix(fp); + Vclip[i].flags = cfile_read_int(fp); + Vclip[i].sound_num = cfile_read_short(fp); + for (j = 0; j < VCLIP_MAX_FRAMES; j++) + Vclip[i].frames[j].index = cfile_read_short(fp); + Vclip[i].light_value = cfile_read_fix(fp); + } +} + +void read_effect_info(CFILE *fp, int inNumEffectsToRead, int inOffset) +{ + int i, j; + + + for (i = inOffset; i < (inNumEffectsToRead + inOffset); i++) + { + Effects[i].vc.play_time = cfile_read_fix(fp); + Effects[i].vc.num_frames = cfile_read_int(fp); + Effects[i].vc.frame_time = cfile_read_fix(fp); + Effects[i].vc.flags = cfile_read_int(fp); + Effects[i].vc.sound_num = cfile_read_short(fp); + for (j = 0; j < VCLIP_MAX_FRAMES; j++) + Effects[i].vc.frames[j].index = cfile_read_short(fp); + Effects[i].vc.light_value = cfile_read_fix(fp); + Effects[i].time_left = cfile_read_fix(fp); + Effects[i].frame_count = cfile_read_int(fp); + Effects[i].changing_wall_texture = cfile_read_short(fp); + Effects[i].changing_object_texture = cfile_read_short(fp); + Effects[i].flags = cfile_read_int(fp); + Effects[i].crit_clip = cfile_read_int(fp); + Effects[i].dest_bm_num = cfile_read_int(fp); + Effects[i].dest_vclip = cfile_read_int(fp); + Effects[i].dest_eclip = cfile_read_int(fp); + Effects[i].dest_size = cfile_read_fix(fp); + Effects[i].sound_num = cfile_read_int(fp); + Effects[i].segnum = cfile_read_int(fp); + Effects[i].sidenum = cfile_read_int(fp); + } +} + +void read_wallanim_info(CFILE *fp, int inNumWallAnimsToRead, int inOffset) +{ + int i, j; + + for (i = inOffset; i < (inNumWallAnimsToRead + inOffset); i++) + { + WallAnims[i].play_time = cfile_read_fix(fp);; + WallAnims[i].num_frames = cfile_read_short(fp);; + for (j = 0; j < MAX_CLIP_FRAMES; j++) + WallAnims[i].frames[j] = cfile_read_short(fp); + WallAnims[i].open_sound = cfile_read_short(fp); + WallAnims[i].close_sound = cfile_read_short(fp); + WallAnims[i].flags = cfile_read_short(fp); + cfread(WallAnims[i].filename, 13, 1, fp); + WallAnims[i].pad = cfile_read_byte(fp); + } +} + +void read_robot_info(CFILE *fp, int inNumRobotsToRead, int inOffset) +{ + int i, j, k; + + for (i = inOffset; i < (inNumRobotsToRead + inOffset); i++) + { + Robot_info[i].model_num = cfile_read_int(fp); + for (j = 0; j < MAX_GUNS; j++) + cfile_read_vector(&(Robot_info[i].gun_points[j]), fp); + for (j = 0; j < MAX_GUNS; j++) + Robot_info[i].gun_submodels[j] = cfile_read_byte(fp); + + Robot_info[i].exp1_vclip_num = cfile_read_short(fp); + Robot_info[i].exp1_sound_num = cfile_read_short(fp); + + Robot_info[i].exp2_vclip_num = cfile_read_short(fp); + Robot_info[i].exp2_sound_num = cfile_read_short(fp); + + Robot_info[i].weapon_type = cfile_read_byte(fp); + Robot_info[i].weapon_type2 = cfile_read_byte(fp); + Robot_info[i].n_guns = cfile_read_byte(fp); + Robot_info[i].contains_id = cfile_read_byte(fp); + + Robot_info[i].contains_count = cfile_read_byte(fp); + Robot_info[i].contains_prob = cfile_read_byte(fp); + Robot_info[i].contains_type = cfile_read_byte(fp); + Robot_info[i].kamikaze = cfile_read_byte(fp); + + Robot_info[i].score_value = cfile_read_short(fp); + Robot_info[i].badass = cfile_read_byte(fp); + Robot_info[i].energy_drain = cfile_read_byte(fp); + + Robot_info[i].lighting = cfile_read_fix(fp); + Robot_info[i].strength = cfile_read_fix(fp); + + Robot_info[i].mass = cfile_read_fix(fp); + Robot_info[i].drag = cfile_read_fix(fp); + + for (j = 0; j < NDL; j++) + Robot_info[i].field_of_view[j] = cfile_read_fix(fp); + for (j = 0; j < NDL; j++) + Robot_info[i].firing_wait[j] = cfile_read_fix(fp); + for (j = 0; j < NDL; j++) + Robot_info[i].firing_wait2[j] = cfile_read_fix(fp); + for (j = 0; j < NDL; j++) + Robot_info[i].turn_time[j] = cfile_read_fix(fp); + for (j = 0; j < NDL; j++) + Robot_info[i].max_speed[j] = cfile_read_fix(fp); + for (j = 0; j < NDL; j++) + Robot_info[i].circle_distance[j] = cfile_read_fix(fp); + for (j = 0; j < NDL; j++) + cfread(&(Robot_info[i].rapidfire_count[j]), sizeof(byte), 1, fp); + for (j = 0; j < NDL; j++) + cfread(&(Robot_info[i].evade_speed[j]), sizeof(byte), 1, fp); + Robot_info[i].cloak_type = cfile_read_byte(fp); + Robot_info[i].attack_type = cfile_read_byte(fp); + + Robot_info[i].see_sound = cfile_read_byte(fp); + Robot_info[i].attack_sound = cfile_read_byte(fp); + Robot_info[i].claw_sound = cfile_read_byte(fp); + Robot_info[i].taunt_sound = cfile_read_byte(fp); + + Robot_info[i].boss_flag = cfile_read_byte(fp); + Robot_info[i].companion = cfile_read_byte(fp); + Robot_info[i].smart_blobs = cfile_read_byte(fp); + Robot_info[i].energy_blobs = cfile_read_byte(fp); + + Robot_info[i].thief = cfile_read_byte(fp); + Robot_info[i].pursuit = cfile_read_byte(fp); + Robot_info[i].lightcast = cfile_read_byte(fp); + Robot_info[i].death_roll = cfile_read_byte(fp); + + Robot_info[i].flags = cfile_read_byte(fp); + Robot_info[i].pad[0] = cfile_read_byte(fp); + Robot_info[i].pad[1] = cfile_read_byte(fp); + Robot_info[i].pad[2] = cfile_read_byte(fp); + + Robot_info[i].deathroll_sound = cfile_read_byte(fp); + Robot_info[i].glow = cfile_read_byte(fp); + Robot_info[i].behavior = cfile_read_byte(fp); + Robot_info[i].aim = cfile_read_byte(fp); + + for (j = 0; j < MAX_GUNS + 1; j++) { + for (k = 0; k < N_ANIM_STATES; k++) { + Robot_info[i].anim_states[j][k].n_joints = cfile_read_short(fp); + Robot_info[i].anim_states[j][k].offset = cfile_read_short(fp); + } + } + + Robot_info[i].always_0xabcd = cfile_read_int(fp); + } +} + +void read_robot_joint_info(CFILE *fp, int inNumRobotJointsToRead, int inOffset) +{ + int i; + + for (i = inOffset; i < (inNumRobotJointsToRead + inOffset); i++) + { + Robot_joints[i].jointnum = cfile_read_short(fp); + cfile_read_angvec(&(Robot_joints[i].angles), fp); + } +} + +void read_weapon_info(CFILE *fp, int inNumWeaponsToRead, int inOffset) +{ + int i, j; + + for (i = inOffset; i < (inNumWeaponsToRead + inOffset); i++) + { + Weapon_info[i].render_type = cfile_read_byte(fp); + Weapon_info[i].persistent = cfile_read_byte(fp); + Weapon_info[i].model_num = cfile_read_short(fp); + Weapon_info[i].model_num_inner = cfile_read_short(fp); + + Weapon_info[i].flash_vclip = cfile_read_byte(fp); + Weapon_info[i].robot_hit_vclip = cfile_read_byte(fp); + Weapon_info[i].flash_sound = cfile_read_short(fp); + + Weapon_info[i].wall_hit_vclip = cfile_read_byte(fp); + Weapon_info[i].fire_count = cfile_read_byte(fp); + Weapon_info[i].robot_hit_sound = cfile_read_short(fp); + + Weapon_info[i].ammo_usage = cfile_read_byte(fp); + Weapon_info[i].weapon_vclip = cfile_read_byte(fp); + Weapon_info[i].wall_hit_sound = cfile_read_short(fp); + + Weapon_info[i].destroyable = cfile_read_byte(fp); + Weapon_info[i].matter = cfile_read_byte(fp); + Weapon_info[i].bounce = cfile_read_byte(fp); + Weapon_info[i].homing_flag = cfile_read_byte(fp); + + Weapon_info[i].speedvar = cfile_read_byte(fp); + Weapon_info[i].flags = cfile_read_byte(fp); + Weapon_info[i].flash = cfile_read_byte(fp); + Weapon_info[i].afterburner_size = cfile_read_byte(fp); + + Weapon_info[i].children = cfile_read_byte(fp); + + Weapon_info[i].energy_usage = cfile_read_fix(fp); + Weapon_info[i].fire_wait = cfile_read_fix(fp); + + Weapon_info[i].multi_damage_scale = cfile_read_fix(fp); + + Weapon_info[i].bitmap.index = cfile_read_short(fp); // bitmap_index = short + + Weapon_info[i].blob_size = cfile_read_fix(fp); + Weapon_info[i].flash_size = cfile_read_fix(fp); + Weapon_info[i].impact_size = cfile_read_fix(fp); + for (j = 0; j < NDL; j++) + Weapon_info[i].strength[j] = cfile_read_fix(fp); + for (j = 0; j < NDL; j++) + Weapon_info[i].speed[j] = cfile_read_fix(fp); + Weapon_info[i].mass = cfile_read_fix(fp); + Weapon_info[i].drag = cfile_read_fix(fp); + Weapon_info[i].thrust = cfile_read_fix(fp); + Weapon_info[i].po_len_to_width_ratio = cfile_read_fix(fp); + Weapon_info[i].light = cfile_read_fix(fp); + Weapon_info[i].lifetime = cfile_read_fix(fp); + Weapon_info[i].damage_radius = cfile_read_fix(fp); + Weapon_info[i].picture.index = cfile_read_short(fp); // bitmap_index is a short + Weapon_info[i].hires_picture.index = cfile_read_short(fp); // bitmap_index is a short + } +} + +void read_powerup_info(CFILE *fp, int inNumPowerupsToRead, int inOffset) +{ + int i; + + for (i = inOffset; i < (inNumPowerupsToRead + inOffset); i++) + { + Powerup_info[i].vclip_num = cfile_read_int(fp); + Powerup_info[i].hit_sound = cfile_read_int(fp); + Powerup_info[i].size = cfile_read_fix(fp); + Powerup_info[i].light = cfile_read_fix(fp); + } +} + +void read_polygon_models(CFILE *fp, int inNumPolygonModelsToRead, int inOffset) +{ + int i, j; + + for (i = inOffset; i < (inNumPolygonModelsToRead + inOffset); i++) + { + Polygon_models[i].n_models = cfile_read_int(fp); + Polygon_models[i].model_data_size = cfile_read_int(fp); + Polygon_models[i].model_data = (ubyte *)read_int_swap(fp); + for (j = 0; j < MAX_SUBMODELS; j++) + Polygon_models[i].submodel_ptrs[j] = cfile_read_int(fp); + for (j = 0; j < MAX_SUBMODELS; j++) + cfile_read_vector(&(Polygon_models[i].submodel_offsets), fp); + for (j = 0; j < MAX_SUBMODELS; j++) + cfile_read_vector(&(Polygon_models[i].submodel_norms), fp); + for (j = 0; j < MAX_SUBMODELS; j++) + cfile_read_vector(&(Polygon_models[i].submodel_pnts), fp); + for (j = 0; j < MAX_SUBMODELS; j++) + Polygon_models[i].submodel_rads[j] = cfile_read_fix(fp); + for (j = 0; j < MAX_SUBMODELS; j++) + Polygon_models[i].submodel_parents[j] = cfile_read_byte(fp); + for (j = 0; j < MAX_SUBMODELS; j++) + cfile_read_vector(&(Polygon_models[i].submodel_mins), fp); + for (j = 0; j < MAX_SUBMODELS; j++) + cfile_read_vector(&(Polygon_models[i].submodel_maxs), fp); + cfile_read_vector(&(Polygon_models[i].mins), fp); + cfile_read_vector(&(Polygon_models[i].maxs), fp); + Polygon_models[i].rad = cfile_read_fix(fp); + Polygon_models[i].n_textures = cfile_read_byte(fp); + Polygon_models[i].first_texture = cfile_read_short(fp); + Polygon_models[i].simpler_model = cfile_read_byte(fp); + } +} + +void read_player_ship(CFILE *fp) +{ + int i; + + only_player_ship.model_num = cfile_read_int(fp); + only_player_ship.expl_vclip_num = cfile_read_int(fp); + only_player_ship.mass = cfile_read_fix(fp); + only_player_ship.drag = cfile_read_fix(fp); + only_player_ship.max_thrust = cfile_read_fix(fp); + only_player_ship.reverse_thrust = cfile_read_fix(fp); + only_player_ship.brakes = cfile_read_fix(fp); + only_player_ship.wiggle = cfile_read_fix(fp); + only_player_ship.max_rotthrust = cfile_read_fix(fp); + for (i = 0; i < N_PLAYER_GUNS; i++) + cfile_read_vector(&(only_player_ship.gun_points[i]), fp); +} + +void read_reactor_info(CFILE *fp, int inNumReactorsToRead, int inOffset) +{ + int i, j; + + for (i = inOffset; i < (inNumReactorsToRead + inOffset); i++) + { + Reactors[i].model_num = cfile_read_int(fp); + Reactors[i].n_guns = cfile_read_int(fp); + for (j = 0; j < MAX_CONTROLCEN_GUNS; j++) + cfile_read_vector(&(Reactors[i].gun_points), fp); + for (j = 0; j < MAX_CONTROLCEN_GUNS; j++) + cfile_read_vector(&(Reactors[i].gun_dirs), fp); + } +} + +#ifdef SHAREWARE +extern int exit_modelnum,destroyed_exit_modelnum, Num_bitmap_files; +int N_ObjBitmaps, extra_bitmap_num; + +bitmap_index exitmodel_bm_load_sub( char * filename ) +{ + bitmap_index bitmap_num; + grs_bitmap * new; + ubyte newpal[256*3]; + int i, iff_error; //reference parm to avoid warning message + + bitmap_num.index = 0; + + MALLOC( new, grs_bitmap, 1 ); + iff_error = iff_read_bitmap(filename,new,BM_LINEAR,newpal); + new->bm_handle=0; + if (iff_error != IFF_NO_ERROR) { + Error("Error loading exit model bitmap <%s> - IFF error: %s",filename,iff_errormsg(iff_error)); + } + + if ( iff_has_transparency ) + gr_remap_bitmap_good( new, newpal, iff_transparent_color, 254 ); + else + gr_remap_bitmap_good( new, newpal, -1, 254 ); + + new->avg_color = 0; //compute_average_pixel(new); + + bitmap_num.index = extra_bitmap_num; + + GameBitmaps[extra_bitmap_num++] = *new; + + d_free( new ); + return bitmap_num; +} + +grs_bitmap *load_exit_model_bitmap(char *name) +{ + Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS); + + { + ObjBitmaps[N_ObjBitmaps] = exitmodel_bm_load_sub(name); + if (GameBitmaps[ObjBitmaps[N_ObjBitmaps].index].bm_w!=64 || GameBitmaps[ObjBitmaps[N_ObjBitmaps].index].bm_h!=64) + Error("Bitmap <%s> is not 64x64",name); + ObjBitmapPtrs[N_ObjBitmaps] = N_ObjBitmaps; + N_ObjBitmaps++; + Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS); + return &GameBitmaps[ObjBitmaps[N_ObjBitmaps-1].index]; + } +} + +void load_exit_models() +{ + CFILE *exit_hamfile; + int i, j; + ubyte pal[768]; + int start_num; + + start_num = N_ObjBitmaps; + extra_bitmap_num = Num_bitmap_files; + load_exit_model_bitmap("steel1.bbm"); + load_exit_model_bitmap("rbot061.bbm"); + load_exit_model_bitmap("rbot062.bbm"); + + load_exit_model_bitmap("steel1.bbm"); + load_exit_model_bitmap("rbot061.bbm"); + load_exit_model_bitmap("rbot063.bbm"); + + exit_hamfile = cfopen(":Data:exit.ham","rb"); + + exit_modelnum = N_polygon_models++; + destroyed_exit_modelnum = N_polygon_models++; + + #ifndef MACINTOSH + cfread( &Polygon_models[exit_modelnum], sizeof(polymodel), 1, exit_hamfile ); + cfread( &Polygon_models[destroyed_exit_modelnum], sizeof(polymodel), 1, exit_hamfile ); + #else + for (i = exit_modelnum; i <= destroyed_exit_modelnum; i++) { + Polygon_models[i].n_models = cfile_read_int(exit_hamfile); + Polygon_models[i].model_data_size = cfile_read_int(exit_hamfile); + Polygon_models[i].model_data = (ubyte *)read_int_swap(exit_hamfile); + for (j = 0; j < MAX_SUBMODELS; j++) + Polygon_models[i].submodel_ptrs[j] = cfile_read_int(exit_hamfile); + for (j = 0; j < MAX_SUBMODELS; j++) + cfile_read_vector(&(Polygon_models[i].submodel_offsets), exit_hamfile); + for (j = 0; j < MAX_SUBMODELS; j++) + cfile_read_vector(&(Polygon_models[i].submodel_norms), exit_hamfile); + for (j = 0; j < MAX_SUBMODELS; j++) + cfile_read_vector(&(Polygon_models[i].submodel_pnts), exit_hamfile); + for (j = 0; j < MAX_SUBMODELS; j++) + Polygon_models[i].submodel_rads[j] = cfile_read_fix(exit_hamfile); + for (j = 0; j < MAX_SUBMODELS; j++) + Polygon_models[i].submodel_parents[j] = cfile_read_byte(exit_hamfile); + for (j = 0; j < MAX_SUBMODELS; j++) + cfile_read_vector(&(Polygon_models[i].submodel_mins), exit_hamfile); + for (j = 0; j < MAX_SUBMODELS; j++) + cfile_read_vector(&(Polygon_models[i].submodel_maxs), exit_hamfile); + cfile_read_vector(&(Polygon_models[i].mins), exit_hamfile); + cfile_read_vector(&(Polygon_models[i].maxs), exit_hamfile); + Polygon_models[i].rad = cfile_read_fix(exit_hamfile); + Polygon_models[i].n_textures = cfile_read_byte(exit_hamfile); + Polygon_models[i].first_texture = cfile_read_short(exit_hamfile); + Polygon_models[i].simpler_model = cfile_read_byte(exit_hamfile); + } + Polygon_models[exit_modelnum].first_texture = start_num; + Polygon_models[destroyed_exit_modelnum].first_texture = start_num+3; + #endif + + Polygon_models[exit_modelnum].model_data = d_malloc(Polygon_models[exit_modelnum].model_data_size); + Assert( Polygon_models[exit_modelnum].model_data != NULL ); + cfread( Polygon_models[exit_modelnum].model_data, sizeof(ubyte), Polygon_models[exit_modelnum].model_data_size, exit_hamfile ); + #ifdef MACINTOSH + swap_polygon_model_data(Polygon_models[exit_modelnum].model_data); + #endif + g3_init_polygon_model(Polygon_models[exit_modelnum].model_data); + + Polygon_models[destroyed_exit_modelnum].model_data = d_malloc(Polygon_models[destroyed_exit_modelnum].model_data_size); + Assert( Polygon_models[destroyed_exit_modelnum].model_data != NULL ); + cfread( Polygon_models[destroyed_exit_modelnum].model_data, sizeof(ubyte), Polygon_models[destroyed_exit_modelnum].model_data_size, exit_hamfile ); + #ifdef MACINTOSH + swap_polygon_model_data(Polygon_models[destroyed_exit_modelnum].model_data); + #endif + g3_init_polygon_model(Polygon_models[destroyed_exit_modelnum].model_data); + + cfclose(exit_hamfile); + +} +#endif // SHAREWARE + +#endif // MACINTOSH + +//----------------------------------------------------------------- +// Read data from piggy. +// This is called when the editor is OUT. +// If editor is in, bm_init_use_table() is called. +int bm_init() +{ + init_polygon_models(); + if (! piggy_init()) // This calls bm_read_all + Error("Cannot open pig and/or ham file"); + + piggy_read_sounds(); + + #ifdef SHAREWARE + init_endlevel(); //this is in bm_init_use_tbl(), so I gues it goes here + #endif + + return 0; +} + +void bm_read_all(CFILE * fp) +{ + int i,t; + + NumTextures = cfile_read_int(fp); +#ifndef MACINTOSH + cfread( Textures, sizeof(bitmap_index), NumTextures, fp ); + cfread( TmapInfo, sizeof(tmap_info), NumTextures, fp ); +#else + for (i = 0; i < NumTextures; i++) + Textures[i].index = cfile_read_short(fp); + read_tmap_info(fp, NumTextures, 0); +#endif + + t = cfile_read_int(fp); + cfread( Sounds, sizeof(ubyte), t, fp ); + cfread( AltSounds, sizeof(ubyte), t, fp ); + + Num_vclips = cfile_read_int(fp); +#ifndef MACINTOSH + cfread( Vclip, sizeof(vclip), Num_vclips, fp ); +#else + read_vclip_info(fp, Num_vclips, 0); +#endif + + Num_effects = cfile_read_int(fp); +#ifndef MACINTOSH + cfread( Effects, sizeof(eclip), Num_effects, fp ); +#else + read_effect_info(fp, Num_effects, 0); +#endif + + Num_wall_anims = cfile_read_int(fp); +#ifndef MACINTOSH + cfread( WallAnims, sizeof(wclip), Num_wall_anims, fp ); +#else + read_wallanim_info(fp, Num_wall_anims, 0); +#endif + + N_robot_types = cfile_read_int(fp); +#ifndef MACINTOSH + cfread( Robot_info, sizeof(robot_info), N_robot_types, fp ); +#else + read_robot_info(fp, N_robot_types, 0); +#endif + N_robot_joints = cfile_read_int(fp); +#ifndef MACINTOSH + cfread( Robot_joints, sizeof(jointpos), N_robot_joints, fp ); +#else + read_robot_joint_info(fp, N_robot_joints, 0); +#endif + + N_weapon_types = cfile_read_int(fp); +#ifndef MACINTOSH + cfread( Weapon_info, sizeof(weapon_info), N_weapon_types, fp ); +#else + read_weapon_info(fp, N_weapon_types, 0); +#endif + + N_powerup_types = cfile_read_int(fp); +#ifndef MACINTOSH + cfread( Powerup_info, sizeof(powerup_type_info), N_powerup_types, fp ); +#else + read_powerup_info(fp, N_powerup_types, 0); +#endif + + N_polygon_models = cfile_read_int(fp); +#ifndef MACINTOSH + cfread( Polygon_models, sizeof(polymodel), N_polygon_models, fp ); +#else + read_polygon_models(fp, N_polygon_models, 0); +#endif + + for (i=0; i= MAX_WEAPON_TYPES) + Error("Too many weapons (%d) in <%s>. Max is %d.",t,fname,MAX_WEAPON_TYPES-N_D2_WEAPON_TYPES); + #ifdef MACINTOSH + read_weapon_info(fp, t, N_D2_WEAPON_TYPES); + #else + cfread( &Weapon_info[N_D2_WEAPON_TYPES], sizeof(weapon_info), t, fp ); + #endif + + //now read robot info + + t = cfile_read_int(fp); + N_robot_types = N_D2_ROBOT_TYPES+t; + if (N_robot_types >= MAX_ROBOT_TYPES) + Error("Too many robots (%d) in <%s>. Max is %d.",t,fname,MAX_ROBOT_TYPES-N_D2_ROBOT_TYPES); + #ifdef MACINTOSH + read_robot_info(fp, t, N_D2_ROBOT_TYPES); + #else + cfread( &Robot_info[N_D2_ROBOT_TYPES], sizeof(robot_info), t, fp ); + #endif + + t = cfile_read_int(fp); + N_robot_joints = N_D2_ROBOT_JOINTS+t; + if (N_robot_joints >= MAX_ROBOT_JOINTS) + Error("Too many robot joints (%d) in <%s>. Max is %d.",t,fname,MAX_ROBOT_JOINTS-N_D2_ROBOT_JOINTS); + #ifdef MACINTOSH + read_robot_joint_info(fp, t, N_D2_ROBOT_JOINTS); + #else + cfread( &Robot_joints[N_D2_ROBOT_JOINTS], sizeof(jointpos), t, fp ); + #endif + + t = cfile_read_int(fp); + N_polygon_models = N_D2_POLYGON_MODELS+t; + if (N_polygon_models >= MAX_POLYGON_MODELS) + Error("Too many polygon models (%d) in <%s>. Max is %d.",t,fname,MAX_POLYGON_MODELS-N_D2_POLYGON_MODELS); + #ifdef MACINTOSH + read_polygon_models(fp, t, N_D2_POLYGON_MODELS); + #else + cfread( &Polygon_models[N_D2_POLYGON_MODELS], sizeof(polymodel), t, fp ); + #endif + + for (i=N_D2_POLYGON_MODELS; i= MAX_OBJ_BITMAPS) + Error("Too many object bitmaps (%d) in <%s>. Max is %d.",t,fname,MAX_OBJ_BITMAPS-N_D2_OBJBITMAPS); + cfread( &ObjBitmaps[N_D2_OBJBITMAPS], sizeof(bitmap_index), t, fp ); + #ifdef MACINTOSH + for (i = N_D2_OBJBITMAPS; i < (N_D2_OBJBITMAPS + t); i++) + { + ObjBitmaps[i].index = SWAPSHORT(ObjBitmaps[i].index); + } + #endif + + t = cfile_read_int(fp); + if (N_D2_OBJBITMAPPTRS+t >= MAX_OBJ_BITMAPS) + Error("Too many object bitmap pointers (%d) in <%s>. Max is %d.",t,fname,MAX_OBJ_BITMAPS-N_D2_OBJBITMAPPTRS); + cfread( &ObjBitmapPtrs[N_D2_OBJBITMAPPTRS], sizeof(ushort), t, fp ); + #ifdef MACINTOSH + for (i = N_D2_OBJBITMAPPTRS; i < (N_D2_OBJBITMAPPTRS + t); i++) + { + ObjBitmapPtrs[i] = SWAPSHORT(ObjBitmapPtrs[i]); + } + #endif + + cfclose(fp); +} + +extern void change_filename_extension( char *dest, char *src, char *new_ext ); + +int Robot_replacements_loaded = 0; + +void load_robot_replacements(char *level_name) +{ + CFILE *fp; + int t,i,j; + char ifile_name[FILENAME_LEN]; + + change_filename_extension(ifile_name, level_name, ".HXM" ); + + fp = cfopen(ifile_name,"rb"); + + if (!fp) //no robot replacement file + return; + + t = cfile_read_int(fp); //read id "HXM!" + if (t!= 0x21584d48) + Error("ID of HXM! file incorrect"); + + t = cfile_read_int(fp); //read version + if (t<1) + Error("HXM! version too old (%d)",t); + + t = cfile_read_int(fp); //read number of robots + for (j=0;j=N_robot_types) + Error("Robots number (%d) out of range in (%s). Range = [0..%d].",i,level_name,N_robot_types-1); + #ifdef MACINTOSH + read_robot_info(fp, 1, i); + #else + cfread( &Robot_info[i], sizeof(robot_info), 1, fp ); + #endif + } + + t = cfile_read_int(fp); //read number of joints + for (j=0;j=N_robot_joints) + Error("Robots joint (%d) out of range in (%s). Range = [0..%d].",i,level_name,N_robot_joints-1); + #ifdef MACINTOSH + read_robot_joint_info(fp, 1, i); + #else + cfread( &Robot_joints[i], sizeof(jointpos), 1, fp ); + #endif + } + + t = cfile_read_int(fp); //read number of polygon models + for (j=0;j=N_polygon_models) + Error("Polygon model (%d) out of range in (%s). Range = [0..%d].",i,level_name,N_polygon_models-1); + + #ifdef MACINTOSH + read_polygon_models(fp, 1, i); + #else + cfread( &Polygon_models[i], sizeof(polymodel), 1, fp ); + #endif + + d_free(Polygon_models[i].model_data); + Polygon_models[i].model_data = d_malloc(Polygon_models[i].model_data_size); + Assert( Polygon_models[i].model_data != NULL ); + + cfread( Polygon_models[i].model_data, sizeof(ubyte), Polygon_models[i].model_data_size, fp ); + #ifdef MACINTOSH + swap_polygon_model_data(Polygon_models[i].model_data); + #endif + g3_init_polygon_model(Polygon_models[i].model_data); + + Dying_modelnums[i] = cfile_read_int(fp); + Dead_modelnums[i] = cfile_read_int(fp); + } + + t = cfile_read_int(fp); //read number of objbitmaps + for (j=0;j=MAX_OBJ_BITMAPS) + Error("Object bitmap number (%d) out of range in (%s). Range = [0..%d].",i,level_name,MAX_OBJ_BITMAPS-1); + ObjBitmaps[i].index = cfile_read_short(fp); + } + + t = cfile_read_int(fp); //read number of objbitmapptrs + for (j=0;j=MAX_OBJ_BITMAPS) + Error("Object bitmap pointer (%d) out of range in (%s). Range = [0..%d].",i,level_name,MAX_OBJ_BITMAPS-1); + ObjBitmapPtrs[i] = cfile_read_short(fp); + } + + cfclose(fp); +} diff --git a/main/bm.h b/main/bm.h new file mode 100644 index 00000000..7801b749 --- /dev/null +++ b/main/bm.h @@ -0,0 +1,100 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifndef _BM_H +#define _BM_H + +#include "gr.h" +#include "piggy.h" + +#define MAX_TEXTURES 1200 + +//tmapinfo flags +#define TMI_VOLATILE 1 //this material blows up when hit +#define TMI_WATER 2 //this material is water +#define TMI_FORCE_FIELD 4 //this is force field - flares don't stick +#define TMI_GOAL_BLUE 8 //this is used to remap the blue goal +#define TMI_GOAL_RED 16 //this is used to remap the red goal +#define TMI_GOAL_HOARD 32 //this is used to remap the goals + +typedef struct { + ubyte flags; //values defined above + ubyte pad[3]; //keep alignment + fix lighting; //how much light this casts + fix damage; //how much damage being against this does (for lava) + short eclip_num; //the eclip that changes this, or -1 + short destroyed; //bitmap to show when destroyed, or -1 + short slide_u,slide_v; //slide rates of texture, stored in 8:8 fix + #ifdef EDITOR + char filename[13]; //used by editor to remap textures + char pad2[3]; + #endif +} __pack__ tmap_info; + +extern int Num_object_types; + +#define N_COCKPIT_BITMAPS 6 +extern int Num_cockpits; +extern bitmap_index cockpit_bitmap[N_COCKPIT_BITMAPS]; + +extern int Num_tmaps; +#ifdef EDITOR +extern int TmapList[MAX_TEXTURES]; +#endif + +extern tmap_info TmapInfo[MAX_TEXTURES]; + +//for each model, a model number for dying & dead variants, or -1 if none +extern int Dying_modelnums[]; +extern int Dead_modelnums[]; + +//the model number of the marker object +extern int Marker_model_num; + +// Initializes the palette, bitmap system... +int bm_init(); +void bm_close(); + +// Initializes the Texture[] array of bmd_bitmap structures. +void init_textures(); + +#define OL_ROBOT 1 +#define OL_HOSTAGE 2 +#define OL_POWERUP 3 +#define OL_CONTROL_CENTER 4 +#define OL_PLAYER 5 +#define OL_CLUTTER 6 //some sort of misc object +#define OL_EXIT 7 //the exit model for external scenes +#define OL_WEAPON 8 //a weapon that can be placed + +#define MAX_OBJTYPE 140 + +extern int Num_total_object_types; // Total number of object types, including robots, hostages, powerups, control centers, faces +extern byte ObjType[MAX_OBJTYPE]; // Type of an object, such as Robot, eg if ObjType[11] == OL_ROBOT, then object #11 is a robot +extern byte ObjId[MAX_OBJTYPE]; // ID of a robot, within its class, eg if ObjType[11] == 3, then object #11 is the third robot +extern fix ObjStrength[MAX_OBJTYPE]; // initial strength of each object + +#if defined(MACINTOSH) && defined(SHAREWARE) +#define MAX_OBJ_BITMAPS 610 +#else +#define MAX_OBJ_BITMAPS 600 +#endif +extern bitmap_index ObjBitmaps[MAX_OBJ_BITMAPS]; +extern ushort ObjBitmapPtrs[MAX_OBJ_BITMAPS]; +extern int First_multi_bitmap_num; + +// Initializes all bitmaps from BITMAPS.TBL file. +int bm_init_use_tbl(void); + +#endif + diff --git a/main/bmread.c b/main/bmread.c new file mode 100644 index 00000000..60885268 --- /dev/null +++ b/main/bmread.c @@ -0,0 +1,2468 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + +#ifdef RCS +char bmread_rcsid[] = "$Id: bmread.c,v 1.1.1.1 2001-01-19 03:30:01 bradleyb Exp $"; +#endif + +#include + +#ifdef EDITOR + + +#include +#include +#include +#include +#include + +#include "pstypes.h" +#include "inferno.h" +#include "gr.h" +#include "bm.h" +#include "gamepal.h" +#include "mem.h" +#include "mono.h" +#include "error.h" +#include "object.h" +#include "vclip.h" +#include "effects.h" +#include "polyobj.h" +#include "wall.h" +#include "textures.h" +#include "game.h" +#include "multi.h" + +#include "iff.h" +#include "cfile.h" + +#include "hostage.h" +#include "powerup.h" +#include "laser.h" +#include "sounds.h" +#include "piggy.h" +#include "aistruct.h" +#include "robot.h" +#include "weapon.h" +#include "gauges.h" +#include "player.h" +#include "endlevel.h" +#include "cntrlcen.h" +#include "compbit.h" +#include "args.h" + + +#include "editor\texpage.h" + +#define BM_NONE -1 +#define BM_COCKPIT 0 +#define BM_TEXTURES 2 +#define BM_UNUSED 3 +#define BM_VCLIP 4 +#define BM_EFFECTS 5 +#define BM_ECLIP 6 +#define BM_WEAPON 7 +#define BM_DEMO 8 +#define BM_ROBOTEX 9 +#define BM_WALL_ANIMS 12 +#define BM_WCLIP 13 +#define BM_ROBOT 14 +#define BM_GAUGES 20 +#define BM_GAUGES_HIRES 21 + +#define MAX_BITMAPS_PER_BRUSH 30 + +extern player_ship only_player_ship; // In bm.c + +short N_ObjBitmaps=0; +short N_ObjBitmapPtrs=0; +static int Num_robot_ais = 0; +int TmapList[MAX_TEXTURES]; +char Powerup_names[MAX_POWERUP_TYPES][POWERUP_NAME_LENGTH]; +char Robot_names[MAX_ROBOT_TYPES][ROBOT_NAME_LENGTH]; + +//---------------- Internal variables --------------------------- +static int Registered_only = 0; // Gets set by ! in column 1. +static int SuperX = -1; +static int Installed=0; +static char *arg; +static short tmap_count = 0; +static short texture_count = 0; +static short clip_count = 0; +static short clip_num; +static short sound_num; +static short frames; +static float time; +static int hit_sound = -1; +static byte bm_flag = BM_NONE; +static int abm_flag = 0; +static int rod_flag = 0; +static short wall_open_sound, wall_close_sound,wall_explodes,wall_blastable, wall_hidden; +float vlighting=0; +static int obj_eclip; +static char *dest_bm; //clip number to play when destroyed +static int dest_vclip; //what vclip to play when exploding +static int dest_eclip; //what eclip to play when exploding +static fix dest_size; //3d size of explosion +static int crit_clip; //clip number to play when destroyed +static int crit_flag; //flag if this is a destroyed eclip +static int tmap1_flag; //flag if this is used as tmap_num (not tmap_num2) +static int num_sounds=0; + +int linenum; //line int table currently being parsed + +//------------------- Useful macros and variables --------------- +#define REMOVE_EOL(s) remove_char((s),'\n') +#define REMOVE_COMMENTS(s) remove_char((s),';') +#define REMOVE_DOTS(s) remove_char((s),'.') + +#define IFTOK(str) if (!strcmp(arg, str)) +char *space = { " \t" }; +//--unused-- char *equal = { "=" }; +char *equal_space = { " \t=" }; + + +// For the sake of LINT, defining prototypes to module's functions +void bm_read_robot_ai(void); +void bm_read_powerup(int unused_flag); +void bm_read_hostage(void); +void bm_read_robot(void); +void bm_read_weapon(int unused_flag); +void bm_read_reactor(void); +void bm_read_exitmodel(void); +void bm_read_player_ship(void); +void bm_read_some_file(void); +void bm_read_sound(void); +void verify_textures(void); + + +//---------------------------------------------------------------------- +void remove_char( char * s, char c ) +{ + char *p; + p = strchr(s,c); + if (p) *p = '\0'; +} + +//--------------------------------------------------------------- +int compute_average_pixel(grs_bitmap *new) +{ + int row, column, color; + char *pptr; + int total_red, total_green, total_blue; + + pptr = (char *)new->bm_data; + + total_red = 0; + total_green = 0; + total_blue = 0; + + for (row=0; rowbm_h; row++) + for (column=0; columnbm_w; column++) { + color = *pptr++; + total_red += gr_palette[color*3]; + total_green += gr_palette[color*3+1]; + total_blue += gr_palette[color*3+2]; + } + + total_red /= (new->bm_h * new->bm_w); + total_green /= (new->bm_h * new->bm_w); + total_blue /= (new->bm_h * new->bm_w); + + return BM_XRGB(total_red/2, total_green/2, total_blue/2); +} + +//--------------------------------------------------------------- +// Loads a bitmap from either the piggy file, a r64 file, or a +// whatever extension is passed. + +bitmap_index bm_load_sub( char * filename ) +{ + bitmap_index bitmap_num; + grs_bitmap * new; + ubyte newpal[256*3]; + int iff_error; //reference parm to avoid warning message + char fname[20]; + + bitmap_num.index = 0; + +#ifdef SHAREWARE + if (Registered_only) { + //mprintf( 0, "Skipping registered-only bitmap '%s'\n", filename ); + return bitmap_num; + } +#endif + + _splitpath( filename, NULL, NULL, fname, NULL ); + + bitmap_num=piggy_find_bitmap( fname ); + if (bitmap_num.index) { + //mprintf(( 0, "Found bitmap '%s' in pig!\n", fname )); + return bitmap_num; + } + + MALLOC( new, grs_bitmap, 1 ); + iff_error = iff_read_bitmap(filename,new,BM_LINEAR,newpal); + new->bm_handle=0; + if (iff_error != IFF_NO_ERROR) { + mprintf((1, "File %s - IFF error: %s",filename,iff_errormsg(iff_error))); + Error("File <%s> - IFF error: %s, line %d",filename,iff_errormsg(iff_error),linenum); + } + + if ( iff_has_transparency ) + gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX ); + else + gr_remap_bitmap_good( new, newpal, -1, SuperX ); + + new->avg_color = compute_average_pixel(new); + + // -- mprintf((0, "N" )); + bitmap_num = piggy_register_bitmap( new, fname, 0 ); + d_free( new ); + return bitmap_num; +} + +extern grs_bitmap bogus_bitmap; +extern ubyte bogus_bitmap_initialized; +extern digi_sound bogus_sound; + +void ab_load( char * filename, bitmap_index bmp[], int *nframes ) +{ + grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH]; + bitmap_index bi; + int i; + int iff_error; //reference parm to avoid warning message + ubyte newpal[768]; + char fname[20]; + char tempname[20]; + +#ifdef SHAREWARE + if (Registered_only) { + Assert( bogus_bitmap_initialized != 0 ); + mprintf(( 0, "Skipping registered-only animation '%s'\n", filename )); + bmp[0].index = 0; //index of bogus bitmap==0 (I think) //&bogus_bitmap; + *nframes = 1; + return; + } +#endif + + + _splitpath( filename, NULL, NULL, fname, NULL ); + + for (i=0; i - IFF error: %s, line %d",filename,iff_errormsg(iff_error),linenum); + } + + for (i=0;i< *nframes; i++) { + bitmap_index new_bmp; + sprintf( tempname, "%s#%d", fname, i ); + if ( iff_has_transparency ) + gr_remap_bitmap_good( bm[i], newpal, iff_transparent_color, SuperX ); + else + gr_remap_bitmap_good( bm[i], newpal, -1, SuperX ); + + bm[i]->avg_color = compute_average_pixel(bm[i]); + + new_bmp = piggy_register_bitmap( bm[i], tempname, 0 ); + d_free( bm[i] ); + bmp[i] = new_bmp; + if (!i) + mprintf((0, "Registering %s in piggy file.", tempname )); + else + mprintf((0, ".")); + } + mprintf((0, "\n")); +} + +int ds_load( char * filename ) { + int i; + CFILE * cfp; + digi_sound new; + char fname[20]; + char rawname[100]; + +#ifdef SHAREWARE + if (Registered_only) { + //mprintf( 0, "Skipping registered-only sound '%s'\n", filename ); + return 0; //don't know what I should return here //&bogus_sound; + } +#endif + + _splitpath( filename, NULL, NULL, fname, NULL ); + _makepath( rawname, NULL, NULL,fname, (digi_sample_rate==SAMPLE_RATE_22K)?".R22":".RAW" ); + + i=piggy_find_sound( fname ); + if (i!=255) { + return i; + } + + cfp = cfopen( rawname, "rb" ); + + if (cfp!=NULL) { + new.length = cfilelength( cfp ); + MALLOC( new.data, ubyte, new.length ); + cfread( new.data, 1, new.length, cfp ); + cfclose(cfp); + // -- mprintf( (0, "S" )); + // -- mprintf( (0, "<%s>", rawname )); + } else { + mprintf( (1, "Warning: Couldn't find '%s'\n", filename )); + return 255; + } + i = piggy_register_sound( &new, fname, 0 ); + return i; +} + +//parse a float +float get_float() +{ + char *xarg; + + xarg = strtok( NULL, space ); + return atof( xarg ); +} + +//parse an int +int get_int() +{ + char *xarg; + + xarg = strtok( NULL, space ); + return atoi( xarg ); +} + +// rotates a byte left one bit, preserving the bit falling off the right +//void +//rotate_left(char *c) +//{ +// int found; +// +// found = 0; +// if (*c & 0x80) +// found = 1; +// *c = *c << 1; +// if (found) +// *c |= 0x01; +//} + +//loads a texture and returns the texture num +int get_texture(char *name) +{ + char short_name[FILENAME_LEN]; + int i; + + strcpy(short_name,name); + REMOVE_DOTS(short_name); + for (i=0;i>8; TmapInfo[texture_count-1].slide_v = fl2f(get_float())>>8;} + else IFTOK("destroyed") {int t=texture_count-1; TmapInfo[t].destroyed = get_texture(strtok( NULL, space ));} + //else IFTOK("Num_effects") Num_effects = get_int(); + else IFTOK("Num_wall_anims") Num_wall_anims = get_int(); + else IFTOK("clip_num") clip_num = get_int(); + else IFTOK("dest_bm") dest_bm = strtok( NULL, space ); + else IFTOK("dest_vclip") dest_vclip = get_int(); + else IFTOK("dest_eclip") dest_eclip = get_int(); + else IFTOK("dest_size") dest_size = fl2f(get_float()); + else IFTOK("crit_clip") crit_clip = get_int(); + else IFTOK("crit_flag") crit_flag = get_int(); + else IFTOK("sound_num") sound_num = get_int(); + else IFTOK("frames") frames = get_int(); + else IFTOK("time") time = get_float(); + else IFTOK("obj_eclip") obj_eclip = get_int(); + else IFTOK("hit_sound") hit_sound = get_int(); + else IFTOK("abm_flag") abm_flag = get_int(); + else IFTOK("tmap1_flag") tmap1_flag = get_int(); + else IFTOK("vlighting") vlighting = get_float(); + else IFTOK("rod_flag") rod_flag = get_int(); + else IFTOK("superx") get_int(); + else IFTOK("open_sound") wall_open_sound = get_int(); + else IFTOK("close_sound") wall_close_sound = get_int(); + else IFTOK("explodes") wall_explodes = get_int(); + else IFTOK("blastable") wall_blastable = get_int(); + else IFTOK("hidden") wall_hidden = get_int(); + else IFTOK("$ROBOT_AI") bm_read_robot_ai(); + + else IFTOK("$POWERUP") {bm_read_powerup(0); continue;} + else IFTOK("$POWERUP_UNUSED") {bm_read_powerup(1); continue;} + else IFTOK("$HOSTAGE") {bm_read_hostage(); continue;} + else IFTOK("$ROBOT") {bm_read_robot(); continue;} + else IFTOK("$WEAPON") {bm_read_weapon(0); continue;} + else IFTOK("$WEAPON_UNUSED") {bm_read_weapon(1); continue;} + else IFTOK("$REACTOR") {bm_read_reactor(); continue;} + else IFTOK("$MARKER") {bm_read_marker(); continue;} + else IFTOK("$PLAYER_SHIP") {bm_read_player_ship(); continue;} + else IFTOK("$EXIT") { + #ifdef SHAREWARE + bm_read_exitmodel(); + #else + clear_to_end_of_line(); + #endif + continue; + } + else { //not a special token, must be a bitmap! + + // Remove any illegal/unwanted spaces and tabs at this point. + while ((*arg=='\t') || (*arg==' ')) arg++; + if (*arg == '\0') { break; } + + //check for '=' in token, indicating error + if (strchr(arg,'=')) + Error("Unknown token <'%s'> on line %d of BITMAPS.TBL",arg,linenum); + + // Otherwise, 'arg' is apparently a bitmap filename. + // Load bitmap and process it below: + bm_read_some_file(); + + } + + arg = strtok( NULL, equal_space ); + continue; + } + } + + NumTextures = texture_count; + Num_tmaps = tmap_count; + + Textures[NumTextures++].index = 0; //entry for bogus tmap + + cfclose( InfoFile ); + + atexit(bm_close); + + Assert(N_robot_types == Num_robot_ais); //should be one ai info per robot + + #ifdef SHAREWARE + init_endlevel(); //this is here so endlevel bitmaps go into pig + #endif + + verify_textures(); + + //check for refereced but unused clip count + for (i=0; ibm_w!=64)||(bmp->bm_h!=64)||(bmp->bm_rowsize!=64) ) { + mprintf( (1, "ERROR: Texture '%s' isn't 64x64 !\n", TmapInfo[i].filename )); + j++; + } + } + if (j) + Error("%d textures were not 64x64. See mono screen for list.",j); + + for (i=0;ibm_data; +//--unused-- for (j=0; j<64*64; j++ ) +//--unused-- if ( (*p++)==255 ) k++; +//--unused-- if ( k ) { +//--unused-- fprintf( fp, "'%s' has %d transparent pixels\n", TmapInfo[i].filename, k ); +//--unused-- } +//--unused-- } +//--unused-- fclose(fp); +//--unused-- } + + +void bm_close() +{ + if (Installed) + { + Installed=0; + } +} + +void set_lighting_flag(byte *bp) +{ + if (vlighting < 0) + *bp |= BM_FLAG_NO_LIGHTING; + else + *bp &= (0xff ^ BM_FLAG_NO_LIGHTING); +} + +void set_texture_name(char *name) +{ + strcpy ( TmapInfo[texture_count].filename, name ); + REMOVE_DOTS(TmapInfo[texture_count].filename); +} + +void bm_read_eclip() +{ + bitmap_index bitmap; + int dest_bm_num; + + Assert(clip_num < MAX_EFFECTS); + + if (clip_num+1 > Num_effects) + Num_effects = clip_num+1; + + Effects[clip_num].flags = 0; + + //load the dest bitmap first, so that after this routine, the last-loaded + //texture will be the monitor, so that lighting parameter will be applied + //to the correct texture + if (dest_bm) { //deal with bitmap for blown up clip + char short_name[FILENAME_LEN]; + int i; + strcpy(short_name,dest_bm); + REMOVE_DOTS(short_name); + for (i=0;i-1) && (clip_count==0) ) + Error( "Wall Clip %d is already used!", clip_num ); + WallAnims[clip_num].play_time = fl2f(time); + WallAnims[clip_num].num_frames = frames; + //WallAnims[clip_num].frame_time = fl2f(time)/frames; + Assert(clip_count < frames); + WallAnims[clip_num].frames[clip_count++] = texture_count; + WallAnims[clip_num].open_sound = wall_open_sound; + WallAnims[clip_num].close_sound = wall_close_sound; + Textures[texture_count] = bitmap; + set_lighting_flag(&GameBitmaps[bitmap.index].bm_flags); + set_texture_name( arg ); + Assert(texture_count < MAX_TEXTURES); + texture_count++; + NumTextures = texture_count; + if (clip_num >= Num_wall_anims) Num_wall_anims = clip_num+1; + } else { + bitmap_index bm[MAX_BITMAPS_PER_BRUSH]; + int nframes; + if ( (WallAnims[clip_num].num_frames>-1) ) + Error( "AB_Wall clip %d is already used!", clip_num ); + abm_flag = 0; + ab_load( arg, bm, &nframes ); + WallAnims[clip_num].num_frames = nframes; + //printf("WC"); + WallAnims[clip_num].play_time = fl2f(time); + //WallAnims[clip_num].frame_time = fl2f(time)/nframes; + WallAnims[clip_num].open_sound = wall_open_sound; + WallAnims[clip_num].close_sound = wall_close_sound; + + WallAnims[clip_num].close_sound = wall_close_sound; + strcpy(WallAnims[clip_num].filename, arg); + REMOVE_DOTS(WallAnims[clip_num].filename); + + if (clip_num >= Num_wall_anims) Num_wall_anims = clip_num+1; + + set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags); + + for (clip_count=0;clip_count < WallAnims[clip_num].num_frames; clip_count++) { + //printf("%d", clip_count); + Textures[texture_count] = bm[clip_count]; + set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags); + WallAnims[clip_num].frames[clip_count] = texture_count; + REMOVE_DOTS(arg); + sprintf( TmapInfo[texture_count].filename, "%s#%d", arg, clip_count); + Assert(texture_count < MAX_TEXTURES); + texture_count++; + NumTextures = texture_count; + } + } +} + +void bm_read_vclip() +{ + bitmap_index bi; + Assert(clip_num < VCLIP_MAXNUM); + + if (clip_num >= Num_vclips) + Num_vclips = clip_num+1; + + if (!abm_flag) { + if ( (Vclip[clip_num].num_frames>-1) && (clip_count==0) ) + Error( "Vclip %d is already used!", clip_num ); + bi = bm_load_sub(arg); + Vclip[clip_num].play_time = fl2f(time); + Vclip[clip_num].num_frames = frames; + Vclip[clip_num].frame_time = fl2f(time)/frames; + Vclip[clip_num].light_value = fl2f(vlighting); + Vclip[clip_num].sound_num = sound_num; + set_lighting_flag(&GameBitmaps[bi.index].bm_flags); + Assert(clip_count < frames); + Vclip[clip_num].frames[clip_count++] = bi; + if (rod_flag) { + rod_flag=0; + Vclip[clip_num].flags |= VF_ROD; + } + + } else { + bitmap_index bm[MAX_BITMAPS_PER_BRUSH]; + abm_flag = 0; + if ( (Vclip[clip_num].num_frames>-1) ) + Error( "AB_Vclip %d is already used!", clip_num ); + ab_load( arg, bm, &Vclip[clip_num].num_frames ); + + if (rod_flag) { + //int i; + rod_flag=0; + Vclip[clip_num].flags |= VF_ROD; + } + //printf("VC"); + Vclip[clip_num].play_time = fl2f(time); + Vclip[clip_num].frame_time = fl2f(time)/Vclip[clip_num].num_frames; + Vclip[clip_num].light_value = fl2f(vlighting); + Vclip[clip_num].sound_num = sound_num; + set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags); + + for (clip_count=0;clip_count < Vclip[clip_num].num_frames; clip_count++) { + //printf("%d", clip_count); + set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags); + Vclip[clip_num].frames[clip_count] = bm[clip_count]; + } + } +} + +// ------------------------------------------------------------------------------ +void get4fix(fix *fixp) +{ + char *curtext; + int i; + + for (i=0; i 179) { + mprintf((1, "Warning: Bogus field of view (%7.3f). Must be in 0..179.\n", ff)); + ff = 179; + } + ff = ff/360; + tt = fl2f(ff); + fix_sincos(tt, &temp, &fovp[i]); + } +} + +void clear_to_end_of_line(void) +{ + arg = strtok( NULL, space ); + while (arg != NULL) + arg = strtok( NULL, space ); +} + +void bm_read_sound() +{ + int sound_num; + int alt_sound_num; + + sound_num = get_int(); + alt_sound_num = get_int(); + + if ( sound_num>=MAX_SOUNDS ) + Error( "Too many sound files.\n" ); + + if (sound_num >= num_sounds) + num_sounds = sound_num+1; + + if (Sounds[sound_num] != 255) + Error("Sound num %d already used, bitmaps.tbl, line %d\n",sound_num,linenum); + + arg = strtok(NULL, space); + + Sounds[sound_num] = ds_load(arg); + + if ( alt_sound_num == 0 ) + AltSounds[sound_num] = sound_num; + else if (alt_sound_num < 0 ) + AltSounds[sound_num] = 255; + else + AltSounds[sound_num] = alt_sound_num; + + if (Sounds[sound_num] == 255) + Error("Can't load soundfile <%s>",arg); +} + +// ------------------------------------------------------------------------------ +void bm_read_robot_ai() +{ + char *robotnum_text; + int robotnum; + robot_info *robptr; + + robotnum_text = strtok(NULL, space); + robotnum = atoi(robotnum_text); + Assert(robotnum < MAX_ROBOT_TYPES); + robptr = &Robot_info[robotnum]; + + Assert(robotnum == Num_robot_ais); //make sure valid number + +#ifdef SHAREWARE + if (Registered_only) { + Num_robot_ais++; + clear_to_end_of_line(); + return; + } +#endif + + Num_robot_ais++; + + get4fix(robptr->field_of_view); + get4fix(robptr->firing_wait); + get4fix(robptr->firing_wait2); + get4byte(robptr->rapidfire_count); + get4fix(robptr->turn_time); +// get4fix(robptr->fire_power); +// get4fix(robptr->shield); + get4fix(robptr->max_speed); + get4fix(robptr->circle_distance); + get4byte(robptr->evade_speed); + + robptr->always_0xabcd = 0xabcd; + + adjust_field_of_view(robptr->field_of_view); + +} + +// ---------------------------------------------------------------------------------------------- +//this will load a bitmap for a polygon models. it puts the bitmap into +//the array ObjBitmaps[], and also deals with animating bitmaps +//returns a pointer to the bitmap +grs_bitmap *load_polymodel_bitmap(char *name) +{ + Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS); + +// Assert( N_ObjBitmaps == N_ObjBitmapPtrs ); + + if (name[0] == '%') { //an animating bitmap! + int eclip_num; + + eclip_num = atoi(name+1); + + if (Effects[eclip_num].changing_object_texture == -1) { //first time referenced + Effects[eclip_num].changing_object_texture = N_ObjBitmaps; + ObjBitmapPtrs[N_ObjBitmapPtrs++] = N_ObjBitmaps; + N_ObjBitmaps++; + } else { + ObjBitmapPtrs[N_ObjBitmapPtrs++] = Effects[eclip_num].changing_object_texture; + } + Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS); + Assert(N_ObjBitmapPtrs < MAX_OBJ_BITMAPS); + return NULL; + } + else { + ObjBitmaps[N_ObjBitmaps] = bm_load_sub(name); + if (GameBitmaps[ObjBitmaps[N_ObjBitmaps].index].bm_w!=64 || GameBitmaps[ObjBitmaps[N_ObjBitmaps].index].bm_h!=64) + Error("Bitmap <%s> is not 64x64",name); + ObjBitmapPtrs[N_ObjBitmapPtrs++] = N_ObjBitmaps; + N_ObjBitmaps++; + Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS); + Assert(N_ObjBitmapPtrs < MAX_OBJ_BITMAPS); + return &GameBitmaps[ObjBitmaps[N_ObjBitmaps-1].index]; + } +} + +#define MAX_MODEL_VARIANTS 4 + +// ------------------------------------------------------------------------------ +void bm_read_robot() +{ + char *model_name[MAX_MODEL_VARIANTS]; + int n_models,i; + int first_bitmap_num[MAX_MODEL_VARIANTS]; + char *equal_ptr; + int exp1_vclip_num=-1; + int exp1_sound_num=-1; + int exp2_vclip_num=-1; + int exp2_sound_num=-1; + fix lighting = F1_0/2; // Default + fix strength = F1_0*10; // Default strength + fix mass = f1_0*4; + fix drag = f1_0/2; + short weapon_type = 0, weapon_type2 = -1; + int g,s; + char name[ROBOT_NAME_LENGTH]; + int contains_count=0, contains_id=0, contains_prob=0, contains_type=0, behavior=AIB_NORMAL; + int companion = 0, smart_blobs=0, energy_blobs=0, badass=0, energy_drain=0, kamikaze=0, thief=0, pursuit=0, lightcast=0, death_roll=0; + fix glow=0, aim=F1_0; + int deathroll_sound = SOUND_BOSS_SHARE_DIE; //default + int score_value=1000; + int cloak_type=0; // Default = this robot does not cloak + int attack_type=0; // Default = this robot attacks by firing (1=lunge) + int boss_flag=0; // Default = robot is not a boss. + int see_sound = ROBOT_SEE_SOUND_DEFAULT; + int attack_sound = ROBOT_ATTACK_SOUND_DEFAULT; + int claw_sound = ROBOT_CLAW_SOUND_DEFAULT; + int taunt_sound = ROBOT_SEE_SOUND_DEFAULT; + ubyte flags=0; + + Assert(N_robot_types < MAX_ROBOT_TYPES); + +#ifdef SHAREWARE + if (Registered_only) { + Robot_info[N_robot_types].model_num = -1; + N_robot_types++; + Assert(N_robot_types < MAX_ROBOT_TYPES); + Num_total_object_types++; + Assert(Num_total_object_types < MAX_OBJTYPE); + clear_to_end_of_line(); + return; + } +#endif + + model_name[0] = strtok( NULL, space ); + first_bitmap_num[0] = N_ObjBitmapPtrs; + n_models = 1; + + // Process bitmaps + bm_flag=BM_ROBOT; + arg = strtok( NULL, space ); + while (arg!=NULL) { + equal_ptr = strchr( arg, '=' ); + if ( equal_ptr ) { + *equal_ptr='\0'; + equal_ptr++; + // if we have john=cool, arg is 'john' and equal_ptr is 'cool' + if (!stricmp( arg, "exp1_vclip" )) { + exp1_vclip_num = atoi(equal_ptr); + } else if (!stricmp( arg, "exp2_vclip" )) { + exp2_vclip_num = atoi(equal_ptr); + } else if (!stricmp( arg, "exp1_sound" )) { + exp1_sound_num = atoi(equal_ptr); + } else if (!stricmp( arg, "exp2_sound" )) { + exp2_sound_num = atoi(equal_ptr); + } else if (!stricmp( arg, "lighting" )) { + lighting = fl2f(atof(equal_ptr)); + if ( (lighting < 0) || (lighting > F1_0 )) { + mprintf( (1, "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting))); + Error( "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting)); + } + } else if (!stricmp( arg, "weapon_type" )) { + weapon_type = atoi(equal_ptr); + } else if (!stricmp( arg, "weapon_type2" )) { + weapon_type2 = atoi(equal_ptr); + } else if (!stricmp( arg, "strength" )) { + strength = i2f(atoi(equal_ptr)); + } else if (!stricmp( arg, "mass" )) { + mass = fl2f(atof(equal_ptr)); + } else if (!stricmp( arg, "drag" )) { + drag = fl2f(atof(equal_ptr)); + } else if (!stricmp( arg, "contains_id" )) { + contains_id = atoi(equal_ptr); + } else if (!stricmp( arg, "contains_type" )) { + contains_type = atoi(equal_ptr); + } else if (!stricmp( arg, "contains_count" )) { + contains_count = atoi(equal_ptr); + } else if (!stricmp( arg, "companion" )) { + companion = atoi(equal_ptr); + } else if (!stricmp( arg, "badass" )) { + badass = atoi(equal_ptr); + } else if (!stricmp( arg, "lightcast" )) { + lightcast = atoi(equal_ptr); + } else if (!stricmp( arg, "glow" )) { + glow = fl2f(atof(equal_ptr)); + } else if (!stricmp( arg, "death_roll" )) { + death_roll = atoi(equal_ptr); + } else if (!stricmp( arg, "deathroll_sound" )) { + deathroll_sound = atoi(equal_ptr); + } else if (!stricmp( arg, "thief" )) { + thief = atoi(equal_ptr); + } else if (!stricmp( arg, "kamikaze" )) { + kamikaze = atoi(equal_ptr); + } else if (!stricmp( arg, "pursuit" )) { + pursuit = atoi(equal_ptr); + } else if (!stricmp( arg, "smart_blobs" )) { + smart_blobs = atoi(equal_ptr); + } else if (!stricmp( arg, "energy_blobs" )) { + energy_blobs = atoi(equal_ptr); + } else if (!stricmp( arg, "energy_drain" )) { + energy_drain = atoi(equal_ptr); + } else if (!stricmp( arg, "contains_prob" )) { + contains_prob = atoi(equal_ptr); + } else if (!stricmp( arg, "cloak_type" )) { + cloak_type = atoi(equal_ptr); + } else if (!stricmp( arg, "attack_type" )) { + attack_type = atoi(equal_ptr); + } else if (!stricmp( arg, "boss" )) { + boss_flag = atoi(equal_ptr); + } else if (!stricmp( arg, "score_value" )) { + score_value = atoi(equal_ptr); + } else if (!stricmp( arg, "see_sound" )) { + see_sound = atoi(equal_ptr); + } else if (!stricmp( arg, "attack_sound" )) { + attack_sound = atoi(equal_ptr); + } else if (!stricmp( arg, "claw_sound" )) { + claw_sound = atoi(equal_ptr); + } else if (!stricmp( arg, "taunt_sound" )) { + taunt_sound = atoi(equal_ptr); + } else if (!stricmp( arg, "aim" )) { + aim = fl2f(atof(equal_ptr)); + } else if (!stricmp( arg, "big_radius" )) { + if (atoi(equal_ptr)) + flags |= RIF_BIG_RADIUS; + } else if (!stricmp( arg, "behavior" )) { + if (!stricmp(equal_ptr, "STILL")) + behavior = AIB_STILL; + else if (!stricmp(equal_ptr, "NORMAL")) + behavior = AIB_NORMAL; + else if (!stricmp(equal_ptr, "BEHIND")) + behavior = AIB_BEHIND; + else if (!stricmp(equal_ptr, "RUN_FROM")) + behavior = AIB_RUN_FROM; + else if (!stricmp(equal_ptr, "SNIPE")) + behavior = AIB_SNIPE; + else if (!stricmp(equal_ptr, "STATION")) + behavior = AIB_STATION; + else if (!stricmp(equal_ptr, "FOLLOW")) + behavior = AIB_FOLLOW; + else + Int3(); // Error. Illegal behavior type for current robot. + } else if (!stricmp( arg, "name" )) { + Assert(strlen(equal_ptr) < ROBOT_NAME_LENGTH); // Oops, name too long. + strcpy(name, &equal_ptr[1]); + name[strlen(name)-1] = 0; + } else if (!stricmp( arg, "simple_model" )) { + model_name[n_models] = equal_ptr; + first_bitmap_num[n_models] = N_ObjBitmapPtrs; + n_models++; + Assert(n_models < MAX_MODEL_VARIANTS); + } else { + Int3(); + mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr )); + } + } else { // Must be a texture specification... + load_polymodel_bitmap(arg); + } + arg = strtok( NULL, space ); + } + + //clear out anim info + for (g=0;g i2f(15)) || (glow < 0) || (glow != 0 && glow < 0x1000)) { + mprintf((0,"Invalid glow value %x for robot %d\n",glow,N_robot_types)); + Int3(); + } + + ObjType[Num_total_object_types] = OL_ROBOT; + ObjId[Num_total_object_types] = N_robot_types; + + Robot_info[N_robot_types].exp1_vclip_num = exp1_vclip_num; + Robot_info[N_robot_types].exp2_vclip_num = exp2_vclip_num; + Robot_info[N_robot_types].exp1_sound_num = exp1_sound_num; + Robot_info[N_robot_types].exp2_sound_num = exp2_sound_num; + Robot_info[N_robot_types].lighting = lighting; + Robot_info[N_robot_types].weapon_type = weapon_type; + Robot_info[N_robot_types].weapon_type2 = weapon_type2; + Robot_info[N_robot_types].strength = strength; + Robot_info[N_robot_types].mass = mass; + Robot_info[N_robot_types].drag = drag; + Robot_info[N_robot_types].cloak_type = cloak_type; + Robot_info[N_robot_types].attack_type = attack_type; + Robot_info[N_robot_types].boss_flag = boss_flag; + + Robot_info[N_robot_types].contains_id = contains_id; + Robot_info[N_robot_types].contains_count = contains_count; + Robot_info[N_robot_types].contains_prob = contains_prob; + Robot_info[N_robot_types].companion = companion; + Robot_info[N_robot_types].badass = badass; + Robot_info[N_robot_types].lightcast = lightcast; + Robot_info[N_robot_types].glow = (glow>>12); //convert to 4:4 + Robot_info[N_robot_types].death_roll = death_roll; + Robot_info[N_robot_types].deathroll_sound = deathroll_sound; + Robot_info[N_robot_types].thief = thief; + Robot_info[N_robot_types].flags = flags; + Robot_info[N_robot_types].kamikaze = kamikaze; + Robot_info[N_robot_types].pursuit = pursuit; + Robot_info[N_robot_types].smart_blobs = smart_blobs; + Robot_info[N_robot_types].energy_blobs = energy_blobs; + Robot_info[N_robot_types].energy_drain = energy_drain; + Robot_info[N_robot_types].score_value = score_value; + Robot_info[N_robot_types].see_sound = see_sound; + Robot_info[N_robot_types].attack_sound = attack_sound; + Robot_info[N_robot_types].claw_sound = claw_sound; + Robot_info[N_robot_types].taunt_sound = taunt_sound; + Robot_info[N_robot_types].behavior = behavior; // Default behavior for this robot, if coming out of matcen. + Robot_info[N_robot_types].aim = min(f2i(aim*255), 255); // how well this robot type can aim. 255=perfect + + if (contains_type) + Robot_info[N_robot_types].contains_type = OBJ_ROBOT; + else + Robot_info[N_robot_types].contains_type = OBJ_POWERUP; + + strcpy(Robot_names[N_robot_types], name); + + N_robot_types++; + Num_total_object_types++; + + Assert(N_robot_types < MAX_ROBOT_TYPES); + Assert(Num_total_object_types < MAX_OBJTYPE); + + bm_flag = BM_NONE; +} + +//read a reactor model +void bm_read_reactor() +{ + char *model_name, *model_name_dead=NULL; + int first_bitmap_num, first_bitmap_num_dead, n_normal_bitmaps; + char *equal_ptr; + short model_num; + short explosion_vclip_num = -1; + short explosion_sound_num = SOUND_ROBOT_DESTROYED; + fix lighting = F1_0/2; // Default + int type=-1; + fix strength=0; + + Assert(Num_reactors < MAX_REACTORS); + +#ifdef SHAREWARE + if (Registered_only) { + Num_reactors++; + clear_to_end_of_line(); + return; + } +#endif + + model_name = strtok( NULL, space ); + + // Process bitmaps + bm_flag = BM_NONE; + arg = strtok( NULL, space ); + first_bitmap_num = N_ObjBitmapPtrs; + + type = OL_CONTROL_CENTER; + + while (arg!=NULL) { + + equal_ptr = strchr( arg, '=' ); + + if ( equal_ptr ) { + *equal_ptr='\0'; + equal_ptr++; + + // if we have john=cool, arg is 'john' and equal_ptr is 'cool' + + //@@if (!stricmp(arg,"type")) { + //@@ if (!stricmp(equal_ptr,"controlcen")) + //@@ type = OL_CONTROL_CENTER; + //@@ else if (!stricmp(equal_ptr,"clutter")) + //@@ type = OL_CLUTTER; + //@@} + + if (!stricmp( arg, "exp_vclip" )) { + explosion_vclip_num = atoi(equal_ptr); + } else if (!stricmp( arg, "dead_pof" )) { + model_name_dead = equal_ptr; + first_bitmap_num_dead=N_ObjBitmapPtrs; + } else if (!stricmp( arg, "exp_sound" )) { + explosion_sound_num = atoi(equal_ptr); + } else if (!stricmp( arg, "lighting" )) { + lighting = fl2f(atof(equal_ptr)); + if ( (lighting < 0) || (lighting > F1_0 )) { + mprintf( (1, "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting))); + Error( "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting)); + } + } else if (!stricmp( arg, "strength" )) { + strength = fl2f(atof(equal_ptr)); + } else { + Int3(); + mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr )); + } + } else { // Must be a texture specification... + load_polymodel_bitmap(arg); + } + arg = strtok( NULL, space ); + } + + if ( model_name_dead ) + n_normal_bitmaps = first_bitmap_num_dead-first_bitmap_num; + else + n_normal_bitmaps = N_ObjBitmapPtrs-first_bitmap_num; + + model_num = load_polygon_model(model_name,n_normal_bitmaps,first_bitmap_num,NULL); + + if ( model_name_dead ) + Dead_modelnums[model_num] = load_polygon_model(model_name_dead,N_ObjBitmapPtrs-first_bitmap_num_dead,first_bitmap_num_dead,NULL); + else + Dead_modelnums[model_num] = -1; + + if (type == -1) + Error("No object type specfied for object in BITMAPS.TBL on line %d\n",linenum); + + Reactors[Num_reactors].model_num = model_num; + Reactors[Num_reactors].n_guns = read_model_guns(model_name,Reactors[Num_reactors].gun_points,Reactors[Num_reactors].gun_dirs,NULL); + + ObjType[Num_total_object_types] = type; + ObjId[Num_total_object_types] = Num_reactors; + ObjStrength[Num_total_object_types] = strength; + + //printf( "Object type %d is a control center\n", Num_total_object_types ); + Num_total_object_types++; + Assert(Num_total_object_types < MAX_OBJTYPE); + + Num_reactors++; +} + +//read the marker object +void bm_read_marker() +{ + char *model_name; + int first_bitmap_num, n_normal_bitmaps; + char *equal_ptr; + + model_name = strtok( NULL, space ); + + // Process bitmaps + bm_flag = BM_NONE; + arg = strtok( NULL, space ); + first_bitmap_num = N_ObjBitmapPtrs; + + while (arg!=NULL) { + + equal_ptr = strchr( arg, '=' ); + + if ( equal_ptr ) { + *equal_ptr='\0'; + equal_ptr++; + + // if we have john=cool, arg is 'john' and equal_ptr is 'cool' + mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr )); + Int3(); + + } else { // Must be a texture specification... + load_polymodel_bitmap(arg); + } + arg = strtok( NULL, space ); + } + + n_normal_bitmaps = N_ObjBitmapPtrs-first_bitmap_num; + + Marker_model_num = load_polygon_model(model_name,n_normal_bitmaps,first_bitmap_num,NULL); +} + +#ifdef SHAREWARE +//read the exit model +void bm_read_exitmodel() +{ + char *model_name, *model_name_dead=NULL; + int first_bitmap_num, first_bitmap_num_dead, n_normal_bitmaps; + char *equal_ptr; + short model_num; + + model_name = strtok( NULL, space ); + + // Process bitmaps + bm_flag = BM_NONE; + arg = strtok( NULL, space ); + first_bitmap_num = N_ObjBitmapPtrs; + + while (arg!=NULL) { + + equal_ptr = strchr( arg, '=' ); + + if ( equal_ptr ) { + *equal_ptr='\0'; + equal_ptr++; + + // if we have john=cool, arg is 'john' and equal_ptr is 'cool' + + if (!stricmp( arg, "dead_pof" )) { + model_name_dead = equal_ptr; + first_bitmap_num_dead=N_ObjBitmapPtrs; + } else { + Int3(); + mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr )); + } + } else { // Must be a texture specification... + load_polymodel_bitmap(arg); + } + arg = strtok( NULL, space ); + } + + if ( model_name_dead ) + n_normal_bitmaps = first_bitmap_num_dead-first_bitmap_num; + else + n_normal_bitmaps = N_ObjBitmapPtrs-first_bitmap_num; + + model_num = load_polygon_model(model_name,n_normal_bitmaps,first_bitmap_num,NULL); + + if ( model_name_dead ) + Dead_modelnums[model_num] = load_polygon_model(model_name_dead,N_ObjBitmapPtrs-first_bitmap_num_dead,first_bitmap_num_dead,NULL); + else + Dead_modelnums[model_num] = -1; + +//@@ ObjType[Num_total_object_types] = type; +//@@ ObjId[Num_total_object_types] = model_num; +//@@ ObjStrength[Num_total_object_types] = strength; +//@@ +//@@ //printf( "Object type %d is a control center\n", Num_total_object_types ); +//@@ Num_total_object_types++; +//@@ Assert(Num_total_object_types < MAX_OBJTYPE); + + exit_modelnum = model_num; + destroyed_exit_modelnum = Dead_modelnums[model_num]; + +} +#endif + +void bm_read_player_ship() +{ + char *model_name_dying=NULL; + char *model_name[MAX_MODEL_VARIANTS]; + int n_models=0,i; + int first_bitmap_num[MAX_MODEL_VARIANTS]; + char *equal_ptr; + robot_info ri; + int last_multi_bitmap_num=-1; + + // Process bitmaps + bm_flag = BM_NONE; + + arg = strtok( NULL, space ); + + Player_ship->mass = Player_ship->drag = 0; //stupid defaults + Player_ship->expl_vclip_num = -1; + + while (arg!=NULL) { + + equal_ptr = strchr( arg, '=' ); + + if ( equal_ptr ) { + + *equal_ptr='\0'; + equal_ptr++; + + // if we have john=cool, arg is 'john' and equal_ptr is 'cool' + + if (!stricmp( arg, "model" )) { + Assert(n_models==0); + model_name[0] = equal_ptr; + first_bitmap_num[0] = N_ObjBitmapPtrs; + n_models = 1; + } else if (!stricmp( arg, "simple_model" )) { + model_name[n_models] = equal_ptr; + first_bitmap_num[n_models] = N_ObjBitmapPtrs; + n_models++; + Assert(n_models < MAX_MODEL_VARIANTS); + + if (First_multi_bitmap_num!=-1 && last_multi_bitmap_num==-1) + last_multi_bitmap_num=N_ObjBitmapPtrs; + } + else if (!stricmp( arg, "mass" )) + Player_ship->mass = fl2f(atof(equal_ptr)); + else if (!stricmp( arg, "drag" )) + Player_ship->drag = fl2f(atof(equal_ptr)); +// else if (!stricmp( arg, "low_thrust" )) +// Player_ship->low_thrust = fl2f(atof(equal_ptr)); + else if (!stricmp( arg, "max_thrust" )) + Player_ship->max_thrust = fl2f(atof(equal_ptr)); + else if (!stricmp( arg, "reverse_thrust" )) + Player_ship->reverse_thrust = fl2f(atof(equal_ptr)); + else if (!stricmp( arg, "brakes" )) + Player_ship->brakes = fl2f(atof(equal_ptr)); + else if (!stricmp( arg, "wiggle" )) + Player_ship->wiggle = fl2f(atof(equal_ptr)); + else if (!stricmp( arg, "max_rotthrust" )) + Player_ship->max_rotthrust = fl2f(atof(equal_ptr)); + else if (!stricmp( arg, "dying_pof" )) + model_name_dying = equal_ptr; + else if (!stricmp( arg, "expl_vclip_num" )) + Player_ship->expl_vclip_num=atoi(equal_ptr); + else { + Int3(); + mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr )); + } + } + else if (!stricmp( arg, "multi_textures" )) { + + First_multi_bitmap_num = N_ObjBitmapPtrs; + first_bitmap_num[n_models] = N_ObjBitmapPtrs; + + } + else // Must be a texture specification... + + load_polymodel_bitmap(arg); + + arg = strtok( NULL, space ); + } + + Assert(model_name != NULL); + + if (First_multi_bitmap_num!=-1 && last_multi_bitmap_num==-1) + last_multi_bitmap_num=N_ObjBitmapPtrs; + + if (First_multi_bitmap_num==-1) + first_bitmap_num[n_models] = N_ObjBitmapPtrs; + + Assert(last_multi_bitmap_num-First_multi_bitmap_num == (MAX_NUM_NET_PLAYERS-1)*2); + + for (i=0;imodel_num = model_num; + else + Polygon_models[last_model_num].simpler_model = model_num+1; + + last_model_num = model_num; + } + + if ( model_name_dying ) { + Assert(n_models); + Dying_modelnums[Player_ship->model_num] = load_polygon_model(model_name_dying,first_bitmap_num[1]-first_bitmap_num[0],first_bitmap_num[0],NULL); + } + + Assert(ri.n_guns == N_PLAYER_GUNS); + + //calc player gun positions + + { + polymodel *pm; + robot_info *r; + vms_vector pnt; + int mn; //submodel number + int gun_num; + + r = &ri; + pm = &Polygon_models[Player_ship->model_num]; + + for (gun_num=0;gun_numn_guns;gun_num++) { + + pnt = r->gun_points[gun_num]; + mn = r->gun_submodels[gun_num]; + + //instance up the tree for this gun + while (mn != 0) { + vm_vec_add2(&pnt,&pm->submodel_offsets[mn]); + mn = pm->submodel_parents[mn]; + } + + Player_ship->gun_points[gun_num] = pnt; + + } + } + + +} + +void bm_read_some_file() +{ + + switch (bm_flag) { + case BM_NONE: + Error("Trying to read bitmap <%s> with bm_flag==BM_NONE on line %d of BITMAPS.TBL",arg,linenum); + break; + case BM_COCKPIT: { + bitmap_index bitmap; + bitmap = bm_load_sub(arg); + Assert( Num_cockpits < N_COCKPIT_BITMAPS ); + cockpit_bitmap[Num_cockpits++] = bitmap; + //bm_flag = BM_NONE; + return; + } + break; + case BM_GAUGES: + bm_read_gauges(); + return; + break; + case BM_GAUGES_HIRES: + bm_read_gauges_hires(); + return; + break; + case BM_WEAPON: + bm_read_weapon(0); + return; + break; + case BM_VCLIP: + bm_read_vclip(); + return; + break; + case BM_ECLIP: + bm_read_eclip(); + return; + break; + case BM_TEXTURES: { + bitmap_index bitmap; + bitmap = bm_load_sub(arg); + Assert(tmap_count < MAX_TEXTURES); + TmapList[tmap_count++] = texture_count; + Textures[texture_count] = bitmap; + set_texture_name( arg ); + Assert(texture_count < MAX_TEXTURES); + texture_count++; + NumTextures = texture_count; + return; + } + break; + case BM_WCLIP: + bm_read_wclip(); + return; + break; + } + + Error("Trying to read bitmap <%s> with unknown bm_flag <%x> on line %d of BITMAPS.TBL",arg,bm_flag,linenum); +} + +// ------------------------------------------------------------------------------ +// If unused_flag is set, then this is just a placeholder. Don't actually reference vclips or load bbms. +void bm_read_weapon(int unused_flag) +{ + int i,n; + int n_models=0; + char *equal_ptr; + char *pof_file_inner=NULL; + char *model_name[MAX_MODEL_VARIANTS]; + int first_bitmap_num[MAX_MODEL_VARIANTS]; + int lighted; //flag for whether is a texture is lighted + + Assert(N_weapon_types < MAX_WEAPON_TYPES); + + n = N_weapon_types; + N_weapon_types++; + Assert(N_weapon_types <= MAX_WEAPON_TYPES); + + if (unused_flag) { + clear_to_end_of_line(); + return; + } + +#ifdef SHAREWARE + if (Registered_only) { + clear_to_end_of_line(); + return; + } +#endif + + // Initialize weapon array + Weapon_info[n].render_type = WEAPON_RENDER_NONE; // 0=laser, 1=blob, 2=object + Weapon_info[n].bitmap.index = 0; + Weapon_info[n].model_num = -1; + Weapon_info[n].model_num_inner = -1; + Weapon_info[n].blob_size = 0x1000; // size of blob + Weapon_info[n].flash_vclip = -1; + Weapon_info[n].flash_sound = SOUND_LASER_FIRED; + Weapon_info[n].flash_size = 0; + Weapon_info[n].robot_hit_vclip = -1; + Weapon_info[n].robot_hit_sound = -1; + Weapon_info[n].wall_hit_vclip = -1; + Weapon_info[n].wall_hit_sound = -1; + Weapon_info[n].impact_size = 0; + for (i=0; ibm_flags |= BM_FLAG_NO_LIGHTING; + + lighted = 1; //default for next bitmap is lighted + } + arg = strtok( NULL, space ); + } + + first_bitmap_num[n_models] = N_ObjBitmapPtrs; + + for (i=0;ifilename)-sizeof(TmapInfo->pad2), 1, fp ); + +fprintf(tfile,"NumTextures = %d, Textures array = %d, TmapInfo array = %d\n",NumTextures,sizeof(bitmap_index)*NumTextures,sizeof(tmap_info)*NumTextures); + + t = MAX_SOUNDS; + fwrite( &t, sizeof(int), 1, fp ); + fwrite( Sounds, sizeof(ubyte), t, fp ); + fwrite( AltSounds, sizeof(ubyte), t, fp ); + +fprintf(tfile,"Num Sounds = %d, Sounds array = %d, AltSounds array = %d\n",t,t,t); + + fwrite( &Num_vclips, sizeof(int), 1, fp ); + fwrite( Vclip, sizeof(vclip), Num_vclips, fp ); + +fprintf(tfile,"Num_vclips = %d, Vclip array = %d\n",Num_vclips,sizeof(vclip)*Num_vclips); + + fwrite( &Num_effects, sizeof(int), 1, fp ); + fwrite( Effects, sizeof(eclip), Num_effects, fp ); + +fprintf(tfile,"Num_effects = %d, Effects array = %d\n",Num_effects,sizeof(eclip)*Num_effects); + + fwrite( &Num_wall_anims, sizeof(int), 1, fp ); + fwrite( WallAnims, sizeof(wclip), Num_wall_anims, fp ); + +fprintf(tfile,"Num_wall_anims = %d, WallAnims array = %d\n",Num_wall_anims,sizeof(wclip)*Num_wall_anims); + + t = N_D2_ROBOT_TYPES; + fwrite( &t, sizeof(int), 1, fp ); + fwrite( Robot_info, sizeof(robot_info), t, fp ); + +fprintf(tfile,"N_robot_types = %d, Robot_info array = %d\n",t,sizeof(robot_info)*N_robot_types); + + t = N_D2_ROBOT_JOINTS; + fwrite( &t, sizeof(int), 1, fp ); + fwrite( Robot_joints, sizeof(jointpos), t, fp ); + +fprintf(tfile,"N_robot_joints = %d, Robot_joints array = %d\n",t,sizeof(jointpos)*N_robot_joints); + + t = N_D2_WEAPON_TYPES; + fwrite( &t, sizeof(int), 1, fp ); + fwrite( Weapon_info, sizeof(weapon_info), t, fp ); + +fprintf(tfile,"N_weapon_types = %d, Weapon_info array = %d\n",N_weapon_types,sizeof(weapon_info)*N_weapon_types); + + fwrite( &N_powerup_types, sizeof(int), 1, fp ); + fwrite( Powerup_info, sizeof(powerup_type_info), N_powerup_types, fp ); + +fprintf(tfile,"N_powerup_types = %d, Powerup_info array = %d\n",N_powerup_types,sizeof(powerup_info)*N_powerup_types); + + t = N_D2_POLYGON_MODELS; + fwrite( &t, sizeof(int), 1, fp ); + fwrite( Polygon_models, sizeof(polymodel), t, fp ); + +fprintf(tfile,"N_polygon_models = %d, Polygon_models array = %d\n",t,sizeof(polymodel)*t); + + for (i=0; i +#include +#include +#include +#include + +#include "pstypes.h" +#include "cmd.h" +#include "console.h" +#include "error.h" + +/* ====== + * cmd_parse - Parse an input string + * ====== + */ +void cmd_parse(char *input) +{ + char buffer[CMD_MAX_LENGTH]; + char *tokens[CMD_MAX_TOKENS]; + int num_tokens; + int i, l; + + Assert(input != NULL); + + /* Strip leading spaces */ + for (i=0; isspace(input[i]); i++) ; + strncpy( buffer, &input[i], CMD_MAX_LENGTH ); + + printf("lead strip \"%s\"\n",buffer); + l = strlen(buffer); + /* If command is empty, give up */ + if (l==0) return; + + /* Strip trailing spaces */ + for (i=l-1; i>0 && isspace(buffer[i]); i--) ; + buffer[i+1] = 0; + printf("trail strip \"%s\"\n",buffer); + + /* Split into tokens */ + l = strlen(buffer); + num_tokens = 1; + + tokens[0] = buffer; + for (i=1; i1) { + printf("setting %s %s\n",tokens[0], tokens[1]); + cvar_set(tokens[0], tokens[1]); + } else { + con_printf(CON_NORMAL, "%s: %f\n", tokens[0], cvar(tokens[0])); + } +} diff --git a/main/cntrlcen.c b/main/cntrlcen.c new file mode 100644 index 00000000..09fe806b --- /dev/null +++ b/main/cntrlcen.c @@ -0,0 +1,504 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifdef RCS +static char rcsid[] = "$Id: cntrlcen.c,v 1.1.1.1 2001-01-19 03:29:59 bradleyb Exp $"; +#endif + +#ifdef WINDOWS +#include "desw.h" +#endif + +#include +#include +#include +#include + +#include "pstypes.h" +#include "error.h" +#include "mono.h" + +#include "inferno.h" +#include "cntrlcen.h" +#include "game.h" +#include "laser.h" +#include "gameseq.h" +#include "ai.h" +#include "multi.h" +#include "wall.h" +#include "object.h" +#include "robot.h" +#include "vclip.h" +#include "fireball.h" +#include "endlevel.h" + +//@@vms_vector controlcen_gun_points[MAX_CONTROLCEN_GUNS]; +//@@vms_vector controlcen_gun_dirs[MAX_CONTROLCEN_GUNS]; + +reactor Reactors[MAX_REACTORS]; +int Num_reactors=0; + +control_center_triggers ControlCenterTriggers; + +int N_controlcen_guns; +int Control_center_been_hit; +int Control_center_player_been_seen; +int Control_center_next_fire_time; +int Control_center_present; + +vms_vector Gun_pos[MAX_CONTROLCEN_GUNS], Gun_dir[MAX_CONTROLCEN_GUNS]; + +void do_countdown_frame(); + +// ----------------------------------------------------------------------------- +//return the position & orientation of a gun on the control center object +void calc_controlcen_gun_point(vms_vector *gun_point,vms_vector *gun_dir,object *obj,int gun_num) +{ + reactor *reactor; + vms_matrix m; + + Assert(obj->type == OBJ_CNTRLCEN); + Assert(obj->render_type==RT_POLYOBJ); + + reactor = &Reactors[obj->id]; + + Assert(gun_num < reactor->n_guns); + + //instance gun position & orientation + + vm_copy_transpose_matrix(&m,&obj->orient); + + vm_vec_rotate(gun_point,&reactor->gun_points[gun_num],&m); + vm_vec_add2(gun_point,&obj->pos); + vm_vec_rotate(gun_dir,&reactor->gun_dirs[gun_num],&m); +} + +// ----------------------------------------------------------------------------- +// Look at control center guns, find best one to fire at *objp. +// Return best gun number (one whose direction dotted with vector to player is largest). +// If best gun has negative dot, return -1, meaning no gun is good. +int calc_best_gun(int num_guns, vms_vector *gun_pos, vms_vector *gun_dir, vms_vector *objpos) +{ + int i; + fix best_dot; + int best_gun; + + best_dot = -F1_0*2; + best_gun = -1; + + for (i=0; i best_dot) { + best_dot = dot; + best_gun = i; + } + } + + Assert(best_gun != -1); // Contact Mike. This is impossible. Or maybe you're getting an unnormalized vector somewhere. + + if (best_dot < 0) + return -1; + else + return best_gun; + +} + +extern fix Player_time_of_death; // object.c + +int Dead_controlcen_object_num=-1; + +//how long to blow up on insane +int Base_control_center_explosion_time=DEFAULT_CONTROL_CENTER_EXPLOSION_TIME; + +int Control_center_destroyed = 0; +fix Countdown_timer=0; +int Countdown_seconds_left=0, Total_countdown_time=0; //in whole seconds + +int Alan_pavlish_reactor_times[NDL] = {90, 60, 45, 35, 30}; + +// ----------------------------------------------------------------------------- +// Called every frame. If control center been destroyed, then actually do something. +void do_controlcen_dead_frame(void) +{ + if ((Dead_controlcen_object_num != -1) && (Countdown_seconds_left > 0)) + if (d_rand() < FrameTime*4) + create_small_fireball_on_object(&Objects[Dead_controlcen_object_num], F1_0, 1); + + if (Control_center_destroyed && !Endlevel_sequence) + do_countdown_frame(); +} + +#define COUNTDOWN_VOICE_TIME fl2f(12.75) + +void do_countdown_frame() +{ + fix old_time; + int fc, div_scale; + + if (!Control_center_destroyed) return; + + #if !defined(D2_OEM) && !defined(SHAREWARE) // get countdown in OEM and SHAREWARE only + // On last level, we don't want a countdown. + if ((Current_mission_num == 0) && (Current_level_num == Last_level)) + { + if (!(Game_mode & GM_MULTI)) + return; + if (Game_mode & GM_MULTI_ROBOTS) + return; + } + #endif + + // Control center destroyed, rock the player's ship. + fc = Countdown_seconds_left; + if (fc > 16) + fc = 16; + + // At Trainee, decrease rocking of ship by 4x. + div_scale = 1; + if (Difficulty_level == 0) + div_scale = 4; + + ConsoleObject->mtype.phys_info.rotvel.x += (fixmul(d_rand() - 16384, 3*F1_0/16 + (F1_0*(16-fc))/32))/div_scale; + ConsoleObject->mtype.phys_info.rotvel.z += (fixmul(d_rand() - 16384, 3*F1_0/16 + (F1_0*(16-fc))/32))/div_scale; + // Hook in the rumble sound effect here. + + old_time = Countdown_timer; + Countdown_timer -= RealFrameTime; + Countdown_seconds_left = f2i(Countdown_timer + F1_0*7/8); + + if ( (old_time > COUNTDOWN_VOICE_TIME ) && (Countdown_timer <= COUNTDOWN_VOICE_TIME) ) { + digi_play_sample( SOUND_COUNTDOWN_13_SECS, F3_0 ); + } + if ( f2i(old_time + F1_0*7/8) != Countdown_seconds_left ) { + if ( (Countdown_seconds_left>=0) && (Countdown_seconds_left<10) ) + digi_play_sample( SOUND_COUNTDOWN_0_SECS+Countdown_seconds_left, F3_0 ); + if ( Countdown_seconds_left==Total_countdown_time-1) + digi_play_sample( SOUND_COUNTDOWN_29_SECS, F3_0 ); + } + + if (Countdown_timer > 0) { + fix size,old_size; + size = (i2f(Total_countdown_time)-Countdown_timer) / fl2f(0.65); + old_size = (i2f(Total_countdown_time)-old_time) / fl2f(0.65); + if (size != old_size && (Countdown_seconds_left < (Total_countdown_time-5) )) { // Every 2 seconds! + //@@if (Dead_controlcen_object_num != -1) { + //@@ vms_vector vp; //,v,c; + //@@ compute_segment_center(&vp, &Segments[Objects[Dead_controlcen_object_num].segnum]); + //@@ object_create_explosion( Objects[Dead_controlcen_object_num].segnum, &vp, size*10, VCLIP_SMALL_EXPLOSION); + //@@} + + digi_play_sample( SOUND_CONTROL_CENTER_WARNING_SIREN, F3_0 ); + } + } else { + int flash_value; + + if (old_time > 0) + digi_play_sample( SOUND_MINE_BLEW_UP, F1_0 ); + + flash_value = f2i(-Countdown_timer * (64 / 4)); // 4 seconds to total whiteness + PALETTE_FLASH_SET(flash_value,flash_value,flash_value); + + if (PaletteBlueAdd > 64 ) { + WINDOS( + dd_gr_set_current_canvas(NULL), + gr_set_current_canvas( NULL ) + ); + WINDOS( + dd_gr_clear_canvas(BM_XRGB(31,31,31)), + gr_clear_canvas(BM_XRGB(31,31,31)) + ); //make screen all white to match palette effect + reset_cockpit(); //force cockpit redraw next time + reset_palette_add(); //restore palette for death message + //controlcen->MaxCapacity = Fuelcen_max_amount; + //gauge_message( "Control Center Reset" ); + DoPlayerDead(); //kill_player(); + } + } +} + +// ----------------------------------------------------------------------------- +// Called when control center gets destroyed. +// This code is common to whether control center is implicitly imbedded in a boss, +// or is an object of its own. +// if objp == NULL that means the boss was the control center and don't set Dead_controlcen_object_num +void do_controlcen_destroyed_stuff(object *objp) +{ + int i; + + if ((Game_mode & GM_MULTI_ROBOTS) && Control_center_destroyed) + return; // Don't allow resetting if control center and boss on same level + + // Must toggle walls whether it is a boss or control center. + for (i=0;isegnum]; + + // This is a hack. Since the control center is not processed by + // ai_do_frame, it doesn't know to deal with cloaked dudes. It + // seems to work in single-player mode because it is actually using + // the value of Believed_player_position that was set by the last + // person to go through ai_do_frame. But since a no-robots game + // never goes through ai_do_frame, I'm making it so the control + // center can spot cloaked dudes. + + if (Game_mode & GM_MULTI) + Believed_player_pos = Objects[Players[Player_num].objnum].pos; + + // Hack for special control centers which are isolated and not reachable because the + // real control center is inside the boss. + for (i=0; ichildren[i])) + break; + if (i == MAX_SIDES_PER_SEGMENT) + return; + + vm_vec_sub(&vec_to_player, &ConsoleObject->pos, &obj->pos); + dist_to_player = vm_vec_normalize_quick(&vec_to_player); + if (dist_to_player < F1_0*200) { + Control_center_player_been_seen = player_is_visible_from_object(obj, &obj->pos, 0, &vec_to_player); + Control_center_next_fire_time = 0; + } + } + + return; + } + + // Periodically, make the reactor fall asleep if player not visible. + if (Control_center_been_hit || Control_center_player_been_seen) { + if ((Last_time_cc_vis_check + F1_0*5 < GameTime) || (Last_time_cc_vis_check > GameTime)) { + vms_vector vec_to_player; + fix dist_to_player; + + vm_vec_sub(&vec_to_player, &ConsoleObject->pos, &obj->pos); + dist_to_player = vm_vec_normalize_quick(&vec_to_player); + Last_time_cc_vis_check = GameTime; + if (dist_to_player < F1_0*120) { + Control_center_player_been_seen = player_is_visible_from_object(obj, &obj->pos, 0, &vec_to_player); + if (!Control_center_player_been_seen) + Control_center_been_hit = 0; + } + } + + } + + if ((Control_center_next_fire_time < 0) && !(Player_is_dead && (GameTime > Player_time_of_death+F1_0*2))) { + if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) + best_gun_num = calc_best_gun(N_controlcen_guns, Gun_pos, Gun_dir, &Believed_player_pos); + else + best_gun_num = calc_best_gun(N_controlcen_guns, Gun_pos, Gun_dir, &ConsoleObject->pos); + + if (best_gun_num != -1) { + int rand_prob, count; + vms_vector vec_to_goal; + fix dist_to_player; + fix delta_fire_time; + + if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) { + vm_vec_sub(&vec_to_goal, &Believed_player_pos, &Gun_pos[best_gun_num]); + dist_to_player = vm_vec_normalize_quick(&vec_to_goal); + } else { + vm_vec_sub(&vec_to_goal, &ConsoleObject->pos, &Gun_pos[best_gun_num]); + dist_to_player = vm_vec_normalize_quick(&vec_to_goal); + } + + if (dist_to_player > F1_0*300) + { + Control_center_been_hit = 0; + Control_center_player_been_seen = 0; + return; + } + + #ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_controlcen_fire(&vec_to_goal, best_gun_num, obj-Objects); + #endif + Laser_create_new_easy( &vec_to_goal, &Gun_pos[best_gun_num], obj-Objects, CONTROLCEN_WEAPON_NUM, 1); + + // some of time, based on level, fire another thing, not directly at player, so it might hit him if he's constantly moving. + rand_prob = F1_0/(abs(Current_level_num)/4+2); + count = 0; + while ((d_rand() > rand_prob) && (count < 4)) { + vms_vector randvec; + + make_random_vector(&randvec); + vm_vec_scale_add2(&vec_to_goal, &randvec, F1_0/6); + vm_vec_normalize_quick(&vec_to_goal); + #ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_controlcen_fire(&vec_to_goal, best_gun_num, obj-Objects); + #endif + Laser_create_new_easy( &vec_to_goal, &Gun_pos[best_gun_num], obj-Objects, CONTROLCEN_WEAPON_NUM, 0); + count++; + } + + delta_fire_time = (NDL - Difficulty_level) * F1_0/4; + if (Difficulty_level == 0) + delta_fire_time += F1_0/2; + + if (Game_mode & GM_MULTI) // slow down rate of fire in multi player + delta_fire_time *= 2; + + Control_center_next_fire_time = delta_fire_time; + + } + } else + Control_center_next_fire_time -= FrameTime; + +} + +int Reactor_strength=-1; //-1 mean not set by designer + +// ----------------------------------------------------------------------------- +// This must be called at the start of each level. +// If this level contains a boss and mode != multiplayer, don't do control center stuff. (Ghost out control center object.) +// If this level contains a boss and mode == multiplayer, do control center stuff. +void init_controlcen_for_level(void) +{ + int i; + object *objp; + int cntrlcen_objnum=-1, boss_objnum=-1; + + for (i=0; i<=Highest_object_index; i++) { + objp = &Objects[i]; + if (objp->type == OBJ_CNTRLCEN) + { + if (cntrlcen_objnum != -1) + mprintf((1, "Warning: Two or more control centers including %i and %i\n", i, cntrlcen_objnum)); + else + cntrlcen_objnum = i; + } + + if ((objp->type == OBJ_ROBOT) && (Robot_info[objp->id].boss_flag)) { +// mprintf((0, "Found boss robot %d.\n", objp->id)); + if (boss_objnum != -1) + mprintf((1, "Warning: Two or more bosses including %i and %i\n", i, boss_objnum)); + else + boss_objnum = i; + } + } + +#ifndef NDEBUG + if (cntrlcen_objnum == -1) { + mprintf((1, "Warning: No control center.\n")); + return; + } +#endif + + if ( (boss_objnum != -1) && !((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_ROBOTS)) ) { + if (cntrlcen_objnum != -1) { +// mprintf((0, "Ghosting control center\n")); + Objects[cntrlcen_objnum].type = OBJ_GHOST; + Objects[cntrlcen_objnum].render_type = RT_NONE; + Control_center_present = 0; + } + } else { + // Compute all gun positions. + objp = &Objects[cntrlcen_objnum]; + N_controlcen_guns = Reactors[objp->id].n_guns; + for (i=0; i= 0) + objp->shields = F1_0*200 + (F1_0*200/4) * Current_level_num; + else + objp->shields = F1_0*200 - Current_level_num*F1_0*150; + } + else { + objp->shields = i2f(Reactor_strength); + } + + } + + // Say the control center has not yet been hit. + Control_center_been_hit = 0; + Control_center_player_been_seen = 0; + Control_center_next_fire_time = 0; + + Dead_controlcen_object_num = -1; +} + +void special_reactor_stuff(void) +{ + mprintf((0, "Mucking with reactor countdown time.\n")); + if (Control_center_destroyed) { + Countdown_timer += i2f(Base_control_center_explosion_time + (NDL-1-Difficulty_level)*Base_control_center_explosion_time/(NDL-1)); + Total_countdown_time = f2i(Countdown_timer)+2; // Will prevent "Self destruct sequence activated" message from replaying. + } +} + diff --git a/main/cntrlcen.h b/main/cntrlcen.h new file mode 100644 index 00000000..8cb1c8f7 --- /dev/null +++ b/main/cntrlcen.h @@ -0,0 +1,77 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifndef _CNTRLCEN_H +#define _CNTRLCEN_H + +#include "vecmat.h" +#include "object.h" +#include "wall.h" +//#include "switch.h" + +#define MAX_CONTROLCEN_GUNS 8 + +#define CONTROLCEN_WEAPON_NUM 6 + +#define MAX_CONTROLCEN_LINKS 10 + +typedef struct control_center_triggers { + short num_links; + short seg[MAX_CONTROLCEN_LINKS]; + short side[MAX_CONTROLCEN_LINKS]; +} __pack__ control_center_triggers; + +extern control_center_triggers ControlCenterTriggers; + +typedef struct reactor { + int model_num; + int n_guns; + vms_vector gun_points[MAX_CONTROLCEN_GUNS]; + vms_vector gun_dirs[MAX_CONTROLCEN_GUNS]; +} __pack__ reactor; + +#define MAX_REACTORS 7 + +extern int Num_reactors; + +extern reactor Reactors[MAX_REACTORS]; + +//@@extern int N_controlcen_guns; +extern int Control_center_been_hit; +extern int Control_center_player_been_seen; +extern int Control_center_next_fire_time; +extern int Control_center_present; +extern int Dead_controlcen_object_num; + +//@@extern vms_vector controlcen_gun_points[MAX_CONTROLCEN_GUNS]; +//@@extern vms_vector controlcen_gun_dirs[MAX_CONTROLCEN_GUNS]; +extern vms_vector Gun_pos[MAX_CONTROLCEN_GUNS]; + +//do whatever this thing does in a frame +extern void do_controlcen_frame(object *obj); + +// Initialize control center for a level. +// Call when a new level is started. +extern void init_controlcen_for_level(void); + +extern void do_controlcen_destroyed_stuff(object *objp); +extern void do_controlcen_dead_frame(void); + +#define DEFAULT_CONTROL_CENTER_EXPLOSION_TIME 30 // Note: Usually uses Alan_pavlish_reactor_times, but can be overridden in editor. + +extern fix Countdown_timer; +extern int Control_center_destroyed,Countdown_seconds_left; +extern int Base_control_center_explosion_time; //how long to blow up on insane +extern int Reactor_strength; + +#endif diff --git a/main/collide.c b/main/collide.c new file mode 100644 index 00000000..30cb47b2 --- /dev/null +++ b/main/collide.c @@ -0,0 +1,2660 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + +#ifdef RCS +static char rcsid[] = "$Id: collide.c,v 1.1.1.1 2001-01-19 03:30:00 bradleyb Exp $"; +#endif + +#include +#include // for memset +#include +#include + +#include "rle.h" +#include "inferno.h" +#include "game.h" +#include "gr.h" +#include "stdlib.h" +#include "bm.h" +//#include "error.h" +#include "mono.h" +#include "3d.h" +#include "segment.h" +#include "texmap.h" +#include "laser.h" +#include "key.h" +#include "gameseg.h" +#include "object.h" +#include "physics.h" +#include "slew.h" +#include "render.h" +#include "wall.h" +#include "vclip.h" +#include "polyobj.h" +#include "fireball.h" +#include "laser.h" +#include "error.h" +#include "ai.h" +#include "hostage.h" +#include "fuelcen.h" +#include "sounds.h" +#include "robot.h" +#include "weapon.h" +#include "player.h" +#include "gauges.h" +#include "powerup.h" +#include "network.h" +#include "newmenu.h" +#include "scores.h" +#include "effects.h" +#include "textures.h" +#include "multi.h" +#include "cntrlcen.h" +#include "newdemo.h" +#include "endlevel.h" +#include "multibot.h" +#include "piggy.h" +#include "text.h" +#include "automap.h" +#include "switch.h" +#include "palette.h" + +#ifdef TACTILE +#include "tactile.h" +#endif + +#ifdef EDITOR +#include "editor\editor.h" +#endif + +#include "collide.h" + +#define STANDARD_EXPL_DELAY (f1_0/4) + +//##void collide_fireball_and_wall(object *fireball,fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) { +//## return; +//##} + +// ------------------------------------------------------------------------------------------------------------- +// The only reason this routine is called (as of 10/12/94) is so Brain guys can open doors. +void collide_robot_and_wall( object * robot, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) +{ + ai_local *ailp = &Ai_local_info[robot-Objects]; + + if ((robot->id == ROBOT_BRAIN) || (robot->ctype.ai_info.behavior == AIB_RUN_FROM) || (Robot_info[robot->id].companion == 1) || (robot->ctype.ai_info.behavior == AIB_SNIPE)) { + int wall_num = Segments[hitseg].sides[hitwall].wall_num; + if (wall_num != -1) { + if ((Walls[wall_num].type == WALL_DOOR) && (Walls[wall_num].keys == KEY_NONE) && (Walls[wall_num].state == WALL_DOOR_CLOSED) && !(Walls[wall_num].flags & WALL_DOOR_LOCKED)) { + // -- mprintf((0, "Trying to open door at segment %i, side %i\n", hitseg, hitwall)); + wall_open_door(&Segments[hitseg], hitwall); + // -- Changed from this, 10/19/95, MK: Don't want buddy getting stranded from player + //-- } else if ((Robot_info[robot->id].companion == 1) && (Walls[wall_num].type == WALL_DOOR) && (Walls[wall_num].keys != KEY_NONE) && (Walls[wall_num].state == WALL_DOOR_CLOSED) && !(Walls[wall_num].flags & WALL_DOOR_LOCKED)) { + } else if ((Robot_info[robot->id].companion == 1) && (Walls[wall_num].type == WALL_DOOR)) { + if ((ailp->mode == AIM_GOTO_PLAYER) || (Escort_special_goal == ESCORT_GOAL_SCRAM)) { + if (Walls[wall_num].keys != KEY_NONE) { + if (Walls[wall_num].keys & Players[Player_num].flags) + wall_open_door(&Segments[hitseg], hitwall); + } else if (!(Walls[wall_num].flags & WALL_DOOR_LOCKED)) + wall_open_door(&Segments[hitseg], hitwall); + } + } else if (Robot_info[robot->id].thief) { // Thief allowed to go through doors to which player has key. + if (Walls[wall_num].keys != KEY_NONE) + if (Walls[wall_num].keys & Players[Player_num].flags) + wall_open_door(&Segments[hitseg], hitwall); + } + } + } + + return; +} + +//##void collide_hostage_and_wall( object * hostage, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) { +//## return; +//##} + +// ------------------------------------------------------------------------------------------------------------- + +int apply_damage_to_clutter(object *clutter, fix damage) +{ + if ( clutter->flags&OF_EXPLODING) return 0; + + if (clutter->shields < 0 ) return 0; //clutter already dead... + + clutter->shields -= damage; + + if (clutter->shields < 0) { + explode_object(clutter,0); + return 1; + } else + return 0; +} + +char Monster_mode = 0; // A cheat. Do massive damage when collide. + +//given the specified force, apply damage from that force to an object +void apply_force_damage(object *obj,fix force,object *other_obj) +{ + int result; + fix damage; + + if (obj->flags & (OF_EXPLODING|OF_SHOULD_BE_DEAD)) + return; //already exploding or dead + + damage = fixdiv(force,obj->mtype.phys_info.mass) / 8; + + if ((other_obj->type == OBJ_PLAYER) && Monster_mode) + damage = 0x7fffffff; + +//mprintf((0,"obj %d, damage=%x\n",obj-Objects,damage)); + + switch (obj->type) { + + case OBJ_ROBOT: + + if (Robot_info[obj->id].attack_type == 1) { + if (other_obj->type == OBJ_WEAPON) + result = apply_damage_to_robot(obj,damage/4, other_obj->ctype.laser_info.parent_num); + else + result = apply_damage_to_robot(obj,damage/4, other_obj-Objects); + } + else { + if (other_obj->type == OBJ_WEAPON) + result = apply_damage_to_robot(obj,damage/2, other_obj->ctype.laser_info.parent_num); + else + result = apply_damage_to_robot(obj,damage/2, other_obj-Objects); + } + + if (result && (other_obj->ctype.laser_info.parent_signature == ConsoleObject->signature)) + add_points_to_score(Robot_info[obj->id].score_value); + break; + + case OBJ_PLAYER: + + // If colliding with a claw type robot, do damage proportional to FrameTime because you can collide with those + // bots every frame since they don't move. + if ( (other_obj->type == OBJ_ROBOT) && (Robot_info[other_obj->id].attack_type) ) + damage = fixmul(damage, FrameTime*2); + + // Make trainee easier. + if (Difficulty_level == 0) + damage /= 2; + + apply_damage_to_player(obj,other_obj,damage); + break; + + case OBJ_CLUTTER: + + apply_damage_to_clutter(obj,damage); + break; + + case OBJ_CNTRLCEN: + + apply_damage_to_controlcen(obj,damage, other_obj-Objects); + break; + + case OBJ_WEAPON: + + break; //weapons don't take damage + + default: + + Int3(); + + } +} + +// ----------------------------------------------------------------------------- +void bump_this_object(object *objp, object *other_objp, vms_vector *force, int damage_flag) +{ + fix force_mag; + + if (! (objp->mtype.phys_info.flags & PF_PERSISTENT)) + { + if (objp->type == OBJ_PLAYER) { + vms_vector force2; + force2.x = force->x/4; + force2.y = force->y/4; + force2.z = force->z/4; + phys_apply_force(objp,&force2); + if (damage_flag && ((other_objp->type != OBJ_ROBOT) || !Robot_info[other_objp->id].companion)) { + force_mag = vm_vec_mag_quick(&force2); + apply_force_damage(objp, force_mag, other_objp); + } + } else if ((objp->type == OBJ_ROBOT) || (objp->type == OBJ_CLUTTER) || (objp->type == OBJ_CNTRLCEN)) { + if (!Robot_info[objp->id].boss_flag) { + vms_vector force2; + force2.x = force->x/(4 + Difficulty_level); + force2.y = force->y/(4 + Difficulty_level); + force2.z = force->z/(4 + Difficulty_level); + + phys_apply_force(objp, force); + phys_apply_rot(objp, &force2); + if (damage_flag) { + force_mag = vm_vec_mag_quick(force); + apply_force_damage(objp, force_mag, other_objp); + } + } + } + } +} + +// ----------------------------------------------------------------------------- +//deal with two objects bumping into each other. Apply force from collision +//to each robot. The flags tells whether the objects should take damage from +//the collision. +void bump_two_objects(object *obj0,object *obj1,int damage_flag) +{ + vms_vector force; + object *t=NULL; + + if (obj0->movement_type != MT_PHYSICS) + t=obj1; + else if (obj1->movement_type != MT_PHYSICS) + t=obj0; + + if (t) { + Assert(t->movement_type == MT_PHYSICS); + vm_vec_copy_scale(&force,&t->mtype.phys_info.velocity,-t->mtype.phys_info.mass); + phys_apply_force(t,&force); + return; + } + + vm_vec_sub(&force,&obj0->mtype.phys_info.velocity,&obj1->mtype.phys_info.velocity); + vm_vec_scale2(&force,2*fixmul(obj0->mtype.phys_info.mass,obj1->mtype.phys_info.mass),(obj0->mtype.phys_info.mass+obj1->mtype.phys_info.mass)); + + bump_this_object(obj1, obj0, &force, damage_flag); + vm_vec_negate(&force); + bump_this_object(obj0, obj1, &force, damage_flag); + +} + +void bump_one_object(object *obj0, vms_vector *hit_dir, fix damage) +{ + vms_vector hit_vec; + + hit_vec = *hit_dir; + vm_vec_scale(&hit_vec, damage); + + phys_apply_force(obj0,&hit_vec); + +} + +#define DAMAGE_SCALE 128 // Was 32 before 8:55 am on Thursday, September 15, changed by MK, walls were hurting me more than robots! +#define DAMAGE_THRESHOLD (F1_0/3) +#define WALL_LOUDNESS_SCALE (20) + +fix force_force = i2f(50); + +void collide_player_and_wall( object * playerobj, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) +{ + fix damage; + char ForceFieldHit=0; + int tmap_num,tmap_num2; + + if (playerobj->id != Player_num) // Execute only for local player + return; + + tmap_num = Segments[hitseg].sides[hitwall].tmap_num; + + // If this wall does damage, don't make *BONK* sound, we'll be making another sound. + if (TmapInfo[tmap_num].damage > 0) + return; + + if (TmapInfo[tmap_num].flags & TMI_FORCE_FIELD) { + vms_vector force; + + PALETTE_FLASH_ADD(0, 0, 60); //flash blue + + //knock player around + force.x = 40*(d_rand() - 16384); + force.y = 40*(d_rand() - 16384); + force.z = 40*(d_rand() - 16384); + phys_apply_rot(playerobj, &force); + +#ifdef TACTILE + if (TactileStick) + Tactile_apply_force (&force,&playerobj->orient); +#endif + + //make sound + digi_link_sound_to_pos( SOUND_FORCEFIELD_BOUNCE_PLAYER, hitseg, 0, hitpt, 0, f1_0 ); +#ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_play_sound(SOUND_FORCEFIELD_BOUNCE_PLAYER, f1_0); +#endif + ForceFieldHit=1; + } + else { + + #ifdef TACTILE + vms_vector force; + if (TactileStick) { + force.x = -playerobj->mtype.phys_info.velocity.x; + force.y = -playerobj->mtype.phys_info.velocity.y; + force.z = -playerobj->mtype.phys_info.velocity.z; + Tactile_do_collide(&force, &playerobj->orient); + } + #endif + + wall_hit_process( &Segments[hitseg], hitwall, 20, playerobj->id, playerobj ); + } + + // ** Damage from hitting wall ** + // If the player has less than 10% shields, don't take damage from bump + // Note: Does quad damage if hit a force field - JL + damage = (hitspeed / DAMAGE_SCALE) * (ForceFieldHit*8 + 1); + + tmap_num2 = Segments[hitseg].sides[hitwall].tmap_num2; + + //don't do wall damage and sound if hit lava or water + if ((TmapInfo[tmap_num].flags & (TMI_WATER|TMI_VOLATILE)) || (tmap_num2 && (TmapInfo[tmap_num2&0x3fff].flags & (TMI_WATER|TMI_VOLATILE)))) + damage = 0; + + if (damage >= DAMAGE_THRESHOLD) { + int volume; + volume = (hitspeed-(DAMAGE_SCALE*DAMAGE_THRESHOLD)) / WALL_LOUDNESS_SCALE ; + + create_awareness_event(playerobj, PA_WEAPON_WALL_COLLISION); + + if ( volume > F1_0 ) + volume = F1_0; + if (volume > 0 && !ForceFieldHit) { // uhhhgly hack + digi_link_sound_to_pos( SOUND_PLAYER_HIT_WALL, hitseg, 0, hitpt, 0, volume ); + #ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_play_sound(SOUND_PLAYER_HIT_WALL, volume); + #endif + } + + if (!(Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE)) + if ( Players[Player_num].shields > f1_0*10 || ForceFieldHit) + apply_damage_to_player( playerobj, playerobj, damage ); + + // -- No point in doing this unless we compute a reasonable hitpt. Currently it is just the player's position. --MK, 01/18/96 + // -- if (!(TmapInfo[Segments[hitseg].sides[hitwall].tmap_num].flags & TMI_FORCE_FIELD)) { + // -- vms_vector hitpt1; + // -- int hitseg1; + // -- + // -- vm_vec_avg(&hitpt1, hitpt, &Objects[Players[Player_num].objnum].pos); + // -- hitseg1 = find_point_seg(&hitpt1, Objects[Players[Player_num].objnum].segnum); + // -- if (hitseg1 != -1) + // -- object_create_explosion( hitseg, hitpt, Weapon_info[0].impact_size, Weapon_info[0].wall_hit_vclip ); + // -- } + + } + + return; +} + +fix Last_volatile_scrape_sound_time = 0; + +void collide_weapon_and_wall( object * weapon, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt); +void collide_debris_and_wall( object * debris, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt); + +//see if wall is volatile or water +//if volatile, cause damage to player +//returns 1=lava, 2=water +int check_volatile_wall(object *obj,int segnum,int sidenum,vms_vector *hitpt) +{ + fix tmap_num,d,water; + + Assert(obj->type==OBJ_PLAYER); + + tmap_num = Segments[segnum].sides[sidenum].tmap_num; + + d = TmapInfo[tmap_num].damage; + water = (TmapInfo[tmap_num].flags & TMI_WATER); + + if (d > 0 || water) { + + if (obj->id == Player_num) { + + if (d > 0) { + fix damage = fixmul(d,FrameTime); + + if (Difficulty_level == 0) + damage /= 2; + + if (!(Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE)) + apply_damage_to_player( obj, obj, damage ); + +#ifdef TACTILE + if (TactileStick) + Tactile_Xvibrate (50,25); +#endif + + PALETTE_FLASH_ADD(f2i(damage*4), 0, 0); //flash red + } + + obj->mtype.phys_info.rotvel.x = (d_rand() - 16384)/2; + obj->mtype.phys_info.rotvel.z = (d_rand() - 16384)/2; + } + + return (d>0)?1:2; + } + else + { +#ifdef TACTILE + if (TactileStick && !(FrameCount & 15)) + Tactile_Xvibrate_clear (); +#endif + + return 0; + } +} + +//this gets called when an object is scraping along the wall +void scrape_object_on_wall(object *obj, short hitseg, short hitside, vms_vector * hitpt ) +{ + switch (obj->type) { + + case OBJ_PLAYER: + + if (obj->id==Player_num) { + int type; + + //mprintf((0, "Scraped segment #%3i, side #%i\n", hitseg, hitside)); + + if ((type=check_volatile_wall(obj,hitseg,hitside,hitpt))!=0) { + vms_vector hit_dir, rand_vec; + + if ((GameTime > Last_volatile_scrape_sound_time + F1_0/4) || (GameTime < Last_volatile_scrape_sound_time)) { + int sound = (type==1)?SOUND_VOLATILE_WALL_HISS:SOUND_SHIP_IN_WATER; + + Last_volatile_scrape_sound_time = GameTime; + + digi_link_sound_to_pos( sound, hitseg, 0, hitpt, 0, F1_0 ); +#ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_play_sound(sound, F1_0); +#endif + } + + #ifdef COMPACT_SEGS + get_side_normal(&Segments[hitseg], higside, 0, &hit_dir ); + #else + hit_dir = Segments[hitseg].sides[hitside].normals[0]; + #endif + + make_random_vector(&rand_vec); + vm_vec_scale_add2(&hit_dir, &rand_vec, F1_0/8); + vm_vec_normalize_quick(&hit_dir); + bump_one_object(obj, &hit_dir, F1_0*8); + } + + //@@} else { + //@@ //what scrape sound + //@@ //PLAY_SOUND( SOUND_PLAYER_SCRAPE_WALL ); + //@@} + + } + + break; + + //these two kinds of objects below shouldn't really slide, so + //if this scrape routine gets called (which it might if the + //object (such as a fusion blob) was created already poking + //through the wall) call the collide routine. + + case OBJ_WEAPON: + collide_weapon_and_wall(obj,0,hitseg,hitside,hitpt); + break; + + case OBJ_DEBRIS: + collide_debris_and_wall(obj,0,hitseg,hitside,hitpt); + break; + } + +} + +//if an effect is hit, and it can blow up, then blow it up +//returns true if it blew up +int check_effect_blowup(segment *seg,int side,vms_vector *pnt, object *blower, int force_blowup_flag) +{ + int tm,tmf,ec,db; + + // If this wall has a trigger and the blower-upper is not the player or the buddy, abort! + { + int ok_to_blow = 0; + + if (blower->ctype.laser_info.parent_type == OBJ_ROBOT) + if (Robot_info[Objects[blower->ctype.laser_info.parent_num].id].companion) + ok_to_blow = 1; + + if (!(ok_to_blow || (blower->ctype.laser_info.parent_type == OBJ_PLAYER))) { + int trigger_num, wall_num; + + wall_num = seg->sides[side].wall_num; + if ( wall_num != -1 ) { + trigger_num = Walls[wall_num].trigger; + + if (trigger_num != -1) + return 0; + } + } + } + + + if ((tm=seg->sides[side].tmap_num2) != 0) { + + tmf = tm&0xc000; //tm flags + tm &= 0x3fff; //tm without flags + + //check if it's an animation (monitor) or casts light + if ((((ec=TmapInfo[tm].eclip_num)!=-1) && ((db=Effects[ec].dest_bm_num)!=-1 && !(Effects[ec].flags&EF_ONE_SHOT))) || (ec==-1 && (TmapInfo[tm].destroyed!=-1))) { + fix u,v; + grs_bitmap *bm = &GameBitmaps[Textures[tm].index]; + int x,y,t; + + PIGGY_PAGE_IN(Textures[tm]); + + //this can be blown up...did we hit it? + + if (!force_blowup_flag) { + find_hitpoint_uv(&u,&v,NULL,pnt,seg,side,0); //evil: always say face zero + + x = ((unsigned) f2i(u*bm->bm_w)) % bm->bm_w; + y = ((unsigned) f2i(v*bm->bm_h)) % bm->bm_h; + + switch (tmf) { //adjust for orientation of paste-on + case 0x0000: break; + case 0x4000: t=y; y=x; x=bm->bm_w-t-1; break; + case 0x8000: y=bm->bm_h-y-1; x=bm->bm_w-x-1; break; + case 0xc000: t=x; x=y; y=bm->bm_h-t-1; break; + } + + //mprintf((0,"u,v = %x,%x x,y=%x,%x",u,v,x,y)); + + if (bm->bm_flags & BM_FLAG_RLE) + bm = rle_expand_texture(bm); + } + + if (force_blowup_flag || (bm->bm_data[y*bm->bm_w+x] != TRANSPARENCY_COLOR)) { //not trans, thus on effect + int vc,sound_num; + fix dest_size; + + +#ifdef NETWORK + if ((Game_mode & GM_MULTI) && Netgame.AlwaysLighting) + if (!(ec!=-1 && db!=-1 && !(Effects[ec].flags&EF_ONE_SHOT))) + return(0); +#endif + + //mprintf((0," HIT!\n")); + + //note: this must get called before the texture changes, + //because we use the light value of the texture to change + //the static light in the segment + subtract_light(seg-Segments,side); + + if (Newdemo_state == ND_STATE_RECORDING) + newdemo_record_effect_blowup( seg-Segments, side, pnt); + + if (ec!=-1) { + dest_size = Effects[ec].dest_size; + vc = Effects[ec].dest_vclip; + } else { + dest_size = i2f(20); + vc = 3; + } + + object_create_explosion( seg-Segments, pnt, dest_size, vc ); + + if (ec!=-1 && db!=-1 && !(Effects[ec].flags&EF_ONE_SHOT)) { + + if ((sound_num = Vclip[vc].sound_num) != -1) + digi_link_sound_to_pos( sound_num, seg-Segments, 0, pnt, 0, F1_0 ); + + if ((sound_num=Effects[ec].sound_num)!=-1) //kill sound + digi_kill_sound_linked_to_segment(seg-Segments,side,sound_num); + + if (Effects[ec].dest_eclip!=-1 && Effects[Effects[ec].dest_eclip].segnum==-1) { + int bm_num; + eclip *new_ec; + + new_ec = &Effects[Effects[ec].dest_eclip]; + bm_num = new_ec->changing_wall_texture; + + mprintf((0,"bm_num = %d\n",bm_num)); + + new_ec->time_left = new_ec->vc.frame_time; + new_ec->frame_count = 0; + new_ec->segnum = seg-Segments; + new_ec->sidenum = side; + new_ec->flags |= EF_ONE_SHOT; + new_ec->dest_bm_num = Effects[ec].dest_bm_num; + + Assert(bm_num!=0 && seg->sides[side].tmap_num2!=0); + seg->sides[side].tmap_num2 = bm_num | tmf; //replace with destoyed + + } + else { + Assert(db!=0 && seg->sides[side].tmap_num2!=0); + seg->sides[side].tmap_num2 = db | tmf; //replace with destoyed + } + } + else { + seg->sides[side].tmap_num2 = TmapInfo[tm].destroyed | tmf; + + //assume this is a light, and play light sound + digi_link_sound_to_pos( SOUND_LIGHT_BLOWNUP, seg-Segments, 0, pnt, 0, F1_0 ); + } + + + return 1; //blew up! + } + } + } + + return 0; //didn't blow up +} + +// Copied from laser.c! +#define MIN_OMEGA_BLOBS 3 // No matter how close the obstruction, at this many blobs created. +#define MIN_OMEGA_DIST (F1_0*3) // At least this distance between blobs, unless doing so would violate MIN_OMEGA_BLOBS +#define DESIRED_OMEGA_DIST (F1_0*5) // This is the desired distance between blobs. For distances > MIN_OMEGA_BLOBS*DESIRED_OMEGA_DIST, but not very large, this will apply. +#define MAX_OMEGA_BLOBS 16 // No matter how far away the obstruction, this is the maximum number of blobs. +#define MAX_OMEGA_DIST (MAX_OMEGA_BLOBS * DESIRED_OMEGA_DIST) // Maximum extent of lightning blobs. + +// ------------------------------------------------- +// Return true if ok to do Omega damage. +int ok_to_do_omega_damage(object *weapon) +{ + int parent_sig = weapon->ctype.laser_info.parent_signature; + int parent_num = weapon->ctype.laser_info.parent_num; + + if (!(Game_mode & GM_MULTI)) + return 1; + + if (Objects[parent_num].signature != parent_sig) + mprintf((0, "Parent of omega blob not consistent with object information.\n")); + else { + fix dist = vm_vec_dist_quick(&Objects[parent_num].pos, &weapon->pos); + + if (dist > MAX_OMEGA_DIST) { + // -- mprintf((0, "Not doing damage in frame %i, too far away.\n", FrameCount)); + return 0; + } else + ; // -- mprintf((0, "*** Doing damage in frame %i ***\n", FrameCount)); + } + + return 1; +} + +//these gets added to the weapon's values when the weapon hits a volitle wall +#define VOLATILE_WALL_EXPL_STRENGTH i2f(10) +#define VOLATILE_WALL_IMPACT_SIZE i2f(3) +#define VOLATILE_WALL_DAMAGE_FORCE i2f(5) +#define VOLATILE_WALL_DAMAGE_RADIUS i2f(30) + +// int Show_seg_and_side = 0; + +void collide_weapon_and_wall( object * weapon, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) +{ + segment *seg = &Segments[hitseg]; + int blew_up; + int wall_type; + int playernum; + int robot_escort; + + if (weapon->id == OMEGA_ID) + if (!ok_to_do_omega_damage(weapon)) + return; + + // If this is a guided missile and it strikes fairly directly, clear bounce flag. + if (weapon->id == GUIDEDMISS_ID) { + fix dot; + + dot = vm_vec_dot(&weapon->orient.fvec, &Segments[hitseg].sides[hitwall].normals[0]); + mprintf((0, "Guided missile dot = %7.3f\n", f2fl(dot))); + if (dot < -F1_0/6) { + mprintf((0, "Guided missile loses bounciness.\n")); + weapon->mtype.phys_info.flags &= ~PF_BOUNCE; + } + } + + //if an energy weapon hits a forcefield, let it bounce + if ((TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_FORCE_FIELD) && + !(weapon->type == OBJ_WEAPON && Weapon_info[weapon->id].energy_usage==0)) { + + //make sound + digi_link_sound_to_pos( SOUND_FORCEFIELD_BOUNCE_WEAPON, hitseg, 0, hitpt, 0, f1_0 ); +#ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_play_sound(SOUND_FORCEFIELD_BOUNCE_WEAPON, f1_0); +#endif + + return; //bail here. physics code will bounce this object + } + + #ifndef NDEBUG + if (keyd_pressed[KEY_LAPOSTRO]) + if (weapon->ctype.laser_info.parent_num == Players[Player_num].objnum) { + // MK: Real pain when you need to know a seg:side and you've got quad lasers. + mprintf((0, "Your laser hit at segment = %i, side = %i\n", hitseg, hitwall)); + HUD_init_message("Hit at segment = %i, side = %i", hitseg, hitwall); + if (weapon->id < 4) + subtract_light(hitseg, hitwall); + else if (weapon->id == FLARE_ID) + add_light(hitseg, hitwall); + } + + //@@#ifdef EDITOR + //@@Cursegp = &Segments[hitseg]; + //@@Curside = hitwall; + //@@#endif + #endif + + if ((weapon->mtype.phys_info.velocity.x == 0) && (weapon->mtype.phys_info.velocity.y == 0) && (weapon->mtype.phys_info.velocity.z == 0)) { + Int3(); // Contact Matt: This is impossible. A weapon with 0 velocity hit a wall, which doesn't move. + return; + } + + blew_up = check_effect_blowup(seg,hitwall,hitpt, weapon, 0); + + //if ((seg->sides[hitwall].tmap_num2==0) && (TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_VOLATILE)) { + + if ((weapon->ctype.laser_info.parent_type == OBJ_ROBOT) && (Robot_info[Objects[weapon->ctype.laser_info.parent_num].id].companion==1)) { + robot_escort = 1; + + if (Game_mode & GM_MULTI) + { + Int3(); // Get Jason! + return; + } + + + playernum = Player_num; //if single player, he's the player's buddy + } + else { + robot_escort = 0; + + if (Objects[weapon->ctype.laser_info.parent_num].type == OBJ_PLAYER) + playernum = Objects[weapon->ctype.laser_info.parent_num].id; + else + playernum = -1; //not a player (thus a robot) + } + + if (blew_up) { //could be a wall switch + //for wall triggers, always say that the player shot it out. This is + //because robots can shoot out wall triggers, and so the trigger better + //take effect + // NO -- Changed by MK, 10/18/95. We don't want robots blowing puzzles. Only player or buddy can open! + check_trigger(seg,hitwall,weapon->ctype.laser_info.parent_num,1); + } + + if (weapon->id == EARTHSHAKER_ID) + smega_rock_stuff(); + + wall_type = wall_hit_process( seg, hitwall, weapon->shields, playernum, weapon ); + + // Wall is volatile if either tmap 1 or 2 is volatile + if ((TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_VOLATILE) || (seg->sides[hitwall].tmap_num2 && (TmapInfo[seg->sides[hitwall].tmap_num2&0x3fff].flags & TMI_VOLATILE))) { + weapon_info *wi = &Weapon_info[weapon->id]; + int vclip; + + //we've hit a volatile wall + + digi_link_sound_to_pos( SOUND_VOLATILE_WALL_HIT,hitseg, 0, hitpt, 0, F1_0 ); + + //for most weapons, use volatile wall hit. For mega, use its special vclip + vclip = (weapon->id == MEGA_ID)?Weapon_info[weapon->id].robot_hit_vclip:VCLIP_VOLATILE_WALL_HIT; + + // New by MK: If powerful badass, explode as badass, not due to lava, fixes megas being wimpy in lava. + if (wi->damage_radius >= VOLATILE_WALL_DAMAGE_RADIUS/2) { + // -- mprintf((0, "Big weapon doing badass in lava instead.\n")); + explode_badass_weapon(weapon,hitpt); + } else { + object_create_badass_explosion( weapon, hitseg, hitpt, + wi->impact_size + VOLATILE_WALL_IMPACT_SIZE, + vclip, + wi->strength[Difficulty_level]/4+VOLATILE_WALL_EXPL_STRENGTH, // diminished by mk on 12/08/94, i was doing 70 damage hitting lava on lvl 1. + wi->damage_radius+VOLATILE_WALL_DAMAGE_RADIUS, + wi->strength[Difficulty_level]/2+VOLATILE_WALL_DAMAGE_FORCE, + weapon->ctype.laser_info.parent_num ); + } + + weapon->flags |= OF_SHOULD_BE_DEAD; //make flares die in lava + + } + else if ((TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_WATER) || (seg->sides[hitwall].tmap_num2 && (TmapInfo[seg->sides[hitwall].tmap_num2&0x3fff].flags & TMI_WATER))) { + weapon_info *wi = &Weapon_info[weapon->id]; + + //we've hit water + + // MK: 09/13/95: Badass in water is 1/2 normal intensity. + if ( Weapon_info[weapon->id].matter ) { + + digi_link_sound_to_pos( SOUND_MISSILE_HIT_WATER,hitseg, 0, hitpt, 0, F1_0 ); + + if ( Weapon_info[weapon->id].damage_radius ) { + + digi_link_sound_to_object(SOUND_BADASS_EXPLOSION, weapon-Objects, 0, F1_0); + + // MK: 09/13/95: Badass in water is 1/2 normal intensity. + object_create_badass_explosion( weapon, hitseg, hitpt, + wi->impact_size/2, + wi->robot_hit_vclip, + wi->strength[Difficulty_level]/4, + wi->damage_radius, + wi->strength[Difficulty_level]/2, + weapon->ctype.laser_info.parent_num ); + } + else + object_create_explosion( weapon->segnum, &weapon->pos, Weapon_info[weapon->id].impact_size, Weapon_info[weapon->id].wall_hit_vclip ); + + } else { + digi_link_sound_to_pos( SOUND_LASER_HIT_WATER,hitseg, 0, hitpt, 0, F1_0 ); + object_create_explosion( weapon->segnum, &weapon->pos, Weapon_info[weapon->id].impact_size, VCLIP_WATER_HIT ); + } + + weapon->flags |= OF_SHOULD_BE_DEAD; //make flares die in water + + } + else { + + if (weapon->mtype.phys_info.flags & PF_BOUNCE) { + + //do special bound sound & effect + + } + else { + + //if it's not the player's weapon, or it is the player's and there + //is no wall, and no blowing up monitor, then play sound + if ((weapon->ctype.laser_info.parent_type != OBJ_PLAYER) || ((seg->sides[hitwall].wall_num == -1 || wall_type==WHP_NOT_SPECIAL) && !blew_up)) + if ((Weapon_info[weapon->id].wall_hit_sound > -1 ) && (!(weapon->flags & OF_SILENT))) + digi_link_sound_to_pos( Weapon_info[weapon->id].wall_hit_sound,weapon->segnum, 0, &weapon->pos, 0, F1_0 ); + + if ( Weapon_info[weapon->id].wall_hit_vclip > -1 ) { + if ( Weapon_info[weapon->id].damage_radius ) + explode_badass_weapon(weapon,hitpt); + else + object_create_explosion( weapon->segnum, &weapon->pos, Weapon_info[weapon->id].impact_size, Weapon_info[weapon->id].wall_hit_vclip ); + } + } + } + + // If weapon fired by player or companion... + if (( weapon->ctype.laser_info.parent_type== OBJ_PLAYER ) || robot_escort) { + + if (!(weapon->flags & OF_SILENT) && (weapon->ctype.laser_info.parent_num == Players[Player_num].objnum)) + create_awareness_event(weapon, PA_WEAPON_WALL_COLLISION); // object "weapon" can attract attention to player + +// if (weapon->id != FLARE_ID) { +// We now allow flares to open doors. + { + + if (((weapon->id != FLARE_ID) || (weapon->ctype.laser_info.parent_type != OBJ_PLAYER)) && !(weapon->mtype.phys_info.flags & PF_BOUNCE)) + weapon->flags |= OF_SHOULD_BE_DEAD; + + //don't let flares stick in force fields + if ((weapon->id == FLARE_ID) && (TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_FORCE_FIELD)) + weapon->flags |= OF_SHOULD_BE_DEAD; + + if (!(weapon->flags & OF_SILENT)) { + switch (wall_type) { + + case WHP_NOT_SPECIAL: + //should be handled above + //digi_link_sound_to_pos( Weapon_info[weapon->id].wall_hit_sound, weapon->segnum, 0, &weapon->pos, 0, F1_0 ); + break; + + case WHP_NO_KEY: + //play special hit door sound (if/when we get it) + digi_link_sound_to_pos( SOUND_WEAPON_HIT_DOOR, weapon->segnum, 0, &weapon->pos, 0, F1_0 ); +#ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_play_sound( SOUND_WEAPON_HIT_DOOR, F1_0 ); +#endif + + break; + + case WHP_BLASTABLE: + //play special blastable wall sound (if/when we get it) + if ((Weapon_info[weapon->id].wall_hit_sound > -1 ) && (!(weapon->flags & OF_SILENT))) + digi_link_sound_to_pos( SOUND_WEAPON_HIT_BLASTABLE, weapon->segnum, 0, &weapon->pos, 0, F1_0 ); + break; + + case WHP_DOOR: + //don't play anything, since door open sound will play + break; + } + } // else + //mprintf((0, "Weapon %i hits wall, but has silent bit set.\n", weapon-Objects)); + } // else { + // if (weapon->lifeleft <= 0) + // weapon->flags |= OF_SHOULD_BE_DEAD; + // } + + } else { + // This is a robot's laser + if (!(weapon->mtype.phys_info.flags & PF_BOUNCE)) + weapon->flags |= OF_SHOULD_BE_DEAD; + } + + return; +} + +//##void collide_camera_and_wall( object * camera, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) { +//## return; +//##} + +//##void collide_powerup_and_wall( object * powerup, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) { +//## return; +//##} + +void collide_debris_and_wall( object * debris, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) { + explode_object(debris,0); + return; +} + +//##void collide_fireball_and_fireball( object * fireball1, object * fireball2, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_fireball_and_robot( object * fireball, object * robot, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_fireball_and_hostage( object * fireball, object * hostage, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_fireball_and_player( object * fireball, object * player, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_fireball_and_weapon( object * fireball, object * weapon, vms_vector *collision_point ) { +//## //weapon->flags |= OF_SHOULD_BE_DEAD; +//## return; +//##} + +//##void collide_fireball_and_camera( object * fireball, object * camera, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_fireball_and_powerup( object * fireball, object * powerup, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_fireball_and_debris( object * fireball, object * debris, vms_vector *collision_point ) { +//## return; +//##} + +// ------------------------------------------------------------------------------------------------------------------- +void collide_robot_and_robot( object * robot1, object * robot2, vms_vector *collision_point ) { +// mprintf((0, "Coll: [%2i %4i %4i %4i] [%2i %4i %4i %4i] at [%4i %4i %4i]", +// robot1-Objects, f2i(robot1->pos.x), f2i(robot1->pos.y), f2i(robot1->pos.z), +// robot2-Objects, f2i(robot2->pos.x), f2i(robot2->pos.y), f2i(robot2->pos.z), +// f2i(collision_point->x), f2i(collision_point->y), f2i(collision_point->z))); + + bump_two_objects(robot1, robot2, 1); + return; +} + +void collide_robot_and_controlcen( object * obj1, object * obj2, vms_vector *collision_point ) +{ + + if (obj1->type == OBJ_ROBOT) { + vms_vector hitvec; + vm_vec_normalize_quick(vm_vec_sub(&hitvec, &obj2->pos, &obj1->pos)); + bump_one_object(obj1, &hitvec, 0); + } else { + vms_vector hitvec; + vm_vec_normalize_quick(vm_vec_sub(&hitvec, &obj1->pos, &obj2->pos)); + bump_one_object(obj2, &hitvec, 0); + } + +} + +//##void collide_robot_and_hostage( object * robot, object * hostage, vms_vector *collision_point ) { +//## return; +//##} + +fix Last_thief_hit_time; + +void collide_robot_and_player( object * robot, object * playerobj, vms_vector *collision_point ) +{ + int steal_attempt = 0; + int collision_seg; + + if (robot->flags&OF_EXPLODING) + return; + + collision_seg = find_point_seg(collision_point, playerobj->segnum); + if (collision_seg != -1) + object_create_explosion( collision_seg, collision_point, Weapon_info[0].impact_size, Weapon_info[0].wall_hit_vclip ); + + if (playerobj->id == Player_num) { + if (Robot_info[robot->id].companion) // Player and companion don't collide. + return; + if (Robot_info[robot->id].kamikaze) { + apply_damage_to_robot(robot, robot->shields+1, playerobj-Objects); + if (playerobj == ConsoleObject) + add_points_to_score(Robot_info[robot->id].score_value); + } + + if (Robot_info[robot->id].thief) { + if (Ai_local_info[robot-Objects].mode == AIM_THIEF_ATTACK) { + Last_thief_hit_time = GameTime; + attempt_to_steal_item(robot, playerobj->id); + steal_attempt = 1; + } else if (GameTime - Last_thief_hit_time < F1_0*2) + return; // ZOUNDS! BRILLIANT! Thief not collide with player if not stealing! + // NO! VERY DUMB! makes thief look very stupid if player hits him while cloaked! -AP + else + Last_thief_hit_time = GameTime; + } + + create_awareness_event(playerobj, PA_PLAYER_COLLISION); // object robot can attract attention to player + do_ai_robot_hit_attack(robot, playerobj, collision_point); + do_ai_robot_hit(robot, PA_WEAPON_ROBOT_COLLISION); + } +#ifdef NETWORK + else + multi_robot_request_change(robot, playerobj->id); +#endif + + // added this if to remove the bump sound if it's the thief. + // A "steal" sound was added and it was getting obscured by the bump. -AP 10/3/95 + // Changed by MK to make this sound unless the robot stole. + if ((!steal_attempt) && !Robot_info[robot->id].energy_drain) + digi_link_sound_to_pos( SOUND_ROBOT_HIT_PLAYER, playerobj->segnum, 0, collision_point, 0, F1_0 ); + + bump_two_objects(robot, playerobj, 1); + return; +} + +// Provide a way for network message to instantly destroy the control center +// without awarding points or anything. + +// if controlcen == NULL, that means don't do the explosion because the control center +// was actually in another object. +void net_destroy_controlcen(object *controlcen) +{ + if (Control_center_destroyed != 1) { + + do_controlcen_destroyed_stuff(controlcen); + + if ((controlcen != NULL) && !(controlcen->flags&(OF_EXPLODING|OF_DESTROYED))) { + digi_link_sound_to_pos( SOUND_CONTROL_CENTER_DESTROYED, controlcen->segnum, 0, &controlcen->pos, 0, F1_0 ); + explode_object(controlcen,0); + } + } + +} + +// ----------------------------------------------------------------------------- +void apply_damage_to_controlcen(object *controlcen, fix damage, short who) +{ + int whotype; + + // Only allow a player to damage the control center. + + if ((who < 0) || (who > Highest_object_index)) + return; + + whotype = Objects[who].type; + if (whotype != OBJ_PLAYER) { + mprintf((0, "Damage to control center by object of type %i prevented by MK!\n", whotype)); + return; + } + + #ifdef NETWORK + if ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) && (Players[Player_num].time_level < Netgame.control_invul_time)) + { + if (Objects[who].id == Player_num) { + int secs = f2i(Netgame.control_invul_time-Players[Player_num].time_level) % 60; + int mins = f2i(Netgame.control_invul_time-Players[Player_num].time_level) / 60; + HUD_init_message("%s %d:%02d.", TXT_CNTRLCEN_INVUL, mins, secs); + } + return; + } + #endif + + if (Objects[who].id == Player_num) { + Control_center_been_hit = 1; + ai_do_cloak_stuff(); + } + + if ( controlcen->shields >= 0 ) + controlcen->shields -= damage; + + if ( (controlcen->shields < 0) && !(controlcen->flags&(OF_EXPLODING|OF_DESTROYED)) ) { + + do_controlcen_destroyed_stuff(controlcen); + + #ifdef NETWORK + if (Game_mode & GM_MULTI) { + if (who == Players[Player_num].objnum) + add_points_to_score(CONTROL_CEN_SCORE); + multi_send_destroy_controlcen((ushort)(controlcen-Objects), Objects[who].id ); + } + #endif + + if (!(Game_mode & GM_MULTI)) + add_points_to_score(CONTROL_CEN_SCORE); + + digi_link_sound_to_pos( SOUND_CONTROL_CENTER_DESTROYED, controlcen->segnum, 0, &controlcen->pos, 0, F1_0 ); + + explode_object(controlcen,0); + } +} + +void collide_player_and_controlcen( object * controlcen, object * playerobj, vms_vector *collision_point ) +{ + if (playerobj->id == Player_num) { + Control_center_been_hit = 1; + ai_do_cloak_stuff(); // In case player cloaked, make control center know where he is. + } + + digi_link_sound_to_pos( SOUND_ROBOT_HIT_PLAYER, playerobj->segnum, 0, collision_point, 0, F1_0 ); + bump_two_objects(controlcen, playerobj, 1); + + return; +} + +void collide_player_and_marker( object * marker, object * playerobj, vms_vector *collision_point ) +{ + mprintf ((0,"Collided with marker %d!\n",marker->id)); + + if (playerobj->id==Player_num) { + int drawn; + + if (Game_mode & GM_MULTI) + { + drawn = HUD_init_message ("MARKER %s: %s",Players[marker->id/2].callsign,MarkerMessage[marker->id]); + } + else + { + if (MarkerMessage[marker->id][0]) + drawn = HUD_init_message("MARKER %d: %s", marker->id+1,MarkerMessage[marker->id]); + else + drawn = HUD_init_message("MARKER %d", marker->id+1); + } + + if (drawn) + digi_play_sample( SOUND_MARKER_HIT, F1_0 ); + + detect_escort_goal_accomplished(marker-Objects); + } +} + +// If a persistent weapon and other object is not a weapon, weaken it, else kill it. +// If both objects are weapons, weaken the weapon. +void maybe_kill_weapon(object *weapon, object *other_obj) +{ + if ((weapon->id == PROXIMITY_ID) || (weapon->id == SUPERPROX_ID) || (weapon->id == PMINE_ID)) { + weapon->flags |= OF_SHOULD_BE_DEAD; + return; + } + + // Changed, 10/12/95, MK: Make weapon-weapon collisions always kill both weapons if not persistent. + // Reason: Otherwise you can't use proxbombs to detonate incoming homing missiles (or mega missiles). + if (weapon->mtype.phys_info.flags & PF_PERSISTENT) { + // Weapons do a lot of damage to weapons, other objects do much less. + if (!(weapon->mtype.phys_info.flags & PF_PERSISTENT)) { + if (other_obj->type == OBJ_WEAPON) + weapon->shields -= other_obj->shields/2; + else + weapon->shields -= other_obj->shields/4; + + if (weapon->shields <= 0) { + weapon->shields = 0; + weapon->flags |= OF_SHOULD_BE_DEAD; // weapon->lifeleft = 1; + } + } + } else + weapon->flags |= OF_SHOULD_BE_DEAD; // weapon->lifeleft = 1; + +// -- if ((weapon->mtype.phys_info.flags & PF_PERSISTENT) || (other_obj->type == OBJ_WEAPON)) { +// -- // Weapons do a lot of damage to weapons, other objects do much less. +// -- if (!(weapon->mtype.phys_info.flags & PF_PERSISTENT)) { +// -- if (other_obj->type == OBJ_WEAPON) +// -- weapon->shields -= other_obj->shields/2; +// -- else +// -- weapon->shields -= other_obj->shields/4; +// -- +// -- if (weapon->shields <= 0) { +// -- weapon->shields = 0; +// -- weapon->flags |= OF_SHOULD_BE_DEAD; +// -- } +// -- } +// -- } else +// -- weapon->flags |= OF_SHOULD_BE_DEAD; +} + +void collide_weapon_and_controlcen( object * weapon, object *controlcen, vms_vector *collision_point ) +{ + + if (weapon->id == OMEGA_ID) + if (!ok_to_do_omega_damage(weapon)) + return; + + if (weapon->ctype.laser_info.parent_type == OBJ_PLAYER) { + fix damage = weapon->shields; + + if (Objects[weapon->ctype.laser_info.parent_num].id == Player_num) + Control_center_been_hit = 1; + + if ( Weapon_info[weapon->id].damage_radius ) + explode_badass_weapon(weapon,collision_point); + else + object_create_explosion( controlcen->segnum, collision_point, controlcen->size*3/20, VCLIP_SMALL_EXPLOSION ); + + digi_link_sound_to_pos( SOUND_CONTROL_CENTER_HIT, controlcen->segnum, 0, collision_point, 0, F1_0 ); + + damage = fixmul(damage, weapon->ctype.laser_info.multiplier); + + apply_damage_to_controlcen(controlcen, damage, weapon->ctype.laser_info.parent_num); + + maybe_kill_weapon(weapon,controlcen); + } else { // If robot weapon hits control center, blow it up, make it go away, but do no damage to control center. + object_create_explosion( controlcen->segnum, collision_point, controlcen->size*3/20, VCLIP_SMALL_EXPLOSION ); + maybe_kill_weapon(weapon,controlcen); + } + +} + +void collide_weapon_and_clutter( object * weapon, object *clutter, vms_vector *collision_point ) { + short exp_vclip = VCLIP_SMALL_EXPLOSION; + + if ( clutter->shields >= 0 ) + clutter->shields -= weapon->shields; + + digi_link_sound_to_pos( SOUND_LASER_HIT_CLUTTER, weapon->segnum, 0, collision_point, 0, F1_0 ); + + object_create_explosion( clutter->segnum, collision_point, ((clutter->size/3)*3)/4, exp_vclip ); + + if ( (clutter->shields < 0) && !(clutter->flags&(OF_EXPLODING|OF_DESTROYED))) + explode_object(clutter,STANDARD_EXPL_DELAY); + + maybe_kill_weapon(weapon,clutter); +} + +//--mk, 121094 -- extern void spin_robot(object *robot, vms_vector *collision_point); + +extern object *explode_badass_object(object *objp, fix damage, fix distance, fix force); + +int Final_boss_is_dead = 0; +fix Final_boss_countdown_time = 0; + +// ------------------------------------------------------------------------------------------------------ +void do_final_boss_frame(void) +{ + + if (!Final_boss_is_dead) + return; + + if (!Control_center_destroyed) + return; + + if (Final_boss_countdown_time == 0) + Final_boss_countdown_time = F1_0*2; + + Final_boss_countdown_time -= FrameTime; + if (Final_boss_countdown_time > 0) + return; + + gr_palette_fade_out( gr_palette, 256, 0 ); + start_endlevel_sequence(); //pretend we hit the exit trigger + +} + +// ------------------------------------------------------------------------------------------------------ +// This is all the ugly stuff we do when you kill the final boss so that you don't die or something +// which would ruin the logic of the cut sequence. +void do_final_boss_hacks(void) +{ + if (Player_is_dead) { + Int3(); // Uh-oh, player is dead. Try to rescue him. + Player_is_dead = 0; + } + + if (Players[Player_num].shields <= 0) + Players[Player_num].shields = 1; + + // If you're not invulnerable, get invulnerable! + if (!(Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE)) { + Players[Player_num].invulnerable_time = GameTime; + Players[Player_num].flags |= PLAYER_FLAGS_INVULNERABLE; + } + if (!(Game_mode & GM_MULTI)) + buddy_message("Nice job, %s!", Players[Player_num].callsign); + + Final_boss_is_dead = 1; +} + +extern int Buddy_dude_cheat; +extern int multi_all_players_alive(); +void multi_send_finish_game (); + +// ------------------------------------------------------------------------------------------------------ +// Return 1 if robot died, else return 0 +int apply_damage_to_robot(object *robot, fix damage, int killer_objnum) +{ + char isthief; + char i,temp_stolen[MAX_STOLEN_ITEMS]; + + if ( robot->flags&OF_EXPLODING) return 0; + + if (robot->shields < 0 ) return 0; //robot already dead... + + if (Robot_info[robot->id].boss_flag) + Boss_hit_time = GameTime; + + // Buddy invulnerable on level 24 so he can give you his important messages. Bah. + // Also invulnerable if his cheat for firing weapons is in effect. + if (Robot_info[robot->id].companion) +// if ((Current_mission_num == 0 && Current_level_num == Last_level) || Buddy_dude_cheat) +#ifdef NETWORK + if ((Current_mission_num == 0 && Current_level_num == Last_level) ) + return 0; +#endif + +// if (robot->control_type == CT_REMOTE) +// return 0; // Can't damange a robot controlled by another player + +// -- MK, 10/21/95, unused! -- if (Robot_info[robot->id].boss_flag) +// Boss_been_hit = 1; + + robot->shields -= damage; + + // Do unspeakable hacks to make sure player doesn't die after killing boss. Or before, sort of. + if (Robot_info[robot->id].boss_flag) +#ifdef NETWORK + if ((Current_mission_num == 0) && Current_level_num == Last_level) +#endif + if (robot->shields < 0) + { +#ifdef NETWORK + if (Game_mode & GM_MULTI) + { + if (!multi_all_players_alive()) // everyones gotta be alive + robot->shields=1; + else + { + multi_send_finish_game(); + do_final_boss_hacks(); + } + + } + else +#endif + { // NOTE LINK TO ABOVE!!! + if ((Players[Player_num].shields < 0) || Player_is_dead) + robot->shields = 1; // Sorry, we can't allow you to kill the final boss after you've died. Rough luck. + else + do_final_boss_hacks(); + } + } + + if (robot->shields < 0) { +#ifdef NETWORK + if (Game_mode & GM_MULTI) { + if (Robot_info[robot->id].thief) + isthief=1; + else + isthief=0; + + if (isthief) + for (i=0;iid].thief)) + { + if (isthief) + for (i=0;iid].thief); + + if (isthief) + for (i=0;iid].boss_flag) { + start_boss_death_sequence(robot); //do_controlcen_destroyed_stuff(NULL); + } else if (Robot_info[robot->id].death_roll) { + start_robot_death_sequence(robot); //do_controlcen_destroyed_stuff(NULL); + } else { + if (robot->id == SPECIAL_REACTOR_ROBOT) + special_reactor_stuff(); + //if (Robot_info[robot->id].smart_blobs) + // create_smart_children(robot, Robot_info[robot->id].smart_blobs); + //if (Robot_info[robot->id].badass) + // explode_badass_object(robot, F1_0*Robot_info[robot->id].badass, F1_0*40, F1_0*150); + if (Robot_info[robot->id].kamikaze) + explode_object(robot,1); // Kamikaze, explode right away, IN YOUR FACE! + else + explode_object(robot,STANDARD_EXPL_DELAY); + } + return 1; + } else + return 0; +} + +extern int boss_spew_robot(object *objp, vms_vector *pos); + +//--ubyte Boss_teleports[NUM_D2_BOSSES] = {1,1,1,1,1,1}; // Set byte if this boss can teleport +//--ubyte Boss_cloaks[NUM_D2_BOSSES] = {1,1,1,1,1,1}; // Set byte if this boss can cloak +//--ubyte Boss_spews_bots_energy[NUM_D2_BOSSES] = {1,1,0,0,1,1}; // Set byte if boss spews bots when hit by energy weapon. +//--ubyte Boss_spews_bots_matter[NUM_D2_BOSSES] = {0,0,1,0,1,1}; // Set byte if boss spews bots when hit by matter weapon. +//--ubyte Boss_invulnerable_energy[NUM_D2_BOSSES] = {0,0,1,1,0,0}; // Set byte if boss is invulnerable to energy weapons. +//--ubyte Boss_invulnerable_matter[NUM_D2_BOSSES] = {0,0,0,1,0,0}; // Set byte if boss is invulnerable to matter weapons. +//--ubyte Boss_invulnerable_spot[NUM_D2_BOSSES] = {0,0,0,0,1,1}; // Set byte if boss is invulnerable in all but a certain spot. (Dot product fvec|vec_to_collision < BOSS_INVULNERABLE_DOT) + +//#define BOSS_INVULNERABLE_DOT 0 // If a boss is invulnerable over most of his body, fvec(dot)vec_to_collision must be less than this for damage to occur. +int Boss_invulnerable_dot = 0; + +int Buddy_gave_hint_count = 5; +fix Last_time_buddy_gave_hint = 0; + +// ------------------------------------------------------------------------------------------------------ +// Return true if damage done to boss, else return false. +int do_boss_weapon_collision(object *robot, object *weapon, vms_vector *collision_point) +{ + int d2_boss_index; + int damage_flag; + + damage_flag = 1; + + d2_boss_index = Robot_info[robot->id].boss_flag - BOSS_D2; + + Assert((d2_boss_index >= 0) && (d2_boss_index < NUM_D2_BOSSES)); + + // See if should spew a bot. + if (weapon->ctype.laser_info.parent_type == OBJ_PLAYER) + if ((Weapon_info[weapon->id].matter && Boss_spews_bots_matter[d2_boss_index]) || (!Weapon_info[weapon->id].matter && Boss_spews_bots_energy[d2_boss_index])) { + if (Boss_spew_more[d2_boss_index]) + if (d_rand() > 16384) { + if (boss_spew_robot(robot, collision_point) != -1) + Last_gate_time = GameTime - Gate_interval - 1; // Force allowing spew of another bot. + } + boss_spew_robot(robot, collision_point); + } + + if (Boss_invulnerable_spot[d2_boss_index]) { + fix dot; + vms_vector tvec1; + + // Boss only vulnerable in back. See if hit there. + vm_vec_sub(&tvec1, collision_point, &robot->pos); + vm_vec_normalize_quick(&tvec1); // Note, if BOSS_INVULNERABLE_DOT is close to F1_0 (in magnitude), then should probably use non-quick version. + dot = vm_vec_dot(&tvec1, &robot->orient.fvec); + mprintf((0, "Boss hit vec dot = %7.3f\n", f2fl(dot))); + + if (dot > Boss_invulnerable_dot) { + int new_obj; + int segnum; + + segnum = find_point_seg(collision_point, robot->segnum); + digi_link_sound_to_pos( SOUND_WEAPON_HIT_DOOR, segnum, 0, collision_point, 0, F1_0); + damage_flag = 0; + + if (Last_time_buddy_gave_hint == 0) + Last_time_buddy_gave_hint = d_rand()*32 + F1_0*16; + + if (Buddy_gave_hint_count) { + if (Last_time_buddy_gave_hint + F1_0*20 < GameTime) { + int sval; + + Buddy_gave_hint_count--; + Last_time_buddy_gave_hint = GameTime; + sval = (d_rand()*4) >> 15; + switch (sval) { + case 0: buddy_message("Hit him in the back!"); break; + case 1: buddy_message("He's invulnerable there!"); break; + case 2: buddy_message("Get behind him and fire!"); break; + case 3: + default: + buddy_message("Hit the glowing spot!"); break; + } + } + } + + // Cause weapon to bounce. + // Make a copy of this weapon, because the physics wants to destroy it. + if (!Weapon_info[weapon->id].matter) { + new_obj = obj_create(weapon->type, weapon->id, weapon->segnum, &weapon->pos, + &weapon->orient, weapon->size, weapon->control_type, weapon->movement_type, weapon->render_type); + + if (new_obj != -1) { + vms_vector vec_to_point; + vms_vector weap_vec; + fix speed; + + if (weapon->render_type == RT_POLYOBJ) { + Objects[new_obj].rtype.pobj_info.model_num = Weapon_info[Objects[new_obj].id].model_num; + Objects[new_obj].size = fixdiv(Polygon_models[Objects[new_obj].rtype.pobj_info.model_num].rad,Weapon_info[Objects[new_obj].id].po_len_to_width_ratio); + } + + Objects[new_obj].mtype.phys_info.mass = Weapon_info[weapon->type].mass; + Objects[new_obj].mtype.phys_info.drag = Weapon_info[weapon->type].drag; + vm_vec_zero(&Objects[new_obj].mtype.phys_info.thrust); + + vm_vec_sub(&vec_to_point, collision_point, &robot->pos); + vm_vec_normalize_quick(&vec_to_point); + weap_vec = weapon->mtype.phys_info.velocity; + speed = vm_vec_normalize_quick(&weap_vec); + vm_vec_scale_add2(&vec_to_point, &weap_vec, -F1_0*2); + vm_vec_scale(&vec_to_point, speed/4); + Objects[new_obj].mtype.phys_info.velocity = vec_to_point; + } + } + } + } else if ((Weapon_info[weapon->id].matter && Boss_invulnerable_matter[d2_boss_index]) || (!Weapon_info[weapon->id].matter && Boss_invulnerable_energy[d2_boss_index])) { + int segnum; + + segnum = find_point_seg(collision_point, robot->segnum); + digi_link_sound_to_pos( SOUND_WEAPON_HIT_DOOR, segnum, 0, collision_point, 0, F1_0); + damage_flag = 0; + } + + return damage_flag; +} + +extern int Robots_kill_robots_cheat; + +// ------------------------------------------------------------------------------------------------------ +void collide_robot_and_weapon( object * robot, object * weapon, vms_vector *collision_point ) +{ + int damage_flag=1; + int boss_invul_flag=0; + + if (weapon->id == OMEGA_ID) + if (!ok_to_do_omega_damage(weapon)) + return; + + if (Robot_info[robot->id].boss_flag) { + Boss_hit_time = GameTime; + if (Robot_info[robot->id].boss_flag >= BOSS_D2) { + damage_flag = do_boss_weapon_collision(robot, weapon, collision_point); + boss_invul_flag = !damage_flag; + } + } + + // Put in at request of Jasen (and Adam) because the Buddy-Bot gets in their way. + // MK has so much fun whacking his butt around the mine he never cared... + if ((Robot_info[robot->id].companion) && ((weapon->ctype.laser_info.parent_type != OBJ_ROBOT) && !Robots_kill_robots_cheat)) + return; + + if (weapon->id == EARTHSHAKER_ID) + smega_rock_stuff(); + + // If a persistent weapon hit robot most recently, quick abort, else we cream the same robot many times, + // depending on frame rate. + if (weapon->mtype.phys_info.flags & PF_PERSISTENT) { + if (weapon->ctype.laser_info.last_hitobj == robot-Objects) + return; + else + weapon->ctype.laser_info.last_hitobj = robot-Objects; + + // mprintf((0, "weapon #%i with power %i hits robot #%i.\n", weapon - Objects, f2i(weapon->shields), robot - Objects)); + } + + if (weapon->ctype.laser_info.parent_signature == robot->signature) + return; + + // Changed, 10/04/95, put out blobs based on skill level and power of weapon doing damage. + // Also, only a weapon hit from a player weapon causes smart blobs. + if ((weapon->ctype.laser_info.parent_type == OBJ_PLAYER) && (Robot_info[robot->id].energy_blobs)) + if ((robot->shields > 0) && Weapon_is_energy[weapon->id]) { + fix probval; + int num_blobs; + + probval = (Difficulty_level+2) * min(weapon->shields, robot->shields); + probval = Robot_info[robot->id].energy_blobs * probval/(NDL*32); + + num_blobs = probval >> 16; + if (2*d_rand() < (probval & 0xffff)) + num_blobs++; + + if (num_blobs) + create_smart_children(robot, num_blobs); + } + + // Note: If weapon hits an invulnerable boss, it will still do badass damage, including to the boss, + // unless this is trapped elsewhere. + if ( Weapon_info[weapon->id].damage_radius ) + { + if (boss_invul_flag) { //don't make badass sound + weapon_info *wi = &Weapon_info[weapon->id]; + + //this code copied from explode_badass_weapon() + + object_create_badass_explosion( weapon, weapon->segnum, collision_point, + wi->impact_size, + wi->robot_hit_vclip, + wi->strength[Difficulty_level], + wi->damage_radius,wi->strength[Difficulty_level], + weapon->ctype.laser_info.parent_num ); + + } + else //normal badass explosion + explode_badass_weapon(weapon,collision_point); + } + + if ( ((weapon->ctype.laser_info.parent_type==OBJ_PLAYER) || Robots_kill_robots_cheat) && !(robot->flags & OF_EXPLODING) ) { + object *expl_obj=NULL; + + if (weapon->ctype.laser_info.parent_num == Players[Player_num].objnum) { + create_awareness_event(weapon, PA_WEAPON_ROBOT_COLLISION); // object "weapon" can attract attention to player + do_ai_robot_hit(robot, PA_WEAPON_ROBOT_COLLISION); + } +#ifdef NETWORK + else + multi_robot_request_change(robot, Objects[weapon->ctype.laser_info.parent_num].id); +#endif + + if ( Robot_info[robot->id].exp1_vclip_num > -1 ) + expl_obj = object_create_explosion( weapon->segnum, collision_point, (robot->size/2*3)/4, Robot_info[robot->id].exp1_vclip_num ); + else if ( Weapon_info[weapon->id].robot_hit_vclip > -1 ) + expl_obj = object_create_explosion( weapon->segnum, collision_point, Weapon_info[weapon->id].impact_size, Weapon_info[weapon->id].robot_hit_vclip ); + + if (expl_obj) + obj_attach(robot,expl_obj); + + if ( damage_flag && (Robot_info[robot->id].exp1_sound_num > -1 )) + digi_link_sound_to_pos( Robot_info[robot->id].exp1_sound_num, robot->segnum, 0, collision_point, 0, F1_0 ); + + if (!(weapon->flags & OF_HARMLESS)) { + fix damage = weapon->shields; + + if (damage_flag) + damage = fixmul(damage, weapon->ctype.laser_info.multiplier); + else + damage = 0; + + // Cut Gauss damage on bosses because it just breaks the game. Bosses are so easy to + // hit, and missing a robot is what prevents the Gauss from being game-breaking. + if (weapon->id == GAUSS_ID) + if (Robot_info[robot->id].boss_flag) + damage = damage * (2*NDL-Difficulty_level)/(2*NDL); + + if (! apply_damage_to_robot(robot, damage, weapon->ctype.laser_info.parent_num)) + bump_two_objects(robot, weapon, 0); //only bump if not dead. no damage from bump + else if (weapon->ctype.laser_info.parent_signature == ConsoleObject->signature) { + add_points_to_score(Robot_info[robot->id].score_value); + detect_escort_goal_accomplished(robot-Objects); + } + } + + + // If Gauss Cannon, spin robot. + if ((robot != NULL) && (!Robot_info[robot->id].companion) && (!Robot_info[robot->id].boss_flag) && (weapon->id == GAUSS_ID)) { + ai_static *aip = &robot->ctype.ai_info; + + if (aip->SKIP_AI_COUNT * FrameTime < F1_0) { + aip->SKIP_AI_COUNT++; + robot->mtype.phys_info.rotthrust.x = fixmul((d_rand() - 16384), FrameTime * aip->SKIP_AI_COUNT); + robot->mtype.phys_info.rotthrust.y = fixmul((d_rand() - 16384), FrameTime * aip->SKIP_AI_COUNT); + robot->mtype.phys_info.rotthrust.z = fixmul((d_rand() - 16384), FrameTime * aip->SKIP_AI_COUNT); + robot->mtype.phys_info.flags |= PF_USES_THRUST; + + } + } + + } + + maybe_kill_weapon(weapon,robot); + + return; +} + +//##void collide_robot_and_camera( object * robot, object * camera, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_robot_and_powerup( object * robot, object * powerup, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_robot_and_debris( object * robot, object * debris, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_hostage_and_hostage( object * hostage1, object * hostage2, vms_vector *collision_point ) { +//## return; +//##} + +void collide_hostage_and_player( object * hostage, object * player, vms_vector *collision_point ) { + // Give player points, etc. + if ( player == ConsoleObject ) { + detect_escort_goal_accomplished(hostage-Objects); + add_points_to_score(HOSTAGE_SCORE); + + // Do effect + hostage_rescue(hostage->id); + + // Remove the hostage object. + hostage->flags |= OF_SHOULD_BE_DEAD; + + #ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_remobj(hostage-Objects); + #endif + } + return; +} + +//--unused-- void collide_hostage_and_weapon( object * hostage, object * weapon, vms_vector *collision_point ) +//--unused-- { +//--unused-- // Cannot kill hostages, as per Matt's edict! +//--unused-- // (A fine edict, but in contradiction to the milestone: "Robots attack hostages.") +//--unused-- hostage->shields -= weapon->shields/2; +//--unused-- +//--unused-- create_awareness_event(weapon, PA_WEAPON_ROBOT_COLLISION); // object "weapon" can attract attention to player +//--unused-- +//--unused-- //PLAY_SOUND_3D( SOUND_HOSTAGE_KILLED, collision_point, hostage->segnum ); +//--unused-- digi_link_sound_to_pos( SOUND_HOSTAGE_KILLED, hostage->segnum , 0, collision_point, 0, F1_0 ); +//--unused-- +//--unused-- +//--unused-- if (hostage->shields <= 0) { +//--unused-- explode_object(hostage,0); +//--unused-- hostage->flags |= OF_SHOULD_BE_DEAD; +//--unused-- } +//--unused-- +//--unused-- if ( Weapon_info[weapon->id].damage_radius ) +//--unused-- explode_badass_weapon(weapon); +//--unused-- +//--unused-- maybe_kill_weapon(weapon,hostage); +//--unused-- +//--unused-- } + +//##void collide_hostage_and_camera( object * hostage, object * camera, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_hostage_and_powerup( object * hostage, object * powerup, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_hostage_and_debris( object * hostage, object * debris, vms_vector *collision_point ) { +//## return; +//##} + +void collide_player_and_player( object * player1, object * player2, vms_vector *collision_point ) { + digi_link_sound_to_pos( SOUND_ROBOT_HIT_PLAYER, player1->segnum, 0, collision_point, 0, F1_0 ); + bump_two_objects(player1, player2, 1); + return; +} + +int maybe_drop_primary_weapon_egg(object *playerobj, int weapon_index) +{ + int weapon_flag = HAS_FLAG(weapon_index); + int powerup_num; + + powerup_num = Primary_weapon_to_powerup[weapon_index]; + + if (Players[playerobj->id].primary_weapon_flags & weapon_flag) + return call_object_create_egg(playerobj, 1, OBJ_POWERUP, powerup_num); + else + return -1; +} + +void maybe_drop_secondary_weapon_egg(object *playerobj, int weapon_index, int count) +{ + int weapon_flag = HAS_FLAG(weapon_index); + int powerup_num; + + powerup_num = Secondary_weapon_to_powerup[weapon_index]; + + if (Players[playerobj->id].secondary_weapon_flags & weapon_flag) { + int i, max_count; + + max_count = min(count, 3); + for (i=0; iid].secondary_ammo[missile_index]; + powerup_id = Secondary_weapon_to_powerup[missile_index]; + + if (num_missiles > 10) + num_missiles = 10; + + call_object_create_egg(playerobj, num_missiles/4, OBJ_POWERUP, powerup_id+1); + call_object_create_egg(playerobj, num_missiles%4, OBJ_POWERUP, powerup_id); +} + +// -- int Items_destroyed = 0; + +void drop_player_eggs(object *playerobj) +{ +// mprintf((0, "In drop_player_eggs...\n")); + + if ((playerobj->type == OBJ_PLAYER) || (playerobj->type == OBJ_GHOST)) { + int rthresh; + int pnum = playerobj->id; + int objnum; + int vulcan_ammo=0; + vms_vector randvec; + + // -- Items_destroyed = 0; + + // Seed the random number generator so in net play the eggs will always + // drop the same way + #ifdef NETWORK + if (Game_mode & GM_MULTI) + { + Net_create_loc = 0; + d_srand(5483L); + } + #endif + + // If the player had smart mines, maybe arm one of them. + rthresh = 30000; + while ((Players[playerobj->id].secondary_ammo[SMART_MINE_INDEX]%4==1) && (d_rand() < rthresh)) { + int newseg; + vms_vector tvec; + + make_random_vector(&randvec); + rthresh /= 2; + vm_vec_add(&tvec, &playerobj->pos, &randvec); + newseg = find_point_seg(&tvec, playerobj->segnum); + if (newseg != -1) + Laser_create_new(&randvec, &tvec, newseg, playerobj-Objects, SUPERPROX_ID, 0); + } + + // If the player had proximity bombs, maybe arm one of them. + + if ((Game_mode & GM_MULTI) && !(Game_mode & GM_HOARD)) + { + rthresh = 30000; + while ((Players[playerobj->id].secondary_ammo[PROXIMITY_INDEX]%4==1) && (d_rand() < rthresh)) { + int newseg; + vms_vector tvec; + + make_random_vector(&randvec); + rthresh /= 2; + vm_vec_add(&tvec, &playerobj->pos, &randvec); + newseg = find_point_seg(&tvec, playerobj->segnum); + if (newseg != -1) + Laser_create_new(&randvec, &tvec, newseg, playerobj-Objects, PROXIMITY_ID, 0); + + } + } + + // If the player dies and he has powerful lasers, create the powerups here. + + if (Players[pnum].laser_level > MAX_LASER_LEVEL) + call_object_create_egg(playerobj, Players[pnum].laser_level-MAX_LASER_LEVEL, OBJ_POWERUP, POW_SUPER_LASER); + else if (Players[pnum].laser_level >= 1) + call_object_create_egg(playerobj, Players[pnum].laser_level, OBJ_POWERUP, POW_LASER); // Note: laser_level = 0 for laser level 1. + + // Drop quad laser if appropos + if (Players[pnum].flags & PLAYER_FLAGS_QUAD_LASERS) + call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_QUAD_FIRE); + + if (Players[pnum].flags & PLAYER_FLAGS_CLOAKED) + call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_CLOAK); + + if (Players[pnum].flags & PLAYER_FLAGS_MAP_ALL) + call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_FULL_MAP); + + if (Players[pnum].flags & PLAYER_FLAGS_AFTERBURNER) + call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_AFTERBURNER); + + if (Players[pnum].flags & PLAYER_FLAGS_AMMO_RACK) + call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_AMMO_RACK); + + if (Players[pnum].flags & PLAYER_FLAGS_CONVERTER) + call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_CONVERTER); + + if (Players[pnum].flags & PLAYER_FLAGS_HEADLIGHT) + call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_HEADLIGHT); + + // drop the other enemies flag if you have it + +#ifdef NETWORK + if ((Game_mode & GM_CAPTURE) && (Players[pnum].flags & PLAYER_FLAGS_FLAG)) + { + if ((get_team (pnum)==TEAM_RED)) + call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_FLAG_BLUE); + else + call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_FLAG_RED); + } + + + if (Game_mode & GM_HOARD) + { + // Drop hoard orbs + + int max_count,i; + + mprintf ((0,"HOARD MODE: Dropping %d orbs\n",Players[pnum].secondary_ammo[PROXIMITY_INDEX])); + + max_count = min(Players[pnum].secondary_ammo[PROXIMITY_INDEX], 12); + for (i=0; iid==Player_num)?Omega_charge:MAX_OMEGA_CHARGE; + + // Drop the secondary weapons + // Note, proximity weapon only comes in packets of 4. So drop n/2, but a max of 3 (handled inside maybe_drop..) Make sense? + + if (!(Game_mode & GM_HOARD)) + maybe_drop_secondary_weapon_egg(playerobj, PROXIMITY_INDEX, (Players[playerobj->id].secondary_ammo[PROXIMITY_INDEX])/4); + + maybe_drop_secondary_weapon_egg(playerobj, SMART_INDEX, Players[playerobj->id].secondary_ammo[SMART_INDEX]); + maybe_drop_secondary_weapon_egg(playerobj, MEGA_INDEX, Players[playerobj->id].secondary_ammo[MEGA_INDEX]); + + maybe_drop_secondary_weapon_egg(playerobj, SMART_MINE_INDEX,(Players[playerobj->id].secondary_ammo[SMART_MINE_INDEX])/4); + maybe_drop_secondary_weapon_egg(playerobj, SMISSILE5_INDEX, Players[playerobj->id].secondary_ammo[SMISSILE5_INDEX]); + + // Drop the player's missiles in packs of 1 and/or 4 + drop_missile_1_or_4(playerobj,HOMING_INDEX); + drop_missile_1_or_4(playerobj,GUIDED_INDEX); + drop_missile_1_or_4(playerobj,CONCUSSION_INDEX); + drop_missile_1_or_4(playerobj,SMISSILE1_INDEX); + drop_missile_1_or_4(playerobj,SMISSILE4_INDEX); + + // If player has vulcan ammo, but no vulcan cannon, drop the ammo. + if (!(Players[playerobj->id].primary_weapon_flags & HAS_VULCAN_FLAG)) { + int amount = Players[playerobj->id].primary_ammo[VULCAN_INDEX]; + if (amount > 200) { + mprintf((0, "Surprising amount of vulcan ammo: %i bullets.\n", amount)); + amount = 200; + } + while (amount > 0) { + call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_VULCAN_AMMO); + amount -= VULCAN_AMMO_AMOUNT; + } + } + + // Always drop a shield and energy powerup. + if (Game_mode & GM_MULTI) { + call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_SHIELD_BOOST); + call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_ENERGY); + } + +//-- // Drop all the keys. +//-- if (Players[Player_num].flags & PLAYER_FLAGS_BLUE_KEY) { +//-- playerobj->contains_count = 1; +//-- playerobj->contains_type = OBJ_POWERUP; +//-- playerobj->contains_id = POW_KEY_BLUE; +//-- object_create_egg(playerobj); +//-- } +//-- if (Players[Player_num].flags & PLAYER_FLAGS_RED_KEY) { +//-- playerobj->contains_count = 1; +//-- playerobj->contains_type = OBJ_POWERUP; +//-- playerobj->contains_id = POW_KEY_RED; +//-- object_create_egg(playerobj); +//-- } +//-- if (Players[Player_num].flags & PLAYER_FLAGS_GOLD_KEY) { +//-- playerobj->contains_count = 1; +//-- playerobj->contains_type = OBJ_POWERUP; +//-- playerobj->contains_id = POW_KEY_GOLD; +//-- object_create_egg(playerobj); +//-- } + +// -- if (Items_destroyed) { +// -- if (Items_destroyed == 1) +// -- HUD_init_message("%i item was destroyed.", Items_destroyed); +// -- else +// -- HUD_init_message("%i items were destroyed.", Items_destroyed); +// -- Items_destroyed = 0; +// -- } + } + +} + +// -- removed, 09/06/95, MK -- void destroy_primary_weapon(int weapon_index) +// -- removed, 09/06/95, MK -- { +// -- removed, 09/06/95, MK -- if (weapon_index == MAX_PRIMARY_WEAPONS) { +// -- removed, 09/06/95, MK -- HUD_init_message("Quad lasers destroyed!"); +// -- removed, 09/06/95, MK -- Players[Player_num].flags &= ~PLAYER_FLAGS_QUAD_LASERS; +// -- removed, 09/06/95, MK -- update_laser_weapon_info(); +// -- removed, 09/06/95, MK -- } else if (weapon_index == 0) { +// -- removed, 09/06/95, MK -- Assert(Players[Player_num].laser_level > 0); +// -- removed, 09/06/95, MK -- HUD_init_message("%s degraded!", Text_string[104+weapon_index]); // Danger! Danger! Use of literal! Danger! +// -- removed, 09/06/95, MK -- Players[Player_num].laser_level--; +// -- removed, 09/06/95, MK -- update_laser_weapon_info(); +// -- removed, 09/06/95, MK -- } else { +// -- removed, 09/06/95, MK -- HUD_init_message("%s destroyed!", Text_string[104+weapon_index]); // Danger! Danger! Use of literal! Danger! +// -- removed, 09/06/95, MK -- Players[Player_num].primary_weapon_flags &= ~(1 << weapon_index); +// -- removed, 09/06/95, MK -- auto_select_weapon(0); +// -- removed, 09/06/95, MK -- } +// -- removed, 09/06/95, MK -- +// -- removed, 09/06/95, MK -- } +// -- removed, 09/06/95, MK -- +// -- removed, 09/06/95, MK -- void destroy_secondary_weapon(int weapon_index) +// -- removed, 09/06/95, MK -- { +// -- removed, 09/06/95, MK -- if (Players[Player_num].secondary_ammo <= 0) +// -- removed, 09/06/95, MK -- return; +// -- removed, 09/06/95, MK -- +// -- removed, 09/06/95, MK -- HUD_init_message("%s destroyed!", Text_string[114+weapon_index]); // Danger! Danger! Use of literal! Danger! +// -- removed, 09/06/95, MK -- if (--Players[Player_num].secondary_ammo[weapon_index] == 0) +// -- removed, 09/06/95, MK -- auto_select_weapon(1); +// -- removed, 09/06/95, MK -- +// -- removed, 09/06/95, MK -- } +// -- removed, 09/06/95, MK -- +// -- removed, 09/06/95, MK -- #define LOSE_WEAPON_THRESHOLD (F1_0*30) + +extern fix Buddy_sorry_time; + +void apply_damage_to_player(object *playerobj, object *killer, fix damage) +{ + if (Player_is_dead) + return; + + if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE) + return; + + if (Endlevel_sequence) + return; + + //for the player, the 'real' shields are maintained in the Players[] + //array. The shields value in the player's object are, I think, not + //used anywhere. This routine, however, sets the objects shields to + //be a mirror of the value in the Player structure. + + if (playerobj->id == Player_num) { //is this the local player? + + // MK: 08/14/95: This code can never be reached. See the return about 12 lines up. +// -- if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE) { +// -- +// -- //invincible, so just do blue flash +// -- +// -- PALETTE_FLASH_ADD(0,0,f2i(damage)*4); //flash blue +// -- +// -- } +// -- else { //take damage, do red flash + + Players[Player_num].shields -= damage; + + PALETTE_FLASH_ADD(f2i(damage)*4,-f2i(damage/2),-f2i(damage/2)); //flash red + +// -- } + + if (Players[Player_num].shields < 0) { + + Players[Player_num].killer_objnum = killer-Objects; + +// if ( killer && (killer->type == OBJ_PLAYER)) +// Players[Player_num].killer_objnum = killer-Objects; + + playerobj->flags |= OF_SHOULD_BE_DEAD; + + if (Buddy_objnum != -1) + if (killer && (killer->type == OBJ_ROBOT) && (Robot_info[killer->id].companion)) + Buddy_sorry_time = GameTime; + } +// -- removed, 09/06/95, MK -- else if (Players[Player_num].shields < LOSE_WEAPON_THRESHOLD) { +// -- removed, 09/06/95, MK -- int randnum = d_rand(); +// -- removed, 09/06/95, MK -- +// -- removed, 09/06/95, MK -- if (fixmul(Players[Player_num].shields, randnum) < damage/4) { +// -- removed, 09/06/95, MK -- if (d_rand() > 20000) { +// -- removed, 09/06/95, MK -- destroy_secondary_weapon(Secondary_weapon); +// -- removed, 09/06/95, MK -- } else if (Primary_weapon == 0) { +// -- removed, 09/06/95, MK -- if (Players[Player_num].flags & PLAYER_FLAGS_QUAD_LASERS) +// -- removed, 09/06/95, MK -- destroy_primary_weapon(MAX_PRIMARY_WEAPONS); // This means to destroy quad laser. +// -- removed, 09/06/95, MK -- else if (Players[Player_num].laser_level > 0) +// -- removed, 09/06/95, MK -- destroy_primary_weapon(Primary_weapon); +// -- removed, 09/06/95, MK -- } else +// -- removed, 09/06/95, MK -- destroy_primary_weapon(Primary_weapon); +// -- removed, 09/06/95, MK -- } else +// -- removed, 09/06/95, MK -- ; // mprintf((0, "%8x > %8x, so don't lose weapon.\n", fixmul(Players[Player_num].shields, randnum), damage/4)); +// -- removed, 09/06/95, MK -- } + + playerobj->shields = Players[Player_num].shields; //mirror + + } +} + +void collide_player_and_weapon( object * playerobj, object * weapon, vms_vector *collision_point ) +{ + fix damage = weapon->shields; + object * killer=NULL; + + // In multiplayer games, only do damage to another player if in first frame. + // This is necessary because in multiplayer, due to varying framerates, omega blobs actually + // have a bit of a lifetime. But they start out with a lifetime of ONE_FRAME_TIME, and this + // gets bashed to 1/4 second in laser_do_weapon_sequence. This bashing occurs for visual purposes only. + if (weapon->id == OMEGA_ID) + if (!ok_to_do_omega_damage(weapon)) + return; + + // Don't collide own smart mines unless direct hit. + if (weapon->id == SUPERPROX_ID) + if (playerobj-Objects == weapon->ctype.laser_info.parent_num) + if (vm_vec_dist_quick(collision_point, &playerobj->pos) > playerobj->size) + return; + + if (weapon->id == EARTHSHAKER_ID) + smega_rock_stuff(); + + damage = fixmul(damage, weapon->ctype.laser_info.multiplier); + if (Game_mode & GM_MULTI) + damage = fixmul(damage, Weapon_info[weapon->id].multi_damage_scale); + + if (weapon->mtype.phys_info.flags & PF_PERSISTENT) + { + if (weapon->ctype.laser_info.last_hitobj == playerobj-Objects) + return; + else + weapon->ctype.laser_info.last_hitobj = playerobj-Objects; + } + + if (playerobj->id == Player_num) + { + if (!(Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE)) + { + digi_link_sound_to_pos( SOUND_PLAYER_GOT_HIT, playerobj->segnum, 0, collision_point, 0, F1_0 ); + #ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_play_sound(SOUND_PLAYER_GOT_HIT, F1_0); + #endif + } + else + { + digi_link_sound_to_pos( SOUND_WEAPON_HIT_DOOR, playerobj->segnum, 0, collision_point, 0, F1_0); + #ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_play_sound(SOUND_WEAPON_HIT_DOOR, F1_0); + #endif + } + } + + object_create_explosion( playerobj->segnum, collision_point, i2f(10)/2, VCLIP_PLAYER_HIT ); + if ( Weapon_info[weapon->id].damage_radius ) + explode_badass_weapon(weapon,collision_point); + + maybe_kill_weapon(weapon,playerobj); + + bump_two_objects(playerobj, weapon, 0); //no damage from bump + + if ( !Weapon_info[weapon->id].damage_radius ) { + if ( weapon->ctype.laser_info.parent_num > -1 ) + killer = &Objects[weapon->ctype.laser_info.parent_num]; + +// if (weapon->id == SMART_HOMING_ID) +// damage /= 4; + + if (!(weapon->flags & OF_HARMLESS)) + apply_damage_to_player( playerobj, killer, damage); + } + + // Robots become aware of you if you get hit. + ai_do_cloak_stuff(); + + return; +} + +// Nasty robots are the ones that attack you by running into you and doing lots of damage. +void collide_player_and_nasty_robot( object * playerobj, object * robot, vms_vector *collision_point ) +{ +// if (!(Robot_info[robot->id].energy_drain && Players[playerobj->id].energy)) + digi_link_sound_to_pos( Robot_info[robot->id].claw_sound, playerobj->segnum, 0, collision_point, 0, F1_0 ); + + object_create_explosion( playerobj->segnum, collision_point, i2f(10)/2, VCLIP_PLAYER_HIT ); + + bump_two_objects(playerobj, robot, 0); //no damage from bump + + apply_damage_to_player( playerobj, robot, F1_0*(Difficulty_level+1)); + + return; +} + +void collide_player_and_materialization_center(object *objp) +{ + int side; + vms_vector exit_dir; + segment *segp = &Segments[objp->segnum]; + + digi_link_sound_to_pos(SOUND_PLAYER_GOT_HIT, objp->segnum, 0, &objp->pos, 0, F1_0); +// digi_play_sample( SOUND_PLAYER_GOT_HIT, F1_0 ); + + object_create_explosion( objp->segnum, &objp->pos, i2f(10)/2, VCLIP_PLAYER_HIT ); + + if (objp->id != Player_num) + return; + + for (side=0; sidepos); + vm_vec_normalize_quick(&exit_dir); + make_random_vector(&rand_vec); + rand_vec.x /= 4; rand_vec.y /= 4; rand_vec.z /= 4; + vm_vec_add2(&exit_dir, &rand_vec); + vm_vec_normalize_quick(&exit_dir); + } + + bump_one_object(objp, &exit_dir, 64*F1_0); + + apply_damage_to_player( objp, objp, 4*F1_0); // Changed, MK, 2/19/96, make killer the player, so if you die in matcen, will say you killed yourself + + return; + +} + +void collide_robot_and_materialization_center(object *objp) +{ + int side; + vms_vector exit_dir; + segment *segp=&Segments[objp->segnum]; + + digi_link_sound_to_pos(SOUND_ROBOT_HIT, objp->segnum, 0, &objp->pos, 0, F1_0); +// digi_play_sample( SOUND_ROBOT_HIT, F1_0 ); + + if ( Robot_info[objp->id].exp1_vclip_num > -1 ) + object_create_explosion( objp->segnum, &objp->pos, (objp->size/2*3)/4, Robot_info[objp->id].exp1_vclip_num ); + + for (side=0; sidepos); + vm_vec_normalize_quick(&exit_dir); + } + + bump_one_object(objp, &exit_dir, 8*F1_0); + + apply_damage_to_robot( objp, F1_0, -1); + + return; + +} + +//##void collide_player_and_camera( object * playerobj, object * camera, vms_vector *collision_point ) { +//## return; +//##} + +extern int Network_got_powerup; // HACK!!! + +void collide_player_and_powerup( object * playerobj, object * powerup, vms_vector *collision_point ) { + if (!Endlevel_sequence && !Player_is_dead && (playerobj->id == Player_num )) { + int powerup_used; + + powerup_used = do_powerup(powerup); + + if (powerup_used) { + powerup->flags |= OF_SHOULD_BE_DEAD; + #ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_remobj(powerup-Objects); + #endif + } + } +#ifndef SHAREWARE + else if ((Game_mode & GM_MULTI_COOP) && (playerobj->id != Player_num)) + { + switch (powerup->id) { + case POW_KEY_BLUE: + Players[playerobj->id].flags |= PLAYER_FLAGS_BLUE_KEY; + break; + case POW_KEY_RED: + Players[playerobj->id].flags |= PLAYER_FLAGS_RED_KEY; + break; + case POW_KEY_GOLD: + Players[playerobj->id].flags |= PLAYER_FLAGS_GOLD_KEY; + break; + default: + break; + } + } +#endif + return; +} + +//##void collide_player_and_debris( object * playerobj, object * debris, vms_vector *collision_point ) { +//## return; +//##} + +void collide_player_and_clutter( object * playerobj, object * clutter, vms_vector *collision_point ) { + digi_link_sound_to_pos( SOUND_ROBOT_HIT_PLAYER, playerobj->segnum, 0, collision_point, 0, F1_0 ); + bump_two_objects(clutter, playerobj, 1); + return; +} + +// See if weapon1 creates a badass explosion. If so, create the explosion +// Return true if weapon does proximity (as opposed to only contact) damage when it explodes. +int maybe_detonate_weapon(object *weapon1, object *weapon2, vms_vector *collision_point) +{ + if ( Weapon_info[weapon1->id].damage_radius ) { + fix dist; + + dist = vm_vec_dist_quick(&weapon1->pos, &weapon2->pos); + if (dist < F1_0*5) { + maybe_kill_weapon(weapon1,weapon2); + if (weapon1->flags & OF_SHOULD_BE_DEAD) { + explode_badass_weapon(weapon1,collision_point); + digi_link_sound_to_pos( Weapon_info[weapon1->id].robot_hit_sound, weapon1->segnum , 0, collision_point, 0, F1_0 ); + } + return 1; + } else { + weapon1->lifeleft = min(dist/64, F1_0); + return 1; + } + } else + return 0; +} + +void collide_weapon_and_weapon( object * weapon1, object * weapon2, vms_vector *collision_point ) +{ + // -- Does this look buggy??: if (weapon1->id == PMINE_ID && weapon1->id == PMINE_ID) + if (weapon1->id == PMINE_ID && weapon2->id == PMINE_ID) + return; //these can't blow each other up + + if (weapon1->id == OMEGA_ID) { + if (!ok_to_do_omega_damage(weapon1)) + return; + } else if (weapon2->id == OMEGA_ID) { + if (!ok_to_do_omega_damage(weapon2)) + return; + } + + if ((Weapon_info[weapon1->id].destroyable) || (Weapon_info[weapon2->id].destroyable)) { + + // Bug reported by Adam Q. Pletcher on September 9, 1994, smart bomb homing missiles were toasting each other. + if ((weapon1->id == weapon2->id) && (weapon1->ctype.laser_info.parent_num == weapon2->ctype.laser_info.parent_num)) + return; + + if (Weapon_info[weapon1->id].destroyable) + if (maybe_detonate_weapon(weapon1, weapon2, collision_point)) + maybe_detonate_weapon(weapon2,weapon1, collision_point); + + if (Weapon_info[weapon2->id].destroyable) + if (maybe_detonate_weapon(weapon2, weapon1, collision_point)) + maybe_detonate_weapon(weapon1,weapon2, collision_point); + + } + +} + +//##void collide_weapon_and_camera( object * weapon, object * camera, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_weapon_and_powerup( object * weapon, object * powerup, vms_vector *collision_point ) { +//## return; +//##} + +void collide_weapon_and_debris( object * weapon, object * debris, vms_vector *collision_point ) { + + // Hack! Prevent debris from causing bombs spewed at player death to detonate! + if ((weapon->id == PROXIMITY_ID) || (weapon->id == SUPERPROX_ID)) { + if (weapon->ctype.laser_info.creation_time + F1_0/2 > GameTime) + return; + } + + if ( (weapon->ctype.laser_info.parent_type==OBJ_PLAYER) && !(debris->flags & OF_EXPLODING) ) { + digi_link_sound_to_pos( SOUND_ROBOT_HIT, weapon->segnum , 0, collision_point, 0, F1_0 ); + + explode_object(debris,0); + if ( Weapon_info[weapon->id].damage_radius ) + explode_badass_weapon(weapon,collision_point); + maybe_kill_weapon(weapon,debris); + weapon->flags |= OF_SHOULD_BE_DEAD; + } + return; +} + +//##void collide_camera_and_camera( object * camera1, object * camera2, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_camera_and_powerup( object * camera, object * powerup, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_camera_and_debris( object * camera, object * debris, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_powerup_and_powerup( object * powerup1, object * powerup2, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_powerup_and_debris( object * powerup, object * debris, vms_vector *collision_point ) { +//## return; +//##} + +//##void collide_debris_and_debris( object * debris1, object * debris2, vms_vector *collision_point ) { +//## return; +//##} + + +/* DPH: Put these macros on one long line to avoid CR/LF problems on linux */ +#define COLLISION_OF(a,b) (((a)<<8) + (b)) + +#define DO_COLLISION(type1,type2,collision_function) case COLLISION_OF( (type1), (type2) ): (collision_function)( (A), (B), collision_point ); break; case COLLISION_OF( (type2), (type1) ): (collision_function)( (B), (A), collision_point ); break; + +#define DO_SAME_COLLISION(type1,type2,collision_function) case COLLISION_OF( (type1), (type1) ): (collision_function)( (A), (B), collision_point ); break; + +//these next two macros define a case that does nothing +#define NO_COLLISION(type1,type2,collision_function) case COLLISION_OF( (type1), (type2) ): break; case COLLISION_OF( (type2), (type1) ): break; + +#define NO_SAME_COLLISION(type1,type2,collision_function) case COLLISION_OF( (type1), (type1) ): break; + +/* DPH: These ones are never used so I'm not going to bother */ +#ifndef __GNUC__ +#define IGNORE_COLLISION(type1,type2,collision_function) \ + case COLLISION_OF( (type1), (type2) ): \ + break; \ + case COLLISION_OF( (type2), (type1) ): \ + break; + +#define ERROR_COLLISION(type1,type2,collision_function) \ + case COLLISION_OF( (type1), (type2) ): \ + Error( "Error in collision type!" ); \ + break; \ + case COLLISION_OF( (type2), (type1) ): \ + Error( "Error in collision type!" ); \ + break; +#endif + +void collide_two_objects( object * A, object * B, vms_vector *collision_point ) +{ + int collision_type; + + collision_type = COLLISION_OF(A->type,B->type); + + //mprintf( (0, "Object %d of type %d collided with object %d of type %d\n", A-Objects,A->type, B-Objects, B->type )); + + switch( collision_type ) { + NO_SAME_COLLISION( OBJ_FIREBALL, OBJ_FIREBALL, collide_fireball_and_fireball ) + DO_SAME_COLLISION( OBJ_ROBOT, OBJ_ROBOT, collide_robot_and_robot ) + NO_SAME_COLLISION( OBJ_HOSTAGE, OBJ_HOSTAGE, collide_hostage_and_hostage ) + DO_SAME_COLLISION( OBJ_PLAYER, OBJ_PLAYER, collide_player_and_player ) + DO_SAME_COLLISION( OBJ_WEAPON, OBJ_WEAPON, collide_weapon_and_weapon ) + NO_SAME_COLLISION( OBJ_CAMERA, OBJ_CAMERA, collide_camera_and_camera ) + NO_SAME_COLLISION( OBJ_POWERUP, OBJ_POWERUP, collide_powerup_and_powerup ) + NO_SAME_COLLISION( OBJ_DEBRIS, OBJ_DEBRIS, collide_debris_and_debris ) + NO_SAME_COLLISION( OBJ_MARKER, OBJ_MARKER, NULL ) + NO_COLLISION( OBJ_FIREBALL, OBJ_ROBOT, collide_fireball_and_robot ) + NO_COLLISION( OBJ_FIREBALL, OBJ_HOSTAGE, collide_fireball_and_hostage ) + NO_COLLISION( OBJ_FIREBALL, OBJ_PLAYER, collide_fireball_and_player ) + NO_COLLISION( OBJ_FIREBALL, OBJ_WEAPON, collide_fireball_and_weapon ) + NO_COLLISION( OBJ_FIREBALL, OBJ_CAMERA, collide_fireball_and_camera ) + NO_COLLISION( OBJ_FIREBALL, OBJ_POWERUP, collide_fireball_and_powerup ) + NO_COLLISION( OBJ_FIREBALL, OBJ_DEBRIS, collide_fireball_and_debris ) + NO_COLLISION( OBJ_ROBOT, OBJ_HOSTAGE, collide_robot_and_hostage ) + DO_COLLISION( OBJ_ROBOT, OBJ_PLAYER, collide_robot_and_player ) + DO_COLLISION( OBJ_ROBOT, OBJ_WEAPON, collide_robot_and_weapon ) + NO_COLLISION( OBJ_ROBOT, OBJ_CAMERA, collide_robot_and_camera ) + NO_COLLISION( OBJ_ROBOT, OBJ_POWERUP, collide_robot_and_powerup ) + NO_COLLISION( OBJ_ROBOT, OBJ_DEBRIS, collide_robot_and_debris ) + DO_COLLISION( OBJ_HOSTAGE, OBJ_PLAYER, collide_hostage_and_player ) + NO_COLLISION( OBJ_HOSTAGE, OBJ_WEAPON, collide_hostage_and_weapon ) + NO_COLLISION( OBJ_HOSTAGE, OBJ_CAMERA, collide_hostage_and_camera ) + NO_COLLISION( OBJ_HOSTAGE, OBJ_POWERUP, collide_hostage_and_powerup ) + NO_COLLISION( OBJ_HOSTAGE, OBJ_DEBRIS, collide_hostage_and_debris ) + DO_COLLISION( OBJ_PLAYER, OBJ_WEAPON, collide_player_and_weapon ) + NO_COLLISION( OBJ_PLAYER, OBJ_CAMERA, collide_player_and_camera ) + DO_COLLISION( OBJ_PLAYER, OBJ_POWERUP, collide_player_and_powerup ) + NO_COLLISION( OBJ_PLAYER, OBJ_DEBRIS, collide_player_and_debris ) + DO_COLLISION( OBJ_PLAYER, OBJ_CNTRLCEN, collide_player_and_controlcen ) + DO_COLLISION( OBJ_PLAYER, OBJ_CLUTTER, collide_player_and_clutter ) + NO_COLLISION( OBJ_WEAPON, OBJ_CAMERA, collide_weapon_and_camera ) + NO_COLLISION( OBJ_WEAPON, OBJ_POWERUP, collide_weapon_and_powerup ) + DO_COLLISION( OBJ_WEAPON, OBJ_DEBRIS, collide_weapon_and_debris ) + NO_COLLISION( OBJ_CAMERA, OBJ_POWERUP, collide_camera_and_powerup ) + NO_COLLISION( OBJ_CAMERA, OBJ_DEBRIS, collide_camera_and_debris ) + NO_COLLISION( OBJ_POWERUP, OBJ_DEBRIS, collide_powerup_and_debris ) + DO_COLLISION( OBJ_WEAPON, OBJ_CNTRLCEN, collide_weapon_and_controlcen ) + DO_COLLISION( OBJ_ROBOT, OBJ_CNTRLCEN, collide_robot_and_controlcen ) + DO_COLLISION( OBJ_WEAPON, OBJ_CLUTTER, collide_weapon_and_clutter ) + + DO_COLLISION( OBJ_MARKER, OBJ_PLAYER, collide_player_and_marker) + NO_COLLISION( OBJ_MARKER, OBJ_ROBOT, NULL) + NO_COLLISION( OBJ_MARKER, OBJ_HOSTAGE, NULL) + NO_COLLISION( OBJ_MARKER, OBJ_WEAPON, NULL) + NO_COLLISION( OBJ_MARKER, OBJ_CAMERA, NULL) + NO_COLLISION( OBJ_MARKER, OBJ_POWERUP, NULL) + NO_COLLISION( OBJ_MARKER, OBJ_DEBRIS, NULL) + + default: + Int3(); //Error( "Unhandled collision_type in collide.c!\n" ); + } +} + +#define ENABLE_COLLISION(type1,type2) \ + CollisionResult[type1][type2] = RESULT_CHECK; \ + CollisionResult[type2][type1] = RESULT_CHECK; + +#define DISABLE_COLLISION(type1,type2) \ + CollisionResult[type1][type2] = RESULT_NOTHING; \ + CollisionResult[type2][type1] = RESULT_NOTHING; + +void collide_init() { + int i, j; + + for (i=0; i < MAX_OBJECT_TYPES; i++ ) + for (j=0; j < MAX_OBJECT_TYPES; j++ ) + CollisionResult[i][j] = RESULT_NOTHING; + + ENABLE_COLLISION( OBJ_WALL, OBJ_ROBOT ); + ENABLE_COLLISION( OBJ_WALL, OBJ_WEAPON ); + ENABLE_COLLISION( OBJ_WALL, OBJ_PLAYER ); + DISABLE_COLLISION( OBJ_FIREBALL, OBJ_FIREBALL ); + + ENABLE_COLLISION( OBJ_ROBOT, OBJ_ROBOT ); +// DISABLE_COLLISION( OBJ_ROBOT, OBJ_ROBOT ); // ALERT: WARNING: HACK: MK = RESPONSIBLE! TESTING!! + + DISABLE_COLLISION( OBJ_HOSTAGE, OBJ_HOSTAGE ); + ENABLE_COLLISION( OBJ_PLAYER, OBJ_PLAYER ); + ENABLE_COLLISION( OBJ_WEAPON, OBJ_WEAPON ); + DISABLE_COLLISION( OBJ_CAMERA, OBJ_CAMERA ); + DISABLE_COLLISION( OBJ_POWERUP, OBJ_POWERUP ); + DISABLE_COLLISION( OBJ_DEBRIS, OBJ_DEBRIS ); + DISABLE_COLLISION( OBJ_FIREBALL, OBJ_ROBOT ); + DISABLE_COLLISION( OBJ_FIREBALL, OBJ_HOSTAGE ); + DISABLE_COLLISION( OBJ_FIREBALL, OBJ_PLAYER ); + DISABLE_COLLISION( OBJ_FIREBALL, OBJ_WEAPON ); + DISABLE_COLLISION( OBJ_FIREBALL, OBJ_CAMERA ); + DISABLE_COLLISION( OBJ_FIREBALL, OBJ_POWERUP ); + DISABLE_COLLISION( OBJ_FIREBALL, OBJ_DEBRIS ); + DISABLE_COLLISION( OBJ_ROBOT, OBJ_HOSTAGE ); + ENABLE_COLLISION( OBJ_ROBOT, OBJ_PLAYER ); + ENABLE_COLLISION( OBJ_ROBOT, OBJ_WEAPON ); + DISABLE_COLLISION( OBJ_ROBOT, OBJ_CAMERA ); + DISABLE_COLLISION( OBJ_ROBOT, OBJ_POWERUP ); + DISABLE_COLLISION( OBJ_ROBOT, OBJ_DEBRIS ); + ENABLE_COLLISION( OBJ_HOSTAGE, OBJ_PLAYER ); + ENABLE_COLLISION( OBJ_HOSTAGE, OBJ_WEAPON ); + DISABLE_COLLISION( OBJ_HOSTAGE, OBJ_CAMERA ); + DISABLE_COLLISION( OBJ_HOSTAGE, OBJ_POWERUP ); + DISABLE_COLLISION( OBJ_HOSTAGE, OBJ_DEBRIS ); + ENABLE_COLLISION( OBJ_PLAYER, OBJ_WEAPON ); + DISABLE_COLLISION( OBJ_PLAYER, OBJ_CAMERA ); + ENABLE_COLLISION( OBJ_PLAYER, OBJ_POWERUP ); + DISABLE_COLLISION( OBJ_PLAYER, OBJ_DEBRIS ); + DISABLE_COLLISION( OBJ_WEAPON, OBJ_CAMERA ); + DISABLE_COLLISION( OBJ_WEAPON, OBJ_POWERUP ); + ENABLE_COLLISION( OBJ_WEAPON, OBJ_DEBRIS ); + DISABLE_COLLISION( OBJ_CAMERA, OBJ_POWERUP ); + DISABLE_COLLISION( OBJ_CAMERA, OBJ_DEBRIS ); + DISABLE_COLLISION( OBJ_POWERUP, OBJ_DEBRIS ); + ENABLE_COLLISION( OBJ_POWERUP, OBJ_WALL ); + ENABLE_COLLISION( OBJ_WEAPON, OBJ_CNTRLCEN ) + ENABLE_COLLISION( OBJ_WEAPON, OBJ_CLUTTER ) + ENABLE_COLLISION( OBJ_PLAYER, OBJ_CNTRLCEN ) + ENABLE_COLLISION( OBJ_ROBOT, OBJ_CNTRLCEN ) + ENABLE_COLLISION( OBJ_PLAYER, OBJ_CLUTTER ) + + ENABLE_COLLISION( OBJ_PLAYER, OBJ_MARKER ); + +} + +void collide_object_with_wall( object * A, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt ) +{ + + switch( A->type ) { + case OBJ_NONE: + Error( "A object of type NONE hit a wall!\n"); + break; + case OBJ_PLAYER: collide_player_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break; + case OBJ_WEAPON: collide_weapon_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break; + case OBJ_DEBRIS: collide_debris_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break; + + case OBJ_FIREBALL: break; //collide_fireball_and_wall(A,hitspeed,hitseg,hitwall,hitpt); + case OBJ_ROBOT: collide_robot_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break; + case OBJ_HOSTAGE: break; //collide_hostage_and_wall(A,hitspeed,hitseg,hitwall,hitpt); + case OBJ_CAMERA: break; //collide_camera_and_wall(A,hitspeed,hitseg,hitwall,hitpt); + case OBJ_POWERUP: break; //collide_powerup_and_wall(A,hitspeed,hitseg,hitwall,hitpt); + case OBJ_GHOST: break; //do nothing + + default: + Error( "Unhandled object type hit wall in collide.c\n" ); + } +} + + diff --git a/main/collide.h b/main/collide.h new file mode 100644 index 00000000..e595b22c --- /dev/null +++ b/main/collide.h @@ -0,0 +1,45 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + + +#ifndef _COLLIDE_H +#define _COLLIDE_H + +void collide_init(); +void collide_two_objects( object * A, object * B, vms_vector *collision_point ); +void collide_object_with_wall( object * A, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt ); +extern void apply_damage_to_player(object *player, object *killer, fix damage); + +// Returns 1 if robot died, else 0. +extern int apply_damage_to_robot(object *robot, fix damage, int killer_objnum); + +extern int Immaterial; + +extern void collide_player_and_weapon( object * player, object * weapon, vms_vector *collision_point ); +extern void collide_player_and_materialization_center(object *objp); +extern void collide_robot_and_materialization_center(object *objp); + +extern void scrape_object_on_wall(object *obj, short hitseg, short hitwall, vms_vector * hitpt ); +extern int maybe_detonate_weapon(object *obj0p, object *obj, vms_vector *pos); + +extern void collide_player_and_nasty_robot( object * player, object * robot, vms_vector *collision_point ); + +extern void net_destroy_controlcen(object *controlcen); +extern void collide_player_and_powerup( object * player, object * powerup, vms_vector *collision_point ); +extern int check_effect_blowup(segment *seg,int side,vms_vector *pnt, object *blower, int force_blowup_flag); +extern void apply_damage_to_controlcen(object *controlcen, fix damage, short who); +extern void bump_one_object(object *obj0, vms_vector *hit_dir, fix damage); + + +#endif diff --git a/main/compbit.h b/main/compbit.h new file mode 100644 index 00000000..eb19df78 --- /dev/null +++ b/main/compbit.h @@ -0,0 +1,23 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + + +#ifndef _COMPBIT_H +#define _COMPBIT_H + +#define BITMAP_TBL_XOR 0xD3 + +extern void encode_rotate_left(char *); + +#endif diff --git a/main/config.c b/main/config.c new file mode 100644 index 00000000..300f092f --- /dev/null +++ b/main/config.c @@ -0,0 +1,1106 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#include + +#ifndef MACINTOSH // I'm going to totally seperate these routines -- yeeech!!!! + // see end of file for macintosh equivs + +#ifdef WINDOWS +#define WIN32_LEAN_AND_MEAN +#include +#include "winapp.h" +#else +#endif + +#include +#include +#include +#include + +#include "pstypes.h" +#include "game.h" +#include "menu.h" +#include "movie.h" +#include "digi.h" +#include "kconfig.h" +#include "palette.h" +#include "joy.h" +#include "songs.h" +#include "args.h" +#include "player.h" +#include "mission.h" +#include "mono.h" +#include "pa_enabl.h" + + + +#ifdef RCS +static char rcsid[] = "$Id: config.c,v 1.1.1.1 2001-01-19 03:30:02 bradleyb Exp $"; +#endif + +ubyte Config_digi_volume = 8; +ubyte Config_midi_volume = 8; +ubyte Config_redbook_volume = 8; +ubyte Config_control_type = 0; +ubyte Config_channels_reversed = 0; +ubyte Config_joystick_sensitivity = 8; + +#ifdef __ENV_MSDOS__ +static char *digi_dev8_str = "DigiDeviceID8"; +static char *digi_dev16_str = "DigiDeviceID16"; +static char *digi_port_str = "DigiPort"; +static char *digi_irq_str = "DigiIrq"; +static char *digi_dma8_str = "DigiDma8"; +static char *digi_dma16_str = "DigiDma16"; +static char *midi_dev_str = "MidiDeviceID"; +static char *midi_port_str = "MidiPort"; + +#define _CRYSTAL_LAKE_8_ST 0xe201 +#define _CRYSTAL_LAKE_16_ST 0xe202 +#define _AWE32_8_ST 0xe208 +#define _AWE32_16_ST 0xe209 +#endif +static char *digi_volume_str = "DigiVolume"; +static char *midi_volume_str = "MidiVolume"; +static char *redbook_enabled_str = "RedbookEnabled"; +static char *redbook_volume_str = "RedbookVolume"; +static char *detail_level_str = "DetailLevel"; +static char *gamma_level_str = "GammaLevel"; +static char *stereo_rev_str = "StereoReverse"; +static char *joystick_min_str = "JoystickMin"; +static char *joystick_max_str = "JoystickMax"; +static char *joystick_cen_str = "JoystickCen"; +static char *last_player_str = "LastPlayer"; +static char *last_mission_str = "LastMission"; +static char *config_vr_type_str = "VR_type"; +static char *config_vr_resolution_str = "VR_resolution"; +static char *config_vr_tracking_str = "VR_tracking"; +static char *movie_hires_str = "MovieHires"; + +char config_last_player[CALLSIGN_LEN+1] = ""; +char config_last_mission[MISSION_NAME_LEN+1] = ""; + +int Config_digi_type = 0; +int Config_digi_dma = 0; +int Config_midi_type = 0; + +#ifdef WINDOWS +int DOSJoySaveMin[4]; +int DOSJoySaveCen[4]; +int DOSJoySaveMax[4]; + +char win95_current_joyname[256]; +#endif + + + +int Config_vr_type = 0; +int Config_vr_resolution = 0; +int Config_vr_tracking = 0; + +int digi_driver_board_16; +int digi_driver_dma_16; + +extern byte Object_complexity, Object_detail, Wall_detail, Wall_render_depth, Debris_amount, SoundChannels; + +void set_custom_detail_vars(void); + + +#define CL_MC0 0xF8F +#define CL_MC1 0xF8D +/* +void CrystalLakeWriteMCP( ushort mc_addr, ubyte mc_data ) +{ + _disable(); + outp( CL_MC0, 0xE2 ); // Write password + outp( mc_addr, mc_data ); // Write data + _enable(); +} + +ubyte CrystalLakeReadMCP( ushort mc_addr ) +{ + ubyte value; + _disable(); + outp( CL_MC0, 0xE2 ); // Write password + value = inp( mc_addr ); // Read data + _enable(); + return value; +} + +void CrystalLakeSetSB() +{ + ubyte tmp; + tmp = CrystalLakeReadMCP( CL_MC1 ); + tmp &= 0x7F; + CrystalLakeWriteMCP( CL_MC1, tmp ); +} + +void CrystalLakeSetWSS() +{ + ubyte tmp; + tmp = CrystalLakeReadMCP( CL_MC1 ); + tmp |= 0x80; + CrystalLakeWriteMCP( CL_MC1, tmp ); +} +*/ +//MovieHires might be changed by -nohighres, so save a "real" copy of it +int SaveMovieHires; +int save_redbook_enabled; + +#ifdef WINDOWS +void CheckMovieAttributes() +{ + HKEY hKey; + DWORD len, type, val; + long lres; + + lres = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Parallax\\Descent II\\1.1\\INSTALL", + 0, KEY_READ, &hKey); + if (lres == ERROR_SUCCESS) { + len = sizeof(val); + lres = RegQueryValueEx(hKey, "HIRES", NULL, &type, &val, &len); + if (lres == ERROR_SUCCESS) { + MovieHires = val; + logentry("HIRES=%d\n", val); + } + RegCloseKey(hKey); + } +} +#endif + + + +int ReadConfigFile() +{ + FILE *infile; + char line[80], *token, *value, *ptr; + ubyte gamma; + int joy_axis_min[7]; + int joy_axis_center[7]; + int joy_axis_max[7]; + int i; + + strcpy( config_last_player, "" ); + + joy_axis_min[0] = joy_axis_min[1] = joy_axis_min[2] = joy_axis_min[3] = 0; + joy_axis_max[0] = joy_axis_max[1] = joy_axis_max[2] = joy_axis_max[3] = 0; + joy_axis_center[0] = joy_axis_center[1] = joy_axis_center[2] = joy_axis_center[3] = 0; + +#ifdef WINDOWS + memset(&joy_axis_min[0], 0, sizeof(int)*7); + memset(&joy_axis_max[0], 0, sizeof(int)*7); + memset(&joy_axis_center[0], 0, sizeof(int)*7); +//@@ joy_set_cal_vals(joy_axis_min, joy_axis_center, joy_axis_max); +#else + joy_set_cal_vals(joy_axis_min, joy_axis_center, joy_axis_max); +#endif + + /*digi_driver_board = 0; + digi_driver_port = 0; + digi_driver_irq = 0; + digi_driver_dma = 0; + + digi_midi_type = 0; + digi_midi_port = 0;*/ + + Config_digi_volume = 8; + Config_midi_volume = 8; + Config_redbook_volume = 8; + Config_control_type = 0; + Config_channels_reversed = 0; + + //set these here in case no cfg file + SaveMovieHires = MovieHires; + save_redbook_enabled = Redbook_enabled; + + infile = fopen("descent.cfg", "rt"); + if (infile == NULL) { + WIN(CheckMovieAttributes()); + return 1; + } + while (!feof(infile)) { + memset(line, 0, 80); + fgets(line, 80, infile); + ptr = &(line[0]); + while (isspace(*ptr)) + ptr++; + if (*ptr != '\0') { + token = strtok(ptr, "="); + value = strtok(NULL, "="); + if (value[strlen(value)-1] == '\n') + value[strlen(value)-1] = 0; +/* if (!strcmp(token, digi_dev8_str)) + digi_driver_board = strtol(value, NULL, 16); + else if (!strcmp(token, digi_dev16_str)) + digi_driver_board_16 = strtol(value, NULL, 16); + else if (!strcmp(token, digi_port_str)) + digi_driver_port = strtol(value, NULL, 16); + else if (!strcmp(token, digi_irq_str)) + digi_driver_irq = strtol(value, NULL, 10); + else if (!strcmp(token, digi_dma8_str)) + digi_driver_dma = strtol(value, NULL, 10); + else if (!strcmp(token, digi_dma16_str)) + digi_driver_dma_16 = strtol(value, NULL, 10); + else*/ if (!strcmp(token, digi_volume_str)) + Config_digi_volume = strtol(value, NULL, 10); + else/* if (!strcmp(token, midi_dev_str)) + digi_midi_type = strtol(value, NULL, 16); + else if (!strcmp(token, midi_port_str)) + digi_midi_port = strtol(value, NULL, 16); + else*/ if (!strcmp(token, midi_volume_str)) + Config_midi_volume = strtol(value, NULL, 10); + else if (!strcmp(token, redbook_enabled_str)) + Redbook_enabled = save_redbook_enabled = strtol(value, NULL, 10); + else if (!strcmp(token, redbook_volume_str)) + Config_redbook_volume = strtol(value, NULL, 10); + else if (!strcmp(token, stereo_rev_str)) + Config_channels_reversed = strtol(value, NULL, 10); + else if (!strcmp(token, gamma_level_str)) { + gamma = strtol(value, NULL, 10); + gr_palette_set_gamma( gamma ); + } + else if (!strcmp(token, detail_level_str)) { + Detail_level = strtol(value, NULL, 10); + if (Detail_level == NUM_DETAIL_LEVELS-1) { + int count,dummy,oc,od,wd,wrd,da,sc; + + count = sscanf (value, "%d,%d,%d,%d,%d,%d,%d\n",&dummy,&oc,&od,&wd,&wrd,&da,&sc); + + if (count == 7) { + Object_complexity = oc; + Object_detail = od; + Wall_detail = wd; + Wall_render_depth = wrd; + Debris_amount = da; + SoundChannels = sc; + set_custom_detail_vars(); + } + #ifdef PA_3DFX_VOODOO // Set to highest detail because you can't change em + Object_complexity=Object_detail=Wall_detail= + Wall_render_depth=Debris_amount=SoundChannels = NUM_DETAIL_LEVELS-1; + Detail_level=NUM_DETAIL_LEVELS-1; + set_custom_detail_vars(); + #endif + } + } + else if (!strcmp(token, joystick_min_str)) { + sscanf( value, "%d,%d,%d,%d", &joy_axis_min[0], &joy_axis_min[1], &joy_axis_min[2], &joy_axis_min[3] ); + } + else if (!strcmp(token, joystick_max_str)) { + sscanf( value, "%d,%d,%d,%d", &joy_axis_max[0], &joy_axis_max[1], &joy_axis_max[2], &joy_axis_max[3] ); + } + else if (!strcmp(token, joystick_cen_str)) { + sscanf( value, "%d,%d,%d,%d", &joy_axis_center[0], &joy_axis_center[1], &joy_axis_center[2], &joy_axis_center[3] ); + } + else if (!strcmp(token, last_player_str)) { + char * p; + strncpy( config_last_player, value, CALLSIGN_LEN ); + p = strchr( config_last_player, '\n'); + if ( p ) *p = 0; + } + else if (!strcmp(token, last_mission_str)) { + char * p; + strncpy( config_last_mission, value, MISSION_NAME_LEN ); + p = strchr( config_last_mission, '\n'); + if ( p ) *p = 0; + } else if (!strcmp(token, config_vr_type_str)) { + Config_vr_type = strtol(value, NULL, 10); + } else if (!strcmp(token, config_vr_resolution_str)) { + Config_vr_resolution = strtol(value, NULL, 10); + } else if (!strcmp(token, config_vr_tracking_str)) { + Config_vr_tracking = strtol(value, NULL, 10); + } else if (!strcmp(token, movie_hires_str)) { + SaveMovieHires = MovieHires = strtol(value, NULL, 10); + } + } + } + + fclose(infile); + +#ifdef WINDOWS + for (i=0;i<4;i++) + { + DOSJoySaveMin[i]=joy_axis_min[i]; + DOSJoySaveCen[i]=joy_axis_center[i]; + DOSJoySaveMax[i]=joy_axis_max[i]; + } +#else + joy_set_cal_vals(joy_axis_min, joy_axis_center, joy_axis_max); +#endif + + i = args_find( "-volume" ); + + if ( i > 0 ) { + i = atoi( Args[i+1] ); + if ( i < 0 ) i = 0; + if ( i > 100 ) i = 100; + Config_digi_volume = (i*8)/100; + Config_midi_volume = (i*8)/100; + Config_redbook_volume = (i*8)/100; + } + + if ( Config_digi_volume > 8 ) Config_digi_volume = 8; + if ( Config_midi_volume > 8 ) Config_midi_volume = 8; + if ( Config_redbook_volume > 8 ) Config_redbook_volume = 8; + + digi_set_volume( (Config_digi_volume*32768)/8, (Config_midi_volume*128)/8 ); +/* + printf( "DigiDeviceID: 0x%x\n", digi_driver_board ); + printf( "DigiPort: 0x%x\n", digi_driver_port ); + printf( "DigiIrq: 0x%x\n", digi_driver_irq ); + printf( "DigiDma: 0x%x\n", digi_driver_dma ); + printf( "MidiDeviceID: 0x%x\n", digi_midi_type ); + printf( "MidiPort: 0x%x\n", digi_midi_port ); + key_getch(); +*/ + + /*Config_midi_type = digi_midi_type; + Config_digi_type = digi_driver_board; + Config_digi_dma = digi_driver_dma;*/ + +#if !defined WINDOWS && !defined __ENV_LINUX__ + if (digi_driver_board_16 > 0 && !args_find("-no16bit") && digi_driver_board_16 != _GUS_16_ST) { + digi_driver_board = digi_driver_board_16; + digi_driver_dma = digi_driver_dma_16; + } +#endif + + // HACK!!! + //Hack to make some cards look like others, such as + //the Crytal Lake look like Microsoft Sound System +#if !defined WINDOWS && !defined __ENV_LINUX__ + if ( digi_driver_board == _CRYSTAL_LAKE_8_ST ) { + ubyte tmp; + tmp = CrystalLakeReadMCP( CL_MC1 ); + if ( !(tmp & 0x80) ) + atexit( CrystalLakeSetSB ); // Restore to SB when done. + CrystalLakeSetWSS(); + digi_driver_board = _MICROSOFT_8_ST; + } else if ( digi_driver_board == _CRYSTAL_LAKE_16_ST ) { + ubyte tmp; + tmp = CrystalLakeReadMCP( CL_MC1 ); + if ( !(tmp & 0x80) ) + atexit( CrystalLakeSetSB ); // Restore to SB when done. + CrystalLakeSetWSS(); + digi_driver_board = _MICROSOFT_16_ST; + } else if ( digi_driver_board == _AWE32_8_ST ) { + digi_driver_board = _SB16_8_ST; + } else if ( digi_driver_board == _AWE32_16_ST ) { + digi_driver_board = _SB16_16_ST; + } else + digi_driver_board = digi_driver_board; +#else + infile = fopen("descentw.cfg", "rt"); + if (infile) { + while (!feof(infile)) { + memset(line, 0, 80); + fgets(line, 80, infile); + ptr = &(line[0]); + while (isspace(*ptr)) + ptr++; + if (*ptr != '\0') { + token = strtok(ptr, "="); + value = strtok(NULL, "="); + if (value[strlen(value)-1] == '\n') + value[strlen(value)-1] = 0; + if (!strcmp(token, joystick_min_str)) { + sscanf( value, "%d,%d,%d,%d,%d,%d,%d", &joy_axis_min[0], &joy_axis_min[1], &joy_axis_min[2], &joy_axis_min[3], &joy_axis_min[4], &joy_axis_min[5], &joy_axis_min[6] ); + } + else if (!strcmp(token, joystick_max_str)) { + sscanf( value, "%d,%d,%d,%d,%d,%d,%d", &joy_axis_max[0], &joy_axis_max[1], &joy_axis_max[2], &joy_axis_max[3], &joy_axis_max[4], &joy_axis_max[5], &joy_axis_max[6] ); + } + else if (!strcmp(token, joystick_cen_str)) { + sscanf( value, "%d,%d,%d,%d,%d,%d,%d", &joy_axis_center[0], &joy_axis_center[1], &joy_axis_center[2], &joy_axis_center[3], &joy_axis_center[4], &joy_axis_center[5], &joy_axis_center[6] ); + } + } + } + fclose(infile); + } +#endif + + return 0; +} + +int WriteConfigFile() +{ + FILE *infile; + char str[256]; + int joy_axis_min[7]; + int joy_axis_center[7]; + int joy_axis_max[7]; + ubyte gamma = gr_palette_get_gamma(); + + joy_get_cal_vals(joy_axis_min, joy_axis_center, joy_axis_max); + +#ifdef WINDOWS + for (i=0;i<4;i++) + { + joy_axis_min[i]=DOSJoySaveMin[i]; + joy_axis_center[i]=DOSJoySaveCen[i]; + joy_axis_max[i]=DOSJoySaveMax[i]; + } +#endif + + infile = fopen("descent.cfg", "wt"); + if (infile == NULL) { + return 1; + } + /*sprintf (str, "%s=0x%x\n", digi_dev8_str, Config_digi_type); + fputs(str, infile); + sprintf (str, "%s=0x%x\n", digi_dev16_str, digi_driver_board_16); + fputs(str, infile); + sprintf (str, "%s=0x%x\n", digi_port_str, digi_driver_port); + fputs(str, infile); + sprintf (str, "%s=%d\n", digi_irq_str, digi_driver_irq); + fputs(str, infile); + sprintf (str, "%s=%d\n", digi_dma8_str, Config_digi_dma); + fputs(str, infile); + sprintf (str, "%s=%d\n", digi_dma16_str, digi_driver_dma_16); + fputs(str, infile);*/ + sprintf (str, "%s=%d\n", digi_volume_str, Config_digi_volume); + fputs(str, infile); + /*sprintf (str, "%s=0x%x\n", midi_dev_str, Config_midi_type); + fputs(str, infile); + sprintf (str, "%s=0x%x\n", midi_port_str, digi_midi_port); + fputs(str, infile);*/ + sprintf (str, "%s=%d\n", midi_volume_str, Config_midi_volume); + fputs(str, infile); + sprintf (str, "%s=%d\n", redbook_enabled_str, args_find("-noredbook")?save_redbook_enabled:Redbook_enabled); + fputs(str, infile); + sprintf (str, "%s=%d\n", redbook_volume_str, Config_redbook_volume); + fputs(str, infile); + sprintf (str, "%s=%d\n", stereo_rev_str, Config_channels_reversed); + fputs(str, infile); + sprintf (str, "%s=%d\n", gamma_level_str, gamma); + fputs(str, infile); + if (Detail_level == NUM_DETAIL_LEVELS-1) + sprintf (str, "%s=%d,%d,%d,%d,%d,%d,%d\n", detail_level_str, Detail_level, + Object_complexity,Object_detail,Wall_detail,Wall_render_depth,Debris_amount,SoundChannels); + else + sprintf (str, "%s=%d\n", detail_level_str, Detail_level); + fputs(str, infile); + + sprintf (str, "%s=%d,%d,%d,%d\n", joystick_min_str, joy_axis_min[0], joy_axis_min[1], joy_axis_min[2], joy_axis_min[3] ); + fputs(str, infile); + sprintf (str, "%s=%d,%d,%d,%d\n", joystick_cen_str, joy_axis_center[0], joy_axis_center[1], joy_axis_center[2], joy_axis_center[3] ); + fputs(str, infile); + sprintf (str, "%s=%d,%d,%d,%d\n", joystick_max_str, joy_axis_max[0], joy_axis_max[1], joy_axis_max[2], joy_axis_max[3] ); + fputs(str, infile); + + sprintf (str, "%s=%s\n", last_player_str, Players[Player_num].callsign ); + fputs(str, infile); + sprintf (str, "%s=%s\n", last_mission_str, config_last_mission ); + fputs(str, infile); + sprintf (str, "%s=%d\n", config_vr_type_str, Config_vr_type ); + fputs(str, infile); + sprintf (str, "%s=%d\n", config_vr_resolution_str, Config_vr_resolution ); + fputs(str, infile); + sprintf (str, "%s=%d\n", config_vr_tracking_str, Config_vr_tracking ); + fputs(str, infile); + sprintf (str, "%s=%d\n", movie_hires_str, SaveMovieHires ); + fputs(str, infile); + + fclose(infile); + +#ifdef WINDOWS +{ +// Save Windows Config File + char joyname[256]; + + + joy_get_cal_vals(joy_axis_min, joy_axis_center, joy_axis_max); + + infile = fopen("descentw.cfg", "wt"); + if (infile == NULL) return 1; + + sprintf(str, "%s=%d,%d,%d,%d,%d,%d,%d\n", joystick_min_str, + joy_axis_min[0], joy_axis_min[1], joy_axis_min[2], joy_axis_min[3], + joy_axis_min[4], joy_axis_min[5], joy_axis_min[6]); + fputs(str, infile); + sprintf(str, "%s=%d,%d,%d,%d,%d,%d,%d\n", joystick_cen_str, + joy_axis_center[0], joy_axis_center[1], joy_axis_center[2], joy_axis_center[3], + joy_axis_center[4], joy_axis_center[5], joy_axis_center[6]); + fputs(str, infile); + sprintf(str, "%s=%d,%d,%d,%d,%d,%d,%d\n", joystick_max_str, + joy_axis_max[0], joy_axis_max[1], joy_axis_max[2], joy_axis_max[3], + joy_axis_max[4], joy_axis_max[5], joy_axis_max[6]); + fputs(str, infile); + + fclose(infile); +} + CheckMovieAttributes(); +#endif + + return 0; +} + +#else // !defined(MACINTOSH) + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "pa_enabl.h" // because some prefs rely on this fact +#include "error.h" +#include "pstypes.h" +#include "game.h" +#include "digi.h" +#include "kconfig.h" +#include "palette.h" +#include "joy.h" +#include "args.h" +#include "player.h" +#include "mission.h" +#include "prefs.h" // prefs file for configuration stuff -- from DeSalvo + +#if defined(POLY_ACC) +#include "poly_acc.h" +#endif + +#ifdef RCS +static char rcsid[] = "$Id: config.c,v 1.1.1.1 2001-01-19 03:30:02 bradleyb Exp $"; +#endif + +#define MAX_CTB_LEN 512 + +typedef struct preferences { + ubyte digi_volume; + ubyte midi_volume; + ubyte stereo_reverse; + ubyte detail_level; + ubyte oc; // object complexity + ubyte od; // object detail + ubyte wd; // wall detail + ubyte wrd; // wall render depth + ubyte da; // debris amount + ubyte sc; // sound channels + ubyte gamma_level; + ubyte pixel_double; + int joy_axis_min[4]; + int joy_axis_max[4]; + int joy_axis_center[4]; + char lastplayer[CALLSIGN_LEN+1]; + char lastmission[MISSION_NAME_LEN+1]; + char ctb_config[MAX_CTB_LEN]; + int ctb_tool; + ubyte master_volume; + ubyte display_dialog; + ubyte change_resolution; + ubyte nosound; + ubyte nomidi; + ubyte sound_11k; + ubyte no_movies; + ubyte game_monitor; + ubyte redbook_volume; + ubyte enable_rave; + ubyte enable_input_sprockets; +} Preferences; + +char config_last_player[CALLSIGN_LEN+1] = ""; +char config_last_mission[MISSION_NAME_LEN+1] = ""; +char config_last_ctb_cfg[MAX_CTB_LEN] = ""; +int config_last_ctb_tool; +ubyte Config_master_volume = 4; +ubyte Config_digi_volume = 8; +ubyte Config_midi_volume = 8; +ubyte Config_redbook_volume = 8; +ubyte Config_control_type = 0; +ubyte Config_channels_reversed = 0; +ubyte Config_joystick_sensitivity = 8; + +int Config_vr_type = 0; +int Config_vr_resolution = 0; +int Config_vr_tracking = 0; + +extern byte Object_complexity, Object_detail, Wall_detail, Wall_render_depth, Debris_amount, SoundChannels; +extern void digi_set_master_volume( int volume ); + +void set_custom_detail_vars(void); + +static ubyte have_prefs = 0; + +//¥ ------------------------------ Private Definitions +//¥ ------------------------------ Private Types + +typedef struct +{ + Str31 fileName; + OSType creator; + OSType fileType; + OSType resType; + short resID; +} PrefsInfo, *PrefsInfoPtr, **PrefsInfoHandle; + +//¥ ------------------------------ Private Variables + +static PrefsInfo prefsInfo; +static Boolean prefsInited = 0; + +//¥ ------------------------------ Private Functions + +static void Pstrcpy(StringPtr dst, StringPtr src); +static void Pstrcat(StringPtr dst, StringPtr src); +static Boolean FindPrefsFile(short *prefVRefNum, long *prefDirID); + +//¥ -------------------- Pstrcpy + +static void +Pstrcpy(StringPtr dst, StringPtr src) +{ + BlockMove(src, dst, (*src) + 1); +} + +//¥ -------------------- Pstrcat + +static void +Pstrcat(StringPtr dst, StringPtr src) +{ + BlockMove(src + 1, dst + (*dst) + 1, *src); + *dst += *src; +} + +//¥ -------------------- FindPrefsFile + +static Boolean +FindPrefsFile(short *prefVRefNum, long *prefDirID) +{ +OSErr theErr; +long response; +CInfoPBRec infoPB; + + if (! prefsInited) + return (0); + + theErr = Gestalt(gestaltFindFolderAttr, &response); + if (theErr == noErr && ((response >> gestaltFindFolderPresent) & 1)) + { + //¥ Find (or make) it the easy way... + theErr = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder, prefVRefNum, prefDirID); + } + else + { + SysEnvRec theSysEnv; + StringPtr prefFolderName = "\pPreferences"; + + //¥ yeachh -- we have to do it all by hand! + theErr = SysEnvirons(1, &theSysEnv); + if (theErr != noErr) + return (0); + + *prefVRefNum = theSysEnv.sysVRefNum; + + //¥ Check whether Preferences folder already exists + infoPB.hFileInfo.ioCompletion = 0; + infoPB.hFileInfo.ioNamePtr = prefFolderName; + infoPB.hFileInfo.ioVRefNum = *prefVRefNum; + infoPB.hFileInfo.ioFDirIndex = 0; + infoPB.hFileInfo.ioDirID = 0; + + theErr = PBGetCatInfo(&infoPB, 0); + if (theErr == noErr) + { + *prefDirID = infoPB.hFileInfo.ioDirID; + } + else if (theErr == fnfErr) //¥ Preferences doesn't already exist + { + HParamBlockRec dirPB; + + //¥ Create "Preferences" folder + dirPB.fileParam.ioCompletion = 0; + dirPB.fileParam.ioVRefNum = *prefVRefNum; + dirPB.fileParam.ioNamePtr = prefFolderName; + dirPB.fileParam.ioDirID = 0; + + theErr = PBDirCreate(&dirPB, 0); + if (theErr == noErr) + *prefDirID = dirPB.fileParam.ioDirID; + } + } + + //¥ If we make it here OK, create Preferences file if necessary + if (theErr == noErr) + { + infoPB.hFileInfo.ioCompletion = 0; + infoPB.hFileInfo.ioNamePtr = prefsInfo.fileName; + infoPB.hFileInfo.ioVRefNum = *prefVRefNum; + infoPB.hFileInfo.ioFDirIndex = 0; + infoPB.hFileInfo.ioDirID = *prefDirID; + + theErr = PBGetCatInfo(&infoPB, 0); + if (theErr == fnfErr) + { + theErr = HCreate(*prefVRefNum, *prefDirID, prefsInfo.fileName, prefsInfo.creator, prefsInfo.fileType); + if (theErr == noErr) + { + HCreateResFile(*prefVRefNum, *prefDirID, prefsInfo.fileName); + theErr = ResError(); + } + } + } + + return (theErr == noErr); +} + +//¥ -------------------- InitPrefsFile + +#define UNKNOWN_TYPE 0x3f3f3f3f + +void +InitPrefsFile(OSType creator) +{ + OSErr err; +PrefsInfoHandle piHdl; + + if ((piHdl = (PrefsInfoHandle) GetResource('PRFI', 0)) == nil) + { + ProcessSerialNumber thePSN; + ProcessInfoRec thePIR; + FSSpec appSpec; + StringPtr app_string; + +#if 0 + GetCurrentProcess(&thePSN); + thePIR.processName = nil; + thePIR.processAppSpec = &appSpec; + + //¥ Set default to 'ÇApplicationÈ Prefs', PREF 0 + err = GetProcessInformation(&thePSN, &thePIR); + if (err) + Int3(); +#endif + app_string = LMGetCurApName(); +// Pstrcpy(prefsInfo.fileName, appSpec.name); + Pstrcpy(prefsInfo.fileName, app_string); + Pstrcat(prefsInfo.fileName, "\p Preferences"); + + //¥ Set creator to calling application's signature (should be able to + //¥ Determine this automatically, but unable to for some reason) + prefsInfo.creator = creator; + prefsInfo.fileType = 'pref'; + prefsInfo.resType = 'pref'; + prefsInfo.resID = 0; + } + else + { + //¥ Get Preferences file setup from PRFI 0 + BlockMove(*piHdl, &prefsInfo, sizeof (prefsInfo)); + ReleaseResource((Handle) piHdl); + + if (prefsInfo.creator == UNKNOWN_TYPE) + prefsInfo.creator = creator; + } + + prefsInited = 1; +} + +//¥ -------------------- LoadPrefsFile + +OSErr +LoadPrefsFile(Handle prefsHdl) +{ +short prefVRefNum, prefRefNum; +long prefDirID; +OSErr theErr = noErr; +Handle origHdl; +Size prefSize, origSize; + + if (prefsHdl == nil) + return (nilHandleErr); + + prefSize = GetHandleSize(prefsHdl); + + if (! FindPrefsFile(&prefVRefNum, &prefDirID)) + return (fnfErr); + + prefRefNum = HOpenResFile(prefVRefNum, prefDirID, prefsInfo.fileName, fsRdWrPerm); + if (prefRefNum == -1) + return (ResError()); + + //¥ Not finding the resource is not an error -- caller will use default data + if ((origHdl = Get1Resource(prefsInfo.resType, prefsInfo.resID)) != nil) + { + origSize = GetHandleSize(origHdl); + if (origSize > prefSize) //¥ Extend handle for extra stored data + SetHandleSize(prefsHdl, origSize); + + BlockMove(*origHdl, *prefsHdl, origSize); + ReleaseResource(origHdl); + } + + CloseResFile(prefRefNum); + + if (theErr == noErr) + theErr = ResError(); + + return (theErr); +} + +//¥ -------------------- SavePrefsFile + +OSErr +SavePrefsFile(Handle prefHdl) +{ +short prefVRefNum, prefRefNum; +long prefDirID; +Handle origHdl = nil; +Size origSize, prefSize; +OSErr theErr = noErr; + + if (! FindPrefsFile(&prefVRefNum, &prefDirID)) + return (fnfErr); + + if (prefHdl == nil) + return (nilHandleErr); + + prefSize = GetHandleSize(prefHdl); + + prefRefNum = HOpenResFile(prefVRefNum, prefDirID, prefsInfo.fileName, fsRdWrPerm); + if (prefRefNum == -1) + return (ResError()); + + if ((origHdl = Get1Resource(prefsInfo.resType, prefsInfo.resID)) != nil) + { + //¥ Overwrite existing preferences + origSize = GetHandleSize(origHdl); + if (prefSize > origSize) + SetHandleSize(origHdl, prefSize); + + BlockMove(*prefHdl, *origHdl, prefSize); + ChangedResource(origHdl); + WriteResource(origHdl); + ReleaseResource(origHdl); + } + else + { + //¥ Store specified preferences for the first time + AddResource(prefHdl, prefsInfo.resType, prefsInfo.resID, "\p"); + WriteResource(prefHdl); + DetachResource(prefHdl); + } + + CloseResFile(prefRefNum); + + if (theErr == noErr) + theErr = ResError(); + + return (theErr); +} + +//¥ ------------------------------------------------------------------------------------------- + +/* + + This module provides the ability to save and load a preferences file in the + Preferences folder in the System Folder. An optional resource, PRFI 0, + is used to provide specifications for the preferences file (creator, etc.). + + Three functions are provided: + + void InitPrefsFile(OSType creator) + + This function will initialize the preferences file, that is, it will create + it in the appropriate place if it doesn't currently exist. It should be + called with the creator code for the application. Note that the creator + code specified in PRFI 0 (if any) will be used only if the creator code + passed to this function is '????'. Without the PRFI 0 resource, the default + specifications are: + + File Name: "{Application} Prefs" (i.e., the name of the app plus " Prefs" + Creator: the creator passed to InitPrefsFile + Type: 'PREF' + Pref Resource Type: 'PREF' + Pref Resource ID: 0 + + The PRFI 0 resource allows you to specify overrides for each of the above + values. This is useful for development, since the application name might + go through changes, but the preferences file name is held constant. + + OSErr LoadPrefsFile(Handle prefsHndl) + + This function will attempt to copy the data stored in the preferences + file to the given handle (which must be pre-allocated). If the handle is too + small, then it will be enlarged. If it is too large, it will not be resized. + The data in the preferences file (normally in PREF 0) will then be copied + into the handle. If the preferences file did not exist, the original data + in the handle will not change. + + OSErr SavePrefsFile(Handle prefsHndl) + + This function will attempt to save the given handle to the preferences + file. Its contents will completely replace the previous data (normally + the PREF 0 resource). + + In typical use, you will use InitPrefsFile once, then allocate a handle large + enough to contain your preferences data, and initialize it with default values. + Throughout the course of your program, the handle will undergo modification as + user preferences change. You can use SavePrefsFile anytime to update the + preferences file, or wait until program exit to do so. + +*/ + +int ReadConfigFile() +{ + int i; + OSErr err; + Handle prefs_handle; + Preferences *prefs; + char *p; + + if (!have_prefs) { // not initialized....get a handle to the preferences file + InitPrefsFile('DCT2'); + have_prefs = 1; + } + + prefs_handle = NewHandleClear(sizeof(Preferences)); // new prefs handle + if (prefs_handle == NULL) + return; + + prefs = (Preferences *)(*prefs_handle); + err = LoadPrefsFile(prefs_handle); + if (err) { + DisposeHandle(prefs_handle); + return -1; + } + + p = (char *)prefs; + for (i = 0; i < sizeof(Preferences); i++) { + if (*p != 0) + break; + p++; + } + if ( i == sizeof(Preferences) ) + return -1; + + Config_digi_volume = prefs->digi_volume; + Config_midi_volume = prefs->midi_volume; + Config_master_volume = prefs->master_volume; + Config_redbook_volume = prefs->redbook_volume; + Config_channels_reversed = prefs->stereo_reverse; + gr_palette_set_gamma( (int)(prefs->gamma_level) ); + + Scanline_double = (int)prefs->pixel_double; + if ( PAEnabled ) + Scanline_double = 0; // can't double with hardware acceleration + + Detail_level = prefs->detail_level; + if (Detail_level == NUM_DETAIL_LEVELS-1) { + Object_complexity = prefs->oc; + Object_detail = prefs->od; + Wall_detail = prefs->wd; + Wall_render_depth = prefs->wrd; + Debris_amount = prefs->da; + SoundChannels = prefs->sc; + set_custom_detail_vars(); + } + #ifdef PA_3DFX_VOODOO // Set to highest detail because you can't change em + Object_complexity=Object_detail=Wall_detail= + Wall_render_depth=Debris_amount=SoundChannels = NUM_DETAIL_LEVELS-1; + Detail_level=NUM_DETAIL_LEVELS-1; + set_custom_detail_vars(); + #endif + + strncpy( config_last_player, prefs->lastplayer, CALLSIGN_LEN ); + p = strchr(config_last_player, '\n' ); + if (p) *p = 0; + + strncpy(config_last_mission, prefs->lastmission, MISSION_NAME_LEN); + p = strchr(config_last_mission, '\n' ); + if (p) *p = 0; + + strcpy(config_last_ctb_cfg, prefs->ctb_config); + + if ( Config_digi_volume > 8 ) Config_digi_volume = 8; + + if ( Config_midi_volume > 8 ) Config_midi_volume = 8; + + joy_set_cal_vals( prefs->joy_axis_min, prefs->joy_axis_center, prefs->joy_axis_max); + digi_set_volume( (Config_digi_volume*256)/8, (Config_midi_volume*256)/8 ); + digi_set_master_volume(Config_master_volume); + + gConfigInfo.mDoNotDisplayOptions = prefs->display_dialog; + gConfigInfo.mUse11kSounds = prefs->sound_11k; + gConfigInfo.mDisableSound = prefs->nosound; + gConfigInfo.mDisableMIDIMusic = prefs->nomidi; + gConfigInfo.mChangeResolution = prefs->change_resolution; + gConfigInfo.mDoNotPlayMovies = prefs->no_movies; + gConfigInfo.mGameMonitor = prefs->game_monitor; + gConfigInfo.mAcceleration = prefs->enable_rave; + gConfigInfo.mInputSprockets = prefs->enable_input_sprockets; + + DisposeHandle(prefs_handle); + return 0; +} + +int WriteConfigFile() +{ + OSErr err; + Handle prefs_handle; + Preferences *prefs; + + prefs_handle = NewHandleClear(sizeof(Preferences)); // new prefs handle + if (prefs_handle == NULL) + return; + + prefs = (Preferences *)(*prefs_handle); + + joy_get_cal_vals(prefs->joy_axis_min, prefs->joy_axis_center, prefs->joy_axis_max); + prefs->digi_volume = Config_digi_volume; + prefs->midi_volume = Config_midi_volume; + prefs->stereo_reverse = Config_channels_reversed; + prefs->detail_level = Detail_level; + if (Detail_level == NUM_DETAIL_LEVELS-1) { + prefs->oc = Object_complexity; + prefs->od = Object_detail; + prefs->wd = Wall_detail; + prefs->wrd = Wall_render_depth; + prefs->da = Debris_amount; + prefs->sc = SoundChannels; + } + prefs->gamma_level = (ubyte)gr_palette_get_gamma(); + + if ( !PAEnabled ) + prefs->pixel_double = (ubyte)Scanline_double; // hmm..don't write this out if doing hardware accel. + + strncpy( prefs->lastplayer, Players[Player_num].callsign, CALLSIGN_LEN ); + strncpy( prefs->lastmission, config_last_mission, MISSION_NAME_LEN ); + strcpy( prefs->ctb_config, config_last_ctb_cfg); + prefs->ctb_tool = config_last_ctb_tool; + prefs->master_volume = Config_master_volume; + prefs->display_dialog = gConfigInfo.mDoNotDisplayOptions; + prefs->change_resolution = gConfigInfo.mChangeResolution; + prefs->nosound = gConfigInfo.mDisableSound; + prefs->nomidi = gConfigInfo.mDisableMIDIMusic; + prefs->sound_11k = gConfigInfo.mUse11kSounds; + prefs->no_movies = gConfigInfo.mDoNotPlayMovies; + prefs->game_monitor = gConfigInfo.mGameMonitor; + prefs->redbook_volume = Config_redbook_volume; + prefs->enable_rave = gConfigInfo.mAcceleration; + prefs->enable_input_sprockets = gConfigInfo.mInputSprockets; + + err = SavePrefsFile(prefs_handle); + DisposeHandle(prefs_handle); + return (int)err; +} + +#endif + diff --git a/main/config.h b/main/config.h new file mode 100644 index 00000000..974f5cbe --- /dev/null +++ b/main/config.h @@ -0,0 +1,65 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + + +#ifndef _CONFIG_H +#define _CONFIG_H + +#include "player.h" + +extern int ReadConfigFile(void); +extern int WriteConfigFile(void); + +extern char config_last_player[CALLSIGN_LEN+1]; + +extern char config_last_mission[]; + +extern ubyte Config_digi_volume; +extern ubyte Config_midi_volume; +#ifdef MACINTOSH +typedef struct ConfigInfoStruct +{ + ubyte mDoNotDisplayOptions; + ubyte mUse11kSounds; + ubyte mDisableSound; + ubyte mDisableMIDIMusic; + ubyte mChangeResolution; + ubyte mDoNotPlayMovies; + ubyte mUserChoseQuit; + ubyte mGameMonitor; + ubyte mAcceleration; // allow RAVE level acceleration + ubyte mInputSprockets; // allow use of Input Sprocket devices +} ConfigInfo; + +extern ConfigInfo gConfigInfo; +extern ubyte Config_master_volume; +#endif +extern ubyte Config_redbook_volume; +extern ubyte Config_control_type; +extern ubyte Config_channels_reversed; +extern ubyte Config_joystick_sensitivity; + +//values for Config_control_type +#define CONTROL_NONE 0 +#define CONTROL_JOYSTICK 1 +#define CONTROL_FLIGHTSTICK_PRO 2 +#define CONTROL_THRUSTMASTER_FCS 3 +#define CONTROL_GRAVIS_GAMEPAD 4 +#define CONTROL_MOUSE 5 +#define CONTROL_CYBERMAN 6 +#define CONTROL_WINJOYSTICK 7 + +#define CONTROL_MAX_TYPES 8 + +#endif diff --git a/main/console.c b/main/console.c new file mode 100644 index 00000000..aefd188d --- /dev/null +++ b/main/console.c @@ -0,0 +1,155 @@ +#include +#include +#include +#include +#include +#include +#include "pstypes.h" +#include "u_mem.h" +#include "error.h" +#include "console.h" +#include "cmd.h" + +int text_console_enabled = 1; +cvar_t *cvar_vars = NULL; + +/* Console specific cvars */ +/* How discriminating we are about which messages are displayed */ +cvar_t con_threshold = {"con_threshold", "0",}; + +/* Private console stuff */ +#define CON_NUM_LINES 40 +#define CON_LINE_LEN 40 +static char con_display[40][40]; +static int con_line; /* Current display line */ + +/* ====== + * con_init - Initialise the console. + * ====== + */ +int con_init(void) +{ + /* Make sure the output is unbuffered */ + if (text_console_enabled) { + setbuf (stdout, NULL); + setbuf (stderr, NULL); + } + + memset(con_display, ' ', sizeof(con_display)); + con_line = 0; + + /* Initialise the cvars */ + cvar_registervariable (&con_threshold); + return 0; +} + +/* ====== + * con_printf - Print a message to the console. + * ====== + */ +void con_printf(int priority, char *fmt, ...) +{ + va_list arglist; + char buffer[2048]; + + if (priority <= ((int)con_threshold.value)) + { + va_start (arglist, fmt); + vsnprintf (buffer, 2048, fmt, arglist); + if (text_console_enabled) vprintf(fmt, arglist); + va_end (arglist); + +/* for (i=0; inext = NULL; + cvar->value = strtod(cvar->string, (char **) NULL); + + if (cvar_vars == NULL) + { + cvar_vars = cvar; + } else + { + for (ptr = cvar_vars; ptr->next != NULL; ptr = ptr->next) ; + ptr->next = cvar; + } +} + +/* ====== + * cvar_set - Set a CVar's value + * ====== + */ +void cvar_set (char *cvar_name, char *value) +{ + cvar_t *ptr; + + for (ptr = cvar_vars; ptr != NULL; ptr = ptr->next) + if (!strcmp(cvar_name, ptr->name)) break; + + if (ptr == NULL) return; // If we didn't find the cvar, give up + + ptr->value = strtod(value, (char **) NULL); +} + +/* ====== + * cvar() - Get a CVar's value + * ====== + */ +float cvar (char *cvar_name) +{ + cvar_t *ptr; + + for (ptr = cvar_vars; ptr != NULL; ptr = ptr->next) + if (!strcmp(cvar_name, ptr->name)) break; + + if (ptr == NULL) return 0.0; // If we didn't find the cvar, give up + + return ptr->value; +} + + +/* ========================================================================== + * DRAWING + * ========================================================================== + */ +void con_draw(void) +{ +/* char buffer[CON_LINE_LEN+1]; + int i,j; */ +/* for (i = con_line, j=0; j < 20; i = (i+1) % CON_NUM_LINES, j++) + { + memcpy(buffer, con_display[i], CON_LINE_LEN); + buffer[CON_LINE_LEN] = 0; + gr_string(1,j*10,buffer); + }*/ +} diff --git a/main/controls.c b/main/controls.c new file mode 100644 index 00000000..535466ec --- /dev/null +++ b/main/controls.c @@ -0,0 +1,197 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + +#ifdef RCS +static char rcsid[] = "$Id: controls.c,v 1.1.1.1 2001-01-19 03:30:01 bradleyb Exp $"; +#endif + +#include +#include +#include + +#include "pstypes.h" +#include "mono.h" +#include "key.h" +#include "joy.h" +#include "timer.h" +#include "error.h" + +#include "inferno.h" +#include "game.h" +#include "object.h" +#include "player.h" + +#include "controls.h" +#include "joydefs.h" +#include "render.h" +#include "args.h" +#include "palette.h" +#include "mouse.h" +#include "kconfig.h" +#include "laser.h" +#include "multi.h" +#include "vclip.h" +#include "fireball.h" + +//look at keyboard, mouse, joystick, CyberMan, whatever, and set +//physics vars rotvel, velocity + +fix Afterburner_charge=f1_0; + +#define AFTERBURNER_USE_SECS 3 //use up in 3 seconds +#define DROP_DELTA_TIME (f1_0/15) //drop 3 per second + +extern int Drop_afterburner_blob_flag; //ugly hack + +extern fix Seismic_tremor_magnitude; + +void read_flying_controls( object * obj ) +{ + fix forward_thrust_time; + + Assert(FrameTime > 0); //Get MATT if hit this! + + if (Player_is_dead) { + vm_vec_zero(&obj->mtype.phys_info.rotthrust); + vm_vec_zero(&obj->mtype.phys_info.thrust); + return; + } + + if ((obj->type!=OBJ_PLAYER) || (obj->id!=Player_num)) return; //references to player_ship require that this obj be the player + + if (Guided_missile[Player_num] && Guided_missile[Player_num]->signature==Guided_missile_sig[Player_num]) { + vms_angvec rotangs; + vms_matrix rotmat,tempm; + fix speed; + + //this is a horrible hack. guided missile stuff should not be + //handled in the middle of a routine that is dealing with the player + + vm_vec_zero(&obj->mtype.phys_info.rotthrust); + + rotangs.p = Controls.pitch_time / 2 + Seismic_tremor_magnitude/64; + rotangs.b = Controls.bank_time / 2 + Seismic_tremor_magnitude/16; + rotangs.h = Controls.heading_time / 2 + Seismic_tremor_magnitude/64; + + vm_angles_2_matrix(&rotmat,&rotangs); + + vm_matrix_x_matrix(&tempm,&Guided_missile[Player_num]->orient,&rotmat); + + Guided_missile[Player_num]->orient = tempm; + + speed = Weapon_info[Guided_missile[Player_num]->id].speed[Difficulty_level]; + + vm_vec_copy_scale(&Guided_missile[Player_num]->mtype.phys_info.velocity,&Guided_missile[Player_num]->orient.fvec,speed); +#ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_guided_info (Guided_missile[Player_num],0); +#endif + + } + else { + obj->mtype.phys_info.rotthrust.x = Controls.pitch_time; + obj->mtype.phys_info.rotthrust.y = Controls.heading_time; + obj->mtype.phys_info.rotthrust.z = Controls.bank_time; + } + +// mprintf( (0, "Rot thrust = %.3f,%.3f,%.3f\n", f2fl(obj->mtype.phys_info.rotthrust.x),f2fl(obj->mtype.phys_info.rotthrust.y), f2fl(obj->mtype.phys_info.rotthrust.z) )); + + forward_thrust_time = Controls.forward_thrust_time; + + if (Players[Player_num].flags & PLAYER_FLAGS_AFTERBURNER) + { + if (Controls.afterburner_state) { //player has key down + //if (forward_thrust_time >= 0) { //..and isn't moving backward + { + fix afterburner_scale; + int old_count,new_count; + + //add in value from 0..1 + afterburner_scale = f1_0 + min(f1_0/2,Afterburner_charge) * 2; + + forward_thrust_time = fixmul(FrameTime,afterburner_scale); //based on full thrust + + old_count = (Afterburner_charge / (DROP_DELTA_TIME/AFTERBURNER_USE_SECS)); + + Afterburner_charge -= FrameTime/AFTERBURNER_USE_SECS; + + if (Afterburner_charge < 0) + Afterburner_charge = 0; + + new_count = (Afterburner_charge / (DROP_DELTA_TIME/AFTERBURNER_USE_SECS)); + + if (old_count != new_count) + Drop_afterburner_blob_flag = 1; //drop blob (after physics called) + } + } + else { + fix cur_energy,charge_up; + + //charge up to full + charge_up = min(FrameTime/8,f1_0 - Afterburner_charge); //recharge over 8 seconds + + cur_energy = max(Players[Player_num].energy-i2f(10),0); //don't drop below 10 + + //maybe limit charge up by energy + charge_up = min(charge_up,cur_energy/10); + + Afterburner_charge += charge_up; + + Players[Player_num].energy -= charge_up * 100 / 10; //full charge uses 10% of energy + } + } + + // Set object's thrust vector for forward/backward + vm_vec_copy_scale(&obj->mtype.phys_info.thrust,&obj->orient.fvec, forward_thrust_time ); + + // slide left/right + vm_vec_scale_add2(&obj->mtype.phys_info.thrust,&obj->orient.rvec, Controls.sideways_thrust_time ); + + // slide up/down + vm_vec_scale_add2(&obj->mtype.phys_info.thrust,&obj->orient.uvec, Controls.vertical_thrust_time ); + + if (obj->mtype.phys_info.flags & PF_WIGGLE) { + fix swiggle; + fix_fastsincos(GameTime, &swiggle, NULL); + vm_vec_scale_add2(&obj->mtype.phys_info.velocity,&obj->orient.uvec,fixmul(swiggle,Player_ship->wiggle)); + } + + // As of now, obj->mtype.phys_info.thrust & obj->mtype.phys_info.rotthrust are + // in units of time... In other words, if thrust==FrameTime, that + // means that the user was holding down the Max_thrust key for the + // whole frame. So we just scale them up by the max, and divide by + // FrameTime to make them independant of framerate + + // Prevent divide overflows on high frame rates. + // In a signed divide, you get an overflow if num >= div<<15 + { + fix ft = FrameTime; + + // Note, you must check for ft < F1_0/2, else you can get an overflow on the << 15. + if ((ft < F1_0/2) && (ft << 15 <= Player_ship->max_thrust)) { + mprintf((0, "Preventing divide overflow in controls.c for Max_thrust!\n")); + ft = (Player_ship->max_thrust >> 15) + 1; + } + + vm_vec_scale( &obj->mtype.phys_info.thrust, fixdiv(Player_ship->max_thrust,ft) ); + + if ((ft < F1_0/2) && (ft << 15 <= Player_ship->max_rotthrust)) { + mprintf((0, "Preventing divide overflow in controls.c for max_rotthrust!\n")); + ft = (Player_ship->max_thrust >> 15) + 1; + } + + vm_vec_scale( &obj->mtype.phys_info.rotthrust, fixdiv(Player_ship->max_rotthrust,ft) ); + } + +} diff --git a/main/controls.h b/main/controls.h new file mode 100644 index 00000000..fe3a8ae9 --- /dev/null +++ b/main/controls.h @@ -0,0 +1,28 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + + +#ifndef _CONTROLS_H +#define _CONTROLS_H + +extern int Cyberman_installed; //SWIFT device present + +void read_flying_controls( object * obj ); + +extern ubyte Controls_stopped; +extern ubyte Controls_always_move; + +extern fix Afterburner_charge; + +#endif diff --git a/main/credits.c b/main/credits.c new file mode 100644 index 00000000..a9a12c13 --- /dev/null +++ b/main/credits.c @@ -0,0 +1,511 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + +#ifdef RCS +static char rcsid[] = "$Id: credits.c,v 1.1.1.1 2001-01-19 03:30:04 bradleyb Exp $"; +#endif + +#ifdef WINDOWS +#include "desw.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include "pa_enabl.h" //$$POLY_ACC +#include "error.h" +#include "pstypes.h" +#include "gr.h" +#include "mono.h" +#include "key.h" +#include "palette.h" +#include "game.h" +#include "gamepal.h" +#include "timer.h" + +#include "newmenu.h" +#include "gamefont.h" +#include "network.h" +#include "iff.h" +#include "pcx.h" +#include "u_mem.h" +#include "mouse.h" +#include "joy.h" +#include "screens.h" +#include "digi.h" + +#include "cfile.h" +#include "compbit.h" +#include "songs.h" +#include "menu.h" // for MenuHires + +#if defined(POLY_ACC) +#include "poly_acc.h" +#endif + +#define ROW_SPACING (MenuHires?26:11) +#define NUM_LINES_HIRES 21 +#define NUM_LINES (MenuHires?NUM_LINES_HIRES:20) + +ubyte fade_values[200] = { 1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,8,9,9,10,10, +11,11,12,12,12,13,13,14,14,15,15,15,16,16,17,17,17,18,18,19,19,19,20,20, +20,21,21,22,22,22,23,23,23,24,24,24,24,25,25,25,26,26,26,26,27,27,27,27, +28,28,28,28,28,29,29,29,29,29,29,30,30,30,30,30,30,30,30,30,31,31,31,31, +31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,30,30,30,30,30, +30,30,30,30,29,29,29,29,29,29,28,28,28,28,28,27,27,27,27,26,26,26,26,25, +25,25,24,24,24,24,23,23,23,22,22,22,21,21,20,20,20,19,19,19,18,18,17,17, +17,16,16,15,15,15,14,14,13,13,12,12,12,11,11,10,10,9,9,8,8,8,7,7,6,6,5, +5,4,4,3,3,2,2,1 }; + +ubyte fade_values_hires[480] = { 1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5,5,5, +5,5,5,6,6,6,6,6,7,7,7,7,7,8,8,8,8,8,9,9,9,9,9,10,10,10,10,10,10,11,11,11,11,11,12,12,12,12,12,12, +13,13,13,13,13,14,14,14,14,14,14,15,15,15,15,15,15,16,16,16,16,16,17,17,17,17,17,17,18,18, +18,18,18,18,18,19,19,19,19,19,19,20,20,20,20,20,20,20,21,21,21,21,21,21,22,22,22,22,22,22, +22,22,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,26,26,26,26, +26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29, +29,29,29,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, +30,30,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, +31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,30,30,30, +30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,29,29,29,29,29,29,29,29,29,29,29,29, +29,29,28,28,28,28,28,28,28,28,28,28,28,28,27,27,27,27,27,27,27,27,27,27,26,26,26,26,26,26, +26,26,26,25,25,25,25,25,25,25,25,25,24,24,24,24,24,24,24,24,23,23,23,23,23,23,23,22,22,22, +22,22,22,22,22,21,21,21,21,21,21,20,20,20,20,20,20,20,19,19,19,19,19,19,18,18,18,18,18,18, +18,17,17,17,17,17,17,16,16,16,16,16,15,15,15,15,15,15,14,14,14,14,14,14,13,13,13,13,13,12, +12,12,12,12,12,11,11,11,11,11,10,10,10,10,10,10,9,9,9,9,9,8,8,8,8,8,7,7,7,7,7,6,6,6,6,6,5,5,5,5, +5,5,4,4,4,4,4,3,3,3,3,3,2,2,2,2,2,1,1}; + +extern ubyte *gr_bitblt_fade_table; + +grs_font * header_font; +grs_font * title_font; +grs_font * names_font; + +#ifdef SHAREWARE +#define ALLOWED_CHAR 'S' +#else +#define ALLOWED_CHAR 'R' +#endif + +#ifdef RELEASE +#define CREDITS_BACKGROUND_FILENAME (MenuHires?"\x01starsb.pcx":"\x01stars.pcx") //only read from hog file +#else +#define CREDITS_BACKGROUND_FILENAME (MenuHires?"starsb.pcx":"stars.pcx") +#endif + +typedef struct box { + int left, top, width, height; +} box; + +#ifdef MACINTOSH +#define CREDITS_FILE "mcredits.tex" +#else +#ifdef D2_OEM +#define CREDITS_FILE "ocredits.tex" +#else +#define CREDITS_FILE "credits.tex" +#endif +#endif + +//if filename passed is NULL, show normal credits +void credits_show(char *credits_filename) +{ + int i, j, l, done; + CFILE * file; + char buffer[NUM_LINES_HIRES][80]; + grs_bitmap backdrop; + ubyte backdrop_palette[768]; + int pcx_error; + int buffer_line = 0; + fix last_time; +// fix time_delay = 4180; // ~ F1_0 / 12.9 +// fix time_delay = 1784; + fix time_delay = 2800; + int first_line_offset,extra_inc=0; + int have_bin_file = 0; + char * tempp; + char filename[32]; + +WIN(int credinit = 0;) + + box dirty_box[NUM_LINES_HIRES]; + grs_canvas *CreditsOffscreenBuf=NULL; + + WINDOS( + dd_grs_canvas *save_canv, + grs_canvas *save_canv + ); + + WINDOS( + save_canv = dd_grd_curcanv, + save_canv = grd_curcanv + ); + + // Clear out all tex buffer lines. + for (i=0; icv_bitmap->bm_type. + + pcx_error = pcx_read_bitmap(CREDITS_BACKGROUND_FILENAME,&backdrop, BM_LINEAR,backdrop_palette); + if (pcx_error != PCX_ERROR_NONE) { + cfclose(file); + return; + } + + songs_play_song( SONG_CREDITS, 1 ); + + gr_remap_bitmap_good( &backdrop,backdrop_palette, -1, -1 ); + +WINDOS( + dd_gr_set_current_canvas(NULL), + gr_set_current_canvas(NULL) +); +WIN(DDGRLOCK(dd_grd_curcanv)); + gr_bitmap(0,0,&backdrop); +WIN(DDGRUNLOCK(dd_grd_curcanv)); + gr_update(); + gr_palette_fade_in( gr_palette, 32, 0 ); + +// Create a new offscreen buffer for the credits screen +//MWA Let's be a little smarter about this and check the VR_offscreen buffer +//MWA for size to determine if we can use that buffer. If the game size +//MWA matches what we need, then lets save memory. + +#ifndef PA_3DFX_VOODOO +#ifndef WINDOWS + if (MenuHires && VR_offscreen_buffer->cv_w == 640) { + CreditsOffscreenBuf = VR_offscreen_buffer; + } + else if (MenuHires) { + CreditsOffscreenBuf = gr_create_canvas(640,480); + } + else { + CreditsOffscreenBuf = gr_create_canvas(320,200); + } +#else + CreditsOffscreenBuf = gr_create_canvas(640,480); +#endif +#else + CreditsOffscreenBuf = gr_create_canvas(640,480); +#endif + + if (!CreditsOffscreenBuf) + Error("Not enough memory to allocate Credits Buffer."); + + //gr_clear_canvas(BM_XRGB(0,0,0)); + key_flush(); + +#ifdef WINDOWS + if (!credinit) +#endif + { + last_time = timer_get_fixed_seconds(); + done = 0; + first_line_offset = 0; + } + + WIN(credinit = 1); + + while( 1 ) { + int k; + + do { + buffer_line = (buffer_line+1) % NUM_LINES; +get_line:; + if (cfgets( buffer[buffer_line], 80, file )) { + char *p; + if (have_bin_file) { // is this a binary tbl file + for (i = 0; i < strlen(buffer[buffer_line]) - 1; i++) { + encode_rotate_left(&(buffer[buffer_line][i])); + buffer[buffer_line][i] ^= BITMAP_TBL_XOR; + encode_rotate_left(&(buffer[buffer_line][i])); + } + } + p = buffer[buffer_line]; + if (p[0] == ';') + goto get_line; + + if (p[0] == '%') + { + if (p[1] == ALLOWED_CHAR) + strcpy(p,p+2); + else + goto get_line; + } + + p = strchr(&buffer[buffer_line][0],'\n'); + if (p) *p = '\0'; + } else { + //fseek( file, 0, SEEK_SET); + buffer[buffer_line][0] = 0; + done++; + } + } while (extra_inc--); + extra_inc = 0; + +NO_DFX (for (i=0; icv_font = header_font; + s++; + } else if ( s[0] == '*' ) { + grd_curcanv->cv_font = title_font; + s++; + } else + grd_curcanv->cv_font = names_font; + + gr_bitblt_fade_table = (MenuHires?fade_values_hires:fade_values); + + tempp = strchr( s, '\t' ); + if ( tempp ) { + // Wacky Credits thing + int w, h, aw, w2, x1, x2; + + *tempp = 0; + gr_get_string_size( s, &w, &h, &aw ); + x1 = ((MenuHires?320:160)-w)/2; + gr_printf( x1 , y, s ); + gr_get_string_size( &tempp[1], &w2, &h, &aw ); + x2 = (MenuHires?320:160)+(((MenuHires?320:160)-w2)/2); + gr_printf( x2, y, &tempp[1] ); + + dirty_box[j].left = ((MenuHires?320:160)-w)/2; + dirty_box[j].top = y; + dirty_box[j].width =(x2+w2)-x1; + dirty_box[j].height = h; + + *tempp = '\t'; + + } else { + // Wacky Fast Credits thing + int w, h, aw; + + gr_get_string_size( s, &w, &h, &aw); + dirty_box[j].width = w; + dirty_box[j].height = h; + dirty_box[j].top = y; + dirty_box[j].left = ((MenuHires?640:320) - w) / 2; + + gr_printf( 0x8000, y, s ); + } + gr_bitblt_fade_table = NULL; + if (buffer[l][0] == '!') + y += ROW_SPACING/2; + else + y += ROW_SPACING; + } + + { // Wacky Fast Credits Thing + box *new_box; + grs_bitmap *tempbmp; + + for (j=0; jcv_bitmap); + + WIN(DDGRSCREENLOCK); +#if defined(POLY_ACC) + if(new_box->width != 0) +#endif + gr_bm_bitblt( new_box->width + 1, new_box->height +4, + new_box->left, new_box->top, new_box->left, new_box->top, + tempbmp, &(grd_curscreen->sc_canvas.cv_bitmap) ); + WIN(DDGRSCREENUNLOCK); + } + +#if defined(POLY_ACC) + pa_flush(); +#endif + +#if !defined(POLY_ACC) || defined(MACINTOSH) + MAC( if(!PAEnabled) ) // POLY_ACC always on for the macintosh + for (j=0; jcv_bitmap); + + gr_bm_bitblt( new_box->width + ,new_box->height+2 + ,new_box->left + ,new_box->top + ,new_box->left + ,new_box->top + ,&backdrop + ,tempbmp ); + } + +#endif + gr_update(); + + } + +// Wacky Fast Credits thing doesn't need this (it's done above) +//@@ WINDOS( +//@@ dd_gr_blt_notrans(CreditsOffscreenBuf, 0,0,0,0, dd_grd_screencanv, 0,0,0,0), +//@@ gr_bm_ubitblt(grd_curcanv->cv_w, grd_curcanv->cv_h, 0, 0, 0, 0, &(CreditsOffscreenBuf->cv_bitmap), &(grd_curscreen->sc_canvas.cv_bitmap) ); +//@@ ); + +// mprintf( ( 0, "Fr = %d", (timer_get_fixed_seconds() - last_time) )); + while( timer_get_fixed_seconds() < last_time+time_delay ); + last_time = timer_get_fixed_seconds(); + + #ifdef WINDOWS + { + MSG msg; + + DoMessageStuff(&msg); + + if (_RedrawScreen) { + _RedrawScreen = FALSE; + + gr_close_font(header_font); + gr_close_font(title_font); + gr_close_font(names_font); + + d_free(backdrop.bm_data); + gr_free_canvas(CreditsOffscreenBuf); + + goto CreditsPaint; + } + + DDGRRESTORE; + } + #endif + + //see if redbook song needs to be restarted + songs_check_redbook_repeat(); + + k = key_inkey(); + + #ifndef NDEBUG + if (k == KEY_BACKSP) { + Int3(); + k=0; + } + #endif + +// { +// fix ot = time_delay; +// time_delay += (keyd_pressed[KEY_X] - keyd_pressed[KEY_Z])*100; +// if (ot!=time_delay) { +// mprintf( (0, "[%x] ", time_delay )); +// } +// } + + if (k == KEY_PRINT_SCREEN) { + save_screen_shot(0); + k = 0; + } + + if ((k>0)||(done>NUM_LINES)) { + gr_close_font(header_font); + gr_close_font(title_font); + gr_close_font(names_font); + gr_palette_fade_out( gr_palette, 32, 0 ); + gr_use_palette_table( DEFAULT_PALETTE ); + d_free(backdrop.bm_data); + cfclose(file); + WINDOS( + dd_gr_set_current_canvas(save_canv), + gr_set_current_canvas(save_canv) + ); + songs_play_song( SONG_TITLE, 1 ); + + #ifdef WINDOWS + gr_free_canvas(CreditsOffscreenBuf); + #else + if (CreditsOffscreenBuf != VR_offscreen_buffer) + gr_free_canvas(CreditsOffscreenBuf); + #endif + + WIN(DEFINE_SCREEN(Menu_pcx_name)); + + return; + } + } + + if (buffer[(buffer_line + 1 ) % NUM_LINES][0] == '!') { + first_line_offset -= ROW_SPACING-ROW_SPACING/2; + if (first_line_offset <= -ROW_SPACING) { + first_line_offset += ROW_SPACING; + extra_inc++; + } + } + } + +} diff --git a/main/credits.h b/main/credits.h new file mode 100644 index 00000000..f68dfae0 --- /dev/null +++ b/main/credits.h @@ -0,0 +1,22 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + + +#ifndef _CREDITS_H +#define _CREDITS_H + +//if filename passed is NULL, show normal credits +void credits_show(char *credits_filename); + +#endif diff --git a/main/crypt.c b/main/crypt.c new file mode 100644 index 00000000..0a94416d --- /dev/null +++ b/main/crypt.c @@ -0,0 +1,56 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifdef RCS +char crypt_rcsid[] = "$Id: crypt.c,v 1.1.1.1 2001-01-19 03:30:01 bradleyb Exp $"; +#endif + +#include +#include +#include +#include + +#include "inferno.h" + +char *jcrypt (char *plainstring) + { + int i,t,len; + static char cryptstring[20]; + + len=strlen (plainstring); + if (len>8) + len=8; + + for (i=0;i + +#include "win\dd.h" +#include "win\winapp.h" +#include "pstypes.h" +#include "fix.h" +#include "gr.h" + +#undef DEFAULT_PALETTE + + +#define WINAPP_NAME "Descent II" + +typedef struct GAME_CONTEXT { + BOOL paused; + BOOL active; +}; + +typedef struct SCREEN_CONTEXT { + char *bkg_filename; +} SCREEN_CONTEXT; + + +typedef struct PALETTE { + WORD version; + WORD num_entries; + PALETTEENTRY entries[256]; +} PALETTE; + +typedef struct RGBBITMAPINFO { + BITMAPINFOHEADER bmiHeader; + RGBQUAD rgb[256]; +} RGBBITMAPINFO; + + + +// Other Structures + +#define MSG_QUIT 0 +#define MSG_SHUTDOWN 1 +#define MSG_NORMAL 2 + + +typedef struct WinJoystickDesc { + char title[32]; + char cal_ztitle[16]; + char cal_rtitle[16]; + char cal_utitle[16]; + char cal_vtitle[16]; + char cal_zmsg[6][16]; + char cal_rmsg[6][16]; + char cal_umsg[6][16]; + char cal_vmsg[6][16]; +} WinJoystickDesc; + + +// Globals + +extern HWND _hAppWnd; // Descent Window +extern HINSTANCE _hAppInstance; +extern int _DDraw; // Direct X Implementation +extern BOOL _AppActive; +extern BOOL SOS_DLLInit; +extern BOOL _RedrawScreen; +extern SCREEN_CONTEXT _SCRContext; + + +extern dd_grs_canvas *dd_VR_offscreen_buffer; +extern dd_grs_canvas dd_VR_screen_pages[2]; +extern dd_grs_canvas dd_VR_render_buffer[2]; +extern dd_grs_canvas dd_VR_render_sub_buffer[2]; + + + +// WinG Stuff + +extern HPALETTE _hAppPalette; // Application Palette + + +// Other Globals + +extern RECT ViewportRect; // Viewport rect for window +extern char *_OffscreenCanvasBits; // Pointer to DIB Bits. +extern fix WinFrameTime; // Time per frame +extern int Platform_system; // Tells us the platform + + +// Functions + +extern void WinDelay(int msecs); + +// misc functions +extern void WErrorPrint(char *msg); +extern dd_grs_canvas *get_current_game_screen(); +extern BOOL SOSInit(); +extern void SOSUnInit(); + + +#define MOUSE_DEFAULT_CURSOR 1 +#define MOUSE_WAIT_CURSOR 2 + +extern void LoadCursorWin(int cursor); +extern void ShowCursorW(); +extern void HideCursorW(); + + +// Macros +#define CanvasWidth(C) ((C).bmiHeader.biWidth) +#define CanvasHeight(C) (((C).bmiHeader.biHeight > 0) ? \ + (C).bmiHeader.biHeight : -(C).bmiHeader.biHeight) + +#define DebugMessageBox(c) (MessageBox(NULL,c,"Message",MB_OK)) + +#define DEFINE_SCREEN(fn) (_SCRContext.bkg_filename = fn) + +#define WINNT_PLATFORM 1 +#define WIN95_PLATFORM 0 + + +#endif + + +#endif diff --git a/main/digi.h b/main/digi.h new file mode 100644 index 00000000..9c97a167 --- /dev/null +++ b/main/digi.h @@ -0,0 +1,230 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/main/digi.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: bradleyb $ + * $Date: 2001-01-19 03:29:59 $ + * + * Include file for sound hardware. + * + * $Log: not supported by cvs2svn $ + * Revision 1.2 1999/11/15 10:43:15 sekmu + * added freq/br to digi_sound struct for alt sounds + * + * Revision 1.1.1.1 1999/06/14 22:12:14 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:28:40 john + * New version 2.0, which has no anonymous unions, builds with + * Watcom 10.0, and doesn't require parsing BITMAPS.TBL. + * + * Revision 1.29 1995/02/11 12:42:00 john + * Added new song method, with FM bank switching.. + * + * Revision 1.28 1995/02/03 17:08:26 john + * Changed sound stuff to allow low memory usage. + * Also, changed so that Sounds isn't an array of digi_sounds, it + * is a ubyte pointing into GameSounds, this way the digi.c code that + * locks sounds won't accidentally unlock a sound that is already playing, but + * since it's Sounds[soundno] is different, it would erroneously be unlocked. + * + * Revision 1.27 1995/02/01 22:20:31 john + * Added digi_is_sound_playing. + * + * Revision 1.26 1994/12/20 18:03:51 john + * Added loop midi flag. + * + * Revision 1.25 1994/12/13 00:46:14 john + * Split digi and midi volume into 2 seperate functions. + * + * Revision 1.24 1994/12/10 20:34:53 john + * Added digi_kill_sound_linked_to_object. + * + * Revision 1.23 1994/12/10 15:59:39 mike + * Fixed bug. + * + * Revision 1.22 1994/12/10 15:44:35 john + * Added max_distance passing for sound objects. + * + * Revision 1.21 1994/12/05 12:17:40 john + * Added code that locks/unlocks digital sounds on demand. + * + * Revision 1.20 1994/11/28 18:34:57 john + * Made the digi_max_channels cut of an old sound instead of + * not playing a new sound. + * + * Revision 1.19 1994/11/14 17:53:56 allender + * made some digi variables extern + * + * Revision 1.18 1994/10/28 14:42:58 john + * Added sound volumes to all sound calls. + * + * Revision 1.17 1994/10/11 15:25:37 john + * Added new function to play a sound once... + * + * Revision 1.16 1994/10/03 20:51:44 john + * Started added pause sound function; for the network I changed to + * packet structure a bit; never tested, though. + * + * + * Revision 1.15 1994/10/03 13:09:43 john + * Added Pause function, but never tested it yet. + * + * Revision 1.14 1994/09/30 10:09:24 john + * Changed sound stuff... made it so the reseting card doesn't hang, + * made volume change only if sound is installed. + * + * Revision 1.13 1994/09/29 21:13:43 john + * Added Master volumes for digi and midi. Also took out panning, + * because it doesn't work with MasterVolume stuff. + * + * Revision 1.12 1994/09/29 12:42:34 john + * Added sidenum to keep track of sound pos. Made sound functions + * not do anything if nosound. Made sounds_init delete currently + * playing sounds. + * + * Revision 1.11 1994/09/29 12:23:42 john + * Added digi_kill_sound_linked_to_segment function. + * + * Revision 1.10 1994/09/29 11:59:04 john + * Added digi_kill_sound + * + * Revision 1.9 1994/09/29 10:37:38 john + * Added sound objects that dynamicaly change volume,pan. + * + * Revision 1.8 1994/09/28 16:18:37 john + * Added capability to play midi song. + * + * Revision 1.7 1994/06/17 18:01:41 john + * A bunch of new stuff by John + * + * Revision 1.6 1994/06/15 19:00:58 john + * Added the capability to make 3d sounds play just once for the + * laser hit wall effects. + * + * Revision 1.5 1994/06/07 10:54:30 john + * Made key S reinit the sound system. + * + * Revision 1.4 1994/05/09 21:11:39 john + * Sound changes; pass index instead of pointer to digi routines. + * Made laser sound cut off the last laser sound. + * + * Revision 1.3 1994/04/27 11:44:25 john + * First version of sound! Yay! + * + * Revision 1.2 1994/04/20 21:58:50 john + * First version of sound stuff... hopefully everything + * is commented out because it hangs.. + * + * Revision 1.1 1994/04/15 14:25:02 john + * Initial revision + * + * + */ + + + +#ifndef _DIGI_H +#define _DIGI_H + +#include "pstypes.h" +#include "vecmat.h" + +/* +#ifdef __DJGPP__ +#define ALLEGRO +#endif +*/ + +#ifdef ALLEGRO +#include "allg_snd.h" +typedef SAMPLE digi_sound; +#else +typedef struct digi_sound { + int bits; + int freq; + int length; + ubyte * data; +} digi_sound; +#endif + +#define SAMPLE_RATE_11K 11025 +#define SAMPLE_RATE_22K 22050 + + + +#ifdef __MSDOS__ +extern int digi_driver_board; +extern int digi_driver_port; +extern int digi_driver_irq; +extern int digi_driver_dma; +extern int digi_midi_type; +extern int digi_midi_port; +#endif + +extern int digi_sample_rate; + +extern int digi_get_settings(); +extern int digi_init(); +extern void digi_reset(); +extern void digi_close(); + +int digi_xlat_sound(int sound); +// Volume is max at F1_0. +extern void digi_play_sample( int sndnum, fix max_volume ); +extern void digi_play_sample_once( int sndnum, fix max_volume ); +extern int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume ); +extern int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume ); +// Same as above, but you pass the max distance sound can be heard. The old way uses f1_0*256 for max_distance. +extern int digi_link_sound_to_object2( int soundnum, short objnum, int forever, fix max_volume, fix max_distance ); +extern int digi_link_sound_to_pos2( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance ); + +extern int digi_link_sound_to_object3( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance, int loop_start, int loop_end ); + +extern void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ); + +extern void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ); // Volume from 0-0x7fff + +extern void digi_init_sounds(); +extern void digi_sync_sounds(); +extern void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum ); +extern void digi_kill_sound_linked_to_object( int objnum ); + +extern void digi_set_midi_volume( int mvolume ); +extern void digi_set_digi_volume( int dvolume ); +extern void digi_set_volume( int dvolume, int mvolume ); + +extern int digi_is_sound_playing(int soundno); + +extern void digi_pause_all(); +extern void digi_resume_all(); +extern void digi_stop_all(); + +extern void digi_set_max_channels(int n); +extern int digi_get_max_channels(); + +extern int digi_lomem; + +extern void digi_pause_digi_sounds(); +extern void digi_resume_digi_sounds(); + +int digi_start_sound(int soundnum, fix volume, fix pan, int unknown1, int unknown2, int unknown3, int unknown4); +void digi_stop_sound(int channel); +void digi_start_sound_queued( short soundnum, fix volume ); +void digi_play_sample_looping( int soundno, fix max_volume,int loop_start, int loop_end ); +void digi_stop_looping_sound(void); +void digi_change_looping_volume(fix volume); + +#endif + diff --git a/main/dumpmine.c b/main/dumpmine.c new file mode 100644 index 00000000..7d89be52 --- /dev/null +++ b/main/dumpmine.c @@ -0,0 +1,1155 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + +#ifdef RCS +static char rcsid[] = "$Id: dumpmine.c,v 1.1.1.1 2001-01-19 03:30:00 bradleyb Exp $"; +#endif + +#include +#include +#include +#include +#include + +#include "pstypes.h" +#include "mono.h" +#include "key.h" +#include "gr.h" +#include "palette.h" + +#include "inferno.h" +#ifdef EDITOR +#include "editor\editor.h" +#endif +#include "error.h" +#include "object.h" +#include "wall.h" +#include "gamemine.h" +#include "robot.h" +#include "player.h" +#include "newmenu.h" +#include "textures.h" + +#include "bm.h" +#include "menu.h" +#include "switch.h" +#include "fuelcen.h" +#include "powerup.h" +#include "gameseq.h" +#include "polyobj.h" +#include "gamesave.h" + + +#ifdef EDITOR + +extern ubyte bogus_data[64*64]; +extern grs_bitmap bogus_bitmap; + +// -------------------------------------------------------------------------------- +char *object_types(int objnum) +{ + int type = Objects[objnum].type; + + Assert((type >= 0) && (type < MAX_OBJECT_TYPES)); + return &Object_type_names[type]; +} + +// -------------------------------------------------------------------------------- +char *object_ids(int objnum) +{ + int type = Objects[objnum].type; + int id = Objects[objnum].id; + + switch (type) { + case OBJ_ROBOT: + return &Robot_names[id]; + break; + case OBJ_POWERUP: + return &Powerup_names[id]; + break; + } + + return NULL; +} + +void err_printf(FILE *my_file, char * format, ... ) +{ + va_list args; + char message[256]; + + va_start(args, format ); + vsprintf(message,format,args); + va_end(args); + + mprintf((1, "%s", message)); + fprintf(my_file, "%s", message); + Errors_in_mine++; +} + +void warning_printf(FILE *my_file, char * format, ... ) +{ + va_list args; + char message[256]; + + va_start(args, format ); + vsprintf(message,format,args); + va_end(args); + + mprintf((0, "%s", message)); + fprintf(my_file, "%s", message); +} + +// ----------------------------------------------------------------------------------------------------------- +void write_exit_text(FILE *my_file) +{ + int i, j, count; + + fprintf(my_file, "-----------------------------------------------------------------------------\n"); + fprintf(my_file, "Exit stuff\n"); + + // ---------- Find exit triggers ---------- + count=0; + for (i=0; i 1) + err_printf(my_file, "Error: Trigger %i is bound to %i walls.\n", i, count2); + + } + + if (count == 0) + err_printf(my_file, "Error: No exit trigger in this mine.\n"); + else if (count != 1) + err_printf(my_file, "Error: More than one exit trigger in this mine.\n"); + else + fprintf(my_file, "\n"); + + // ---------- Find exit doors ---------- + count = 0; + for (i=0; i<=Highest_segment_index; i++) + for (j=0; j 1) + warning_printf(my_file, "Warning: %i doors are keyed to the blue key.\n", blue_count); + + if (red_count > 1) + warning_printf(my_file, "Warning: %i doors are keyed to the red key.\n", red_count); + + if (gold_count > 1) + warning_printf(my_file, "Warning: %i doors are keyed to the gold key.\n", gold_count); + + red_count2 = 0; + blue_count2 = 0; + gold_count2 = 0; + + for (i=0; i<=Highest_object_index; i++) { + if (Objects[i].type == OBJ_POWERUP) + if (Objects[i].id == POW_KEY_BLUE) { + fprintf(my_file, "The BLUE key is object %i in segment %i\n", i, Objects[i].segnum); + blue_count2++; + } + if (Objects[i].type == OBJ_POWERUP) + if (Objects[i].id == POW_KEY_RED) { + fprintf(my_file, "The RED key is object %i in segment %i\n", i, Objects[i].segnum); + red_count2++; + } + if (Objects[i].type == OBJ_POWERUP) + if (Objects[i].id == POW_KEY_GOLD) { + fprintf(my_file, "The GOLD key is object %i in segment %i\n", i, Objects[i].segnum); + gold_count2++; + } + + if (Objects[i].contains_count) { + if (Objects[i].contains_type == OBJ_POWERUP) { + switch (Objects[i].contains_id) { + case POW_KEY_BLUE: + fprintf(my_file, "The BLUE key is contained in object %i (a %s %s) in segment %i\n", i, Object_type_names[Objects[i].type], Robot_names[Objects[i].id], Objects[i].segnum); + blue_count2 += Objects[i].contains_count; + break; + case POW_KEY_GOLD: + fprintf(my_file, "The GOLD key is contained in object %i (a %s %s) in segment %i\n", i, Object_type_names[Objects[i].type], Robot_names[Objects[i].id], Objects[i].segnum); + gold_count2 += Objects[i].contains_count; + break; + case POW_KEY_RED: + fprintf(my_file, "The RED key is contained in object %i (a %s %s) in segment %i\n", i, Object_type_names[Objects[i].type], Robot_names[Objects[i].id], Objects[i].segnum); + red_count2 += Objects[i].contains_count; + break; + default: + break; + } + } + } + } + + if (blue_count) + if (blue_count2 == 0) + err_printf(my_file, "Error: There is a door keyed to the blue key, but no blue key!\n"); + + if (red_count) + if (red_count2 == 0) + err_printf(my_file, "Error: There is a door keyed to the red key, but no red key!\n"); + + if (gold_count) + if (gold_count2 == 0) + err_printf(my_file, "Error: There is a door keyed to the gold key, but no gold key!\n"); + + if (blue_count2 > 1) + err_printf(my_file, "Error: There are %i blue keys!\n", blue_count2); + + if (red_count2 > 1) + err_printf(my_file, "Error: There are %i red keys!\n", red_count2); + + if (gold_count2 > 1) + err_printf(my_file, "Error: There are %i gold keys!\n", gold_count2); +} + +// ------------------------------------------------------------------------------------------ +void write_control_center_text(FILE *my_file) +{ + int i, count, objnum, count2; + + fprintf(my_file, "-----------------------------------------------------------------------------\n"); + fprintf(my_file, "Control Center stuff:\n"); + + count = 0; + for (i=0; i<=Highest_segment_index; i++) + if (Segment2s[i].special == SEGMENT_IS_CONTROLCEN) { + count++; + fprintf(my_file, "Segment %3i is a control center.\n", i); + objnum = Segments[i].objects; + count2 = 0; + while (objnum != -1) { + if (Objects[objnum].type == OBJ_CNTRLCEN) + count2++; + objnum = Objects[objnum].next; + } + if (count2 == 0) + fprintf(my_file, "No control center object in control center segment.\n"); + else if (count2 != 1) + fprintf(my_file, "%i control center objects in control center segment.\n", count2); + } + + if (count == 0) + err_printf(my_file, "Error: No control center in this mine.\n"); + else if (count != 1) + err_printf(my_file, "Error: More than one control center in this mine.\n"); +} + +// ------------------------------------------------------------------------------------------ +void write_fuelcen_text(FILE *my_file) +{ + int i; + + fprintf(my_file, "-----------------------------------------------------------------------------\n"); + fprintf(my_file, "Fuel Center stuff: (Note: This means fuel, repair, materialize, control centers!)\n"); + + for (i=0; i 30) { + fprintf(my_file, "\nAborted after %i links\n", depth); + break; + } + } + } + fprintf(my_file, "\n"); + } +} + +// ------------------------------------------------------------------------------------------ +// This routine is bogus. It assumes that all centers are matcens, which is not true. The setting of segnum is bogus. +void write_matcen_text(FILE *my_file) +{ + int i, j, k; + + fprintf(my_file, "-----------------------------------------------------------------------------\n"); + fprintf(my_file, "Materialization centers:\n"); + for (i=0; i> 16, Walls[i].trigger, Walls[i].clip_num, Walls[i].keys, Walls[i].state); + + if (Walls[i].trigger >= Num_triggers) + fprintf(my_file, "Wall %03d points to invalid trigger %d\n",i,Walls[i].trigger); + + segnum = Walls[i].segnum; + sidenum = Walls[i].sidenum; + + if (Segments[segnum].sides[sidenum].wall_num != i) + err_printf(my_file, "Error: Wall %i points at segment %i, side %i, but that segment doesn't point back (it's wall_num = %i)\n", i, segnum, sidenum, Segments[segnum].sides[sidenum].wall_num); + } + + for (i=0; isides[j]; + if (sidep->wall_num != -1) + if (wall_flags[sidep->wall_num]) + err_printf(my_file, "Error: Wall %i appears in two or more segments, including segment %i, side %i.\n", sidep->wall_num, i, j); + else + wall_flags[sidep->wall_num] = 1; + } + } + +} + +//typedef struct trigger { +// byte type; +// short flags; +// fix value; +// fix time; +// byte link_num; +// short num_links; +// short seg[MAX_WALLS_PER_LINK]; +// short side[MAX_WALLS_PER_LINK]; +// } trigger; + +// ------------------------------------------------------------------------------------------ +void write_player_text(FILE *my_file) +{ + int i, num_players=0; + + fprintf(my_file, "-----------------------------------------------------------------------------\n"); + fprintf(my_file, "Players:\n"); + for (i=0; i<=Highest_object_index; i++) { + if (Objects[i].type == OBJ_PLAYER) { + num_players++; + fprintf(my_file, "Player %2i is object #%3i in segment #%3i.\n", Objects[i].id, i, Objects[i].segnum); + } + } + + if (num_players != MAX_PLAYERS) + err_printf(my_file, "Error: %i player objects. %i are required.\n", num_players, MAX_PLAYERS); + if (num_players > MAX_MULTI_PLAYERS) + err_printf(my_file, "Error: %i player objects. %i are required.\n", num_players, MAX_PLAYERS); +} + +// ------------------------------------------------------------------------------------------ +void write_trigger_text(FILE *my_file) +{ + int i, j, w; + + fprintf(my_file, "-----------------------------------------------------------------------------\n"); + fprintf(my_file, "Triggers:\n"); + for (i=0; i 4); + + Assert (filename[namelen-4] == '.'); + + strcpy(my_filename, filename); + strcpy( &my_filename[namelen-4], ".txm"); + + // mprintf((0, "Writing text file [%s]\n", my_filename)); + + my_file = fopen( my_filename, "wt" ); + // -- mprintf((1, "Fileno = %i\n", fileno(my_file))); + + if (!my_file) { + char ErrorMessage[200]; + + sprintf( ErrorMessage, "ERROR: Unable to open %s\nErrno = %i", my_file, errno ); + stop_time(); + gr_palette_load(gr_palette); + nm_messagebox( NULL, 1, "Ok", ErrorMessage ); + start_time(); + + return; + } + + dump_used_textures_level(my_file, 0); + say_totals(my_file, Gamesave_current_filename); + + fprintf(my_file, "\nNumber of segments: %4i\n", Highest_segment_index+1); + fprintf(my_file, "Number of objects: %4i\n", Highest_object_index+1); + fprintf(my_file, "Number of walls: %4i\n", Num_walls); + fprintf(my_file, "Number of open doors: %4i\n", Num_open_doors); + fprintf(my_file, "Number of triggers: %4i\n", Num_triggers); + fprintf(my_file, "Number of matcens: %4i\n", Num_robot_centers); + fprintf(my_file, "\n"); + + write_segment_text(my_file); + + write_fuelcen_text(my_file); + + write_matcen_text(my_file); + + write_player_text(my_file); + + write_wall_text(my_file); + + write_trigger_text(my_file); + + write_exit_text(my_file); + + // ---------- Find control center segment ---------- + write_control_center_text(my_file); + + // ---------- Show keyed walls ---------- + write_key_text(my_file); + +{ int r; + r = fclose(my_file); + mprintf((1, "Close value = %i\n", r)); + if (r) + Int3(); +} +} + +// -- // --------------- +// -- // Note: This only works for a loaded level because the objects array must be valid. +// -- void determine_used_textures_robots(int *tmap_buf) +// -- { +// -- int i, objnum; +// -- polymodel *po; +// -- +// -- Assert(N_polygon_models); +// -- +// -- for (objnum=0; objnum <= Highest_object_index; objnum++) { +// -- int model_num; +// -- +// -- if (Objects[objnum].render_type == RT_POLYOBJ) { +// -- model_num = Objects[objnum].rtype.pobj_info.model_num; +// -- +// -- po=&Polygon_models[model_num]; +// -- +// -- for (i=0;in_textures;i++) { +// -- int tli; +// -- +// -- tli = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]]; +// -- Assert((tli>=0) && (tli<= Num_tmaps)); +// -- tmap_buf[tli]++; +// -- } +// -- } +// -- } +// -- +// -- } + +// --05/17/95--// ----------------------------------------------------------------------------- +// --05/17/95--void determine_used_textures_level(int load_level_flag, int shareware_flag, int level_num, int *tmap_buf, int *wall_buf, byte *level_tmap_buf, int max_tmap) +// --05/17/95--{ +// --05/17/95-- int segnum, sidenum; +// --05/17/95-- int i, j; +// --05/17/95-- +// --05/17/95-- for (i=0; isides[sidenum]; +// --05/17/95-- +// --05/17/95-- if (sidep->wall_num != -1) { +// --05/17/95-- int clip_num = Walls[sidep->wall_num].clip_num; +// --05/17/95-- if (clip_num != -1) { +// --05/17/95-- +// --05/17/95-- int num_frames = WallAnims[clip_num].num_frames; +// --05/17/95-- +// --05/17/95-- wall_buf[clip_num] = 1; +// --05/17/95-- +// --05/17/95-- for (j=0; jtmap_num >= 0) +// --05/17/95-- if (sidep->tmap_num < max_tmap) { +// --05/17/95-- tmap_buf[sidep->tmap_num]++; +// --05/17/95-- if (level_tmap_buf[sidep->tmap_num] == -1) +// --05/17/95-- level_tmap_buf[sidep->tmap_num] = level_num + (!shareware_flag) * NUM_SHAREWARE_LEVELS; +// --05/17/95-- } else +// --05/17/95-- Int3(); // Error, bogus texture map. Should not be greater than max_tmap. +// --05/17/95-- +// --05/17/95-- if ((sidep->tmap_num2 & 0x3fff) != 0) +// --05/17/95-- if ((sidep->tmap_num2 & 0x3fff) < max_tmap) { +// --05/17/95-- tmap_buf[sidep->tmap_num2 & 0x3fff]++; +// --05/17/95-- if (level_tmap_buf[sidep->tmap_num2 & 0x3fff] == -1) +// --05/17/95-- level_tmap_buf[sidep->tmap_num2 & 0x3fff] = level_num + (!shareware_flag) * NUM_SHAREWARE_LEVELS; +// --05/17/95-- } else +// --05/17/95-- Int3(); // Error, bogus texture map. Should not be greater than max_tmap. +// --05/17/95-- } +// --05/17/95-- } +// --05/17/95--} + +// Adam: Change NUM_ADAM_LEVELS to the number of levels. +#define NUM_ADAM_LEVELS 30 + +// Adam: Stick the names here. +char *Adam_level_names[NUM_ADAM_LEVELS] = { + "D2LEVA-1.LVL", + "D2LEVA-2.LVL", + "D2LEVA-3.LVL", + "D2LEVA-4.LVL", + "D2LEVA-S.LVL", + + "D2LEVB-1.LVL", + "D2LEVB-2.LVL", + "D2LEVB-3.LVL", + "D2LEVB-4.LVL", + "D2LEVB-S.LVL", + + "D2LEVC-1.LVL", + "D2LEVC-2.LVL", + "D2LEVC-3.LVL", + "D2LEVC-4.LVL", + "D2LEVC-S.LVL", + + "D2LEVD-1.LVL", + "D2LEVD-2.LVL", + "D2LEVD-3.LVL", + "D2LEVD-4.LVL", + "D2LEVD-S.LVL", + + "D2LEVE-1.LVL", + "D2LEVE-2.LVL", + "D2LEVE-3.LVL", + "D2LEVE-4.LVL", + "D2LEVE-S.LVL", + + "D2LEVF-1.LVL", + "D2LEVF-2.LVL", + "D2LEVF-3.LVL", + "D2LEVF-4.LVL", + "D2LEVF-S.LVL", +}; + +typedef struct BitmapFile { + char name[15]; +} BitmapFile; + +extern BitmapFile AllBitmaps[ MAX_BITMAP_FILES ]; + +int Ignore_tmap_num2_error; + +// ----------------------------------------------------------------------------- +void determine_used_textures_level(int load_level_flag, int shareware_flag, int level_num, int *tmap_buf, int *wall_buf, byte *level_tmap_buf, int max_tmap) +{ + int segnum, sidenum, objnum=max_tmap; + int i, j; + + Assert(shareware_flag != -17); + + for (i=0; irender_type == RT_POLYOBJ) { + polymodel *po = &Polygon_models[objp->rtype.pobj_info.model_num]; + + for (i=0; in_textures; i++) { + + int tli = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index; + // -- mprintf((0, "%s ", AllBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index].name)); + + if ((tli < MAX_BITMAP_FILES) && (tli >= 0)) { + tmap_buf[tli]++; + if (level_tmap_buf[tli] == -1) + level_tmap_buf[tli] = level_num; + } else + Int3(); // Hmm, It seems this texture is bogus! + } + + } + } + + + Ignore_tmap_num2_error = 0; + + // Process walls and segment sides. + for (segnum=0; segnum<=Highest_segment_index; segnum++) { + segment *segp = &Segments[segnum]; + + for (sidenum=0; sidenumsides[sidenum]; + + if (sidep->wall_num != -1) { + int clip_num = Walls[sidep->wall_num].clip_num; + if (clip_num != -1) { + + // -- int num_frames = WallAnims[clip_num].num_frames; + + wall_buf[clip_num] = 1; + + for (j=0; j<1; j++) { // Used to do through num_frames, but don't really want all the door01#3 stuff. + int tmap_num; + + tmap_num = Textures[WallAnims[clip_num].frames[j]].index; + Assert((tmap_num >= 0) && (tmap_num < MAX_BITMAP_FILES)); + tmap_buf[tmap_num]++; + if (level_tmap_buf[tmap_num] == -1) + level_tmap_buf[tmap_num] = level_num; + } + } + } else if (segp->children[sidenum] == -1) { + + if (sidep->tmap_num >= 0) + if (sidep->tmap_num < MAX_BITMAP_FILES) { + Assert(Textures[sidep->tmap_num].index < MAX_BITMAP_FILES); + tmap_buf[Textures[sidep->tmap_num].index]++; + if (level_tmap_buf[Textures[sidep->tmap_num].index] == -1) + level_tmap_buf[Textures[sidep->tmap_num].index] = level_num; + } else + Int3(); // Error, bogus texture map. Should not be greater than max_tmap. + + if ((sidep->tmap_num2 & 0x3fff) != 0) + if ((sidep->tmap_num2 & 0x3fff) < MAX_BITMAP_FILES) { + Assert(Textures[sidep->tmap_num2 & 0x3fff].index < MAX_BITMAP_FILES); + tmap_buf[Textures[sidep->tmap_num2 & 0x3fff].index]++; + if (level_tmap_buf[Textures[sidep->tmap_num2 & 0x3fff].index] == -1) + level_tmap_buf[Textures[sidep->tmap_num2 & 0x3fff].index] = level_num; + } else { + if (!Ignore_tmap_num2_error) + Int3(); // Error, bogus texture map. Should not be greater than max_tmap. + Ignore_tmap_num2_error = 1; + sidep->tmap_num2 = 0; + } + } + } + } +} + +// ----------------------------------------------------------------------------- +void merge_buffers(int *dest, int *src, int num) +{ + int i; + + for (i=0; i= 4) { +// -- mk, 08/14/95 -- fprintf(my_file, "\n"); +// -- mk, 08/14/95 -- count = 0; +// -- mk, 08/14/95 -- } + } +} + +// --05/17/95--// ----------------------------------------------------------------------------- +// --05/17/95--void say_used_once_tmaps(FILE *my_file, int *tb, byte *tb_lnum) +// --05/17/95--{ +// --05/17/95-- int i; +// --05/17/95-- char *level_name; +// --05/17/95-- +// --05/17/95-- for (i=0; i= NUM_SHAREWARE_LEVELS) { +// --05/17/95-- Assert((level_num - NUM_SHAREWARE_LEVELS >= 0) && (level_num - NUM_SHAREWARE_LEVELS < NUM_REGISTERED_LEVELS)); +// --05/17/95-- level_name = Registered_level_names[level_num - NUM_SHAREWARE_LEVELS]; +// --05/17/95-- } else { +// --05/17/95-- Assert((level_num >= 0) && (level_num < NUM_SHAREWARE_LEVELS)); +// --05/17/95-- level_name = Shareware_level_names[level_num]; +// --05/17/95-- } +// --05/17/95-- +// --05/17/95-- fprintf(my_file, "Texture %3i %8s used only once on level %s\n", i, TmapInfo[i].filename, level_name); +// --05/17/95-- } +// --05/17/95--} + +// ----------------------------------------------------------------------------- +void say_used_once_tmaps(FILE *my_file, int *tb, byte *tb_lnum) +{ + int i; + char *level_name; + + for (i=0; i= 4) { + fprintf(my_file, "\n"); + count = 0; + } + } +} + +// ----------------------------------------------------------------------------- +void say_unused_walls(FILE *my_file, int *tb) +{ + int i; + + for (i=0; iscale. +// Modifies only free vertices (those which are not part of a segment other than *sp). +// The vector *svp contains the x,y,z scale factors. The x,y,z directions are relative +// to the segment. x scales in the dimension of the right vector, y of the up vector, z of the forward vector. +// The dimension of the vectors is determined by averaging appropriate sets of 4 of the 8 points. +extern void med_scale_segment(segment *sp); + +// Loads mine *name from disk, updating global variables: +// Segments, Vertices +// Num_segments,Num_vertices +// Cursegp = pointer to active segment. Written as an index in med_save_mine, converted to a pointer +// at load time. +// Returns: +// 0 = successfully loaded. +// 1 = unable to load. +extern int med_load_mine(char *name); + +// Loads game *name from disk. +// This function automatically loads mine with name.MIN +extern int med_load_game(char *name); + + +// Loads a previous generation mine. Needs to be updated in code. +extern int med_load_pmine(char *name); + +// Saves mine contained in Segments[] and Vertices[]. +// Num_segments = number of segments in mine. +// Num_vertices = number of vertices in mine. +// Cursegp = current segment. +// Saves Num_segments, and index of current segment (which is Cursegp - Segments), which will be converted to a pointer +// and written to Cursegp in med_load_mine. +// Returns: +// 0 = successfully saved. +// 1 = unable to save. +extern int med_save_mine(char *name); + +// Loads group *filename from disk. +// Adds group to global Segments and Vertices array. +// Returns: +// 0 = successfully loaded. +// 1 = unable to load. +extern int med_load_group( char *filename, short *vertex_ids, short *segment_ids, int *num_vertices, int *num_segments); + +// Saves group *filename from disk. +// Saves group defined by vertex_ids and segment_ids to disk. +// Returns: +// 0 = successfully saved. +// 1 = unable to save. +extern int med_save_group( char *filename, short *vertex_ids, short *segment_ids, int num_vertices, int num_segments); + +// Updates the screen... (I put the prototype here for curves.c) +extern int medlisp_update_screen(); + +// Returns 0 if no error, 1 if error, whatever that might be. +// Sets globals: +// Num_segments +// Num_vertices +// Cursegp = pointer to only segment. +extern int create_new_mine(void); + +// extern void med_create_segment(segment *sp, vms_vector *scale); +extern void old_med_attach_segment(segment *sp,int main_side,int branch_side,fix cx, fix cy, fix cz, fix length, fix width, fix height, vms_matrix *mp); + +// Copy a segment from *ssp to *dsp. Do not simply copy the struct. Use *dsp's vertices, copying in +// just the values, not the indices. +extern void med_copy_segment(segment *dsp,segment *ssp); + +// Create a default segment. +// Useful for when user creates a garbage segment. +extern void med_create_default_segment(segment *sp); + +// Create New_segment with sizes found in *scale. +extern void med_create_new_segment(vms_vector *scale); + +// Create New_segment with sizes found in Cursegp. +extern void med_create_new_segment_from_cursegp(void); + +// Update New_segment using scale factors. +extern void med_update_new_segment(void); + +// Replace *sp with New_segment. +extern void med_update_segment(segment *sp); + +// Create a new segment and use it to form a bridge between two existing segments. +// Specify two segment:side pairs. If either segment:side is not open (ie, segment->children[side] != -1) +// then it is not legal to form the brider. +// Return: +// 0 bridge segment formed +// 1 unable to form bridge because one (or both) of the sides is not open. +// Note that no new vertices are created by this process. +extern int med_form_bridge_segment(segment *seg1, int side1, segment *seg2, int side2); + +// Compress mine at Segments and Vertices by squeezing out all holes. +// If no holes (ie, an unused segment followed by a used segment), then no action. +// If Cursegp or Markedsegp is a segment which gets moved to fill in a hole, then +// they are properly updated. +extern void med_compress_mine(void); + +// Extract the forward vector from segment *sp, return in *vp. +// The forward vector is defined to be the vector from the the center of the front face of the segment +// to the center of the back face of the segment. +extern void med_extract_forward_vector_from_segment(segment *sp,vms_vector *vp); + +// Extract the right vector from segment *sp, return in *vp. +// The forward vector is defined to be the vector from the the center of the left face of the segment +// to the center of the right face of the segment. +extern void med_extract_right_vector_from_segment(segment *sp,vms_vector *vp); + +// Extract the up vector from segment *sp, return in *vp. +// The forward vector is defined to be the vector from the the center of the bottom face of the segment +// to the center of the top face of the segment. +extern void med_extract_up_vector_from_segment(segment *sp,vms_vector *vp); + +// Compute the center point of a side of a segment. +// The center point is defined to be the average of the 4 points defining the side. +extern void med_compute_center_point_on_side(vms_vector *vp,segment *sp,int side); + +extern void set_matrix_based_on_side(vms_matrix *rotmat,int destside); + +// Given a forward vector, compute and return an angvec triple. +// [ THIS SHOULD BE MOVED TO THE VECTOR MATRIX LIBRARY ] +extern vms_angvec *vm_vec_to_angles(vms_angvec *result, vms_vector *forvec); + + +// Curves stuff. + +#define ACCURACY 0.1*F1_0 + +typedef struct vms_equation { + union { + struct {fix x3, x2, x1, x0, y3, y2, y1, y0, z3, z2, z1, z0;}; + fix xyz[3][4]; + }; +} vms_equation; + +extern void create_curve(vms_vector *p1, vms_vector *p4, vms_vector *r1, vms_vector *r4, vms_equation *coeffs); +// Q(t) = (2t^3 - 3t^2 + 1) p1 + (-2t^3 + 3t^2) p4 + (t^3 - 2t^2 + t) r1 + (t^3 - t^2 ) r4 + +extern vms_vector evaluate_curve(vms_equation *coeffs, int degree, fix t); + +extern fix curve_dist(vms_equation *coeffs, int degree, fix t0, vms_vector *p0, fix dist); + +extern void curve_dir(vms_equation *coeffs, int degree, fix t0, vms_vector *dir); + +extern void plot_parametric(vms_equation *coeffs, fix min_t, fix max_t, fix del_t); + +// Curve generation routine. +// Returns 1 if curve is generated. +// Returns 0 if no curve. +extern int generate_curve( fix r1scale, fix r4scale ); + +// Deletes existing curve generated in generate_curve(). +extern void delete_curve(); + +// --- // -- Temporary function, identical to med_rotate_segment, but it takes a vector instead of an angvec +// --- extern int med_rotate_segment_vec(segment *seg, vms_vector *vec); + +extern void med_extract_matrix_from_segment(segment *sp,vms_matrix *rotmat); + +// Assign default u,v coordinates to all sides of a segment. +// This routine should only be used for segments which are not connected to anything else, +// ie the segment created at mine creation. +extern void assign_default_uvs_to_segment(segment *segp); +extern void assign_default_uvs_to_side(segment *segp, int side); + +extern void assign_default_uvs_to_side(segment *segp,int side); + +// Assign u,v coordinates to con_seg, con_common_side from base_seg, base_common_side +// They are connected at the edge defined by the vertices abs_id1, abs_id2. +extern void med_assign_uvs_to_side(segment *con_seg, int con_common_side, segment *base_seg, int base_common_side, int abs_id1, int abs_id2); + +// Debug -- show a matrix. +// type: 0 --> mprintf, 1 --> printf +// *s = string to display +// *mp = matrix to display +extern void show_matrix(char *s,vms_matrix *mp,int type); + +// Create coordinate axes in orientation of specified segment, stores vertices at *vp. +extern void create_coordinate_axes_from_segment(segment *sp,short *vertnums); + +// Scale a segment. Then, if it is connected to something, rotate it. +extern int med_scale_and_rotate_segment(segment *seg, vms_angvec *rot); + +// Set Vertex_active to number of occurrences of each vertex. +// Set Num_vertices. +extern void set_vertex_counts(void); + +// Modify seg2 to share side2 with seg1:side1. This forms a connection between +// two segments without creating a new segment. It modifies seg2 by sharing +// vertices from seg1. seg1 is not modified. Four vertices from seg2 are +// deleted. +// If the four vertices forming side2 in seg2 are not free, the joint is not formed. +// Return code: +// 0 joint formed +// 1 unable to form joint because one or more vertices of side2 is not free +// 2 unable to form joint because side1 is already used +extern int med_form_joint(segment *seg1, int side1, segment *seg2, int side2); + +// The current texture... use by saying something=bm_lock_bitmap(CurrentTexture) +extern int CurrentTexture; + +extern void compute_segment_center(vms_vector *vp,segment *sp); + +extern void med_propagate_tmaps_to_segments(segment *base_seg,segment *con_seg, int uv_only_flag); + +extern void med_propagate_tmaps_to_back_side(segment *base_seg, int back_side, int uv_only_flag); + +extern void med_propagate_tmaps_to_any_side(segment *base_seg, int back_side, int tmap_num, int uv_only_flag); + +// Find segment adjacent to sp:side. +// Adjacent means a segment which shares all four vertices. +// Return true if segment found and fill in segment in adj_sp and side in adj_side. +// Return false if unable to find, in which case adj_sp and adj_side are undefined. +extern int med_find_adjacent_segment_side(segment *sp, int side, segment **adj_sp, int *adj_side); + +// Finds the closest segment and side to sp:side. +extern int med_find_closest_threshold_segment_side(segment *sp, int side, segment **adj_sp, int *adj_side, fix threshold); + +// Given two segments, return the side index in the connecting segment which connects to the base segment +extern int find_connect_side(segment *base_seg, segment *con_seg); + +// Select previous segment. +// If there is a connection on the side opposite to the current side, then choose that segment. +// If there is no connecting segment on the opposite face, try any segment. +extern void get_previous_segment(int curseg_num, int curside,int *newseg_num, int *newside); + +// Select next segment. +// If there is a connection on the current side, then choose that segment. +// If there is no connecting segment on the current side, try any segment. +extern void get_next_segment(int curseg_num, int curside, int *newseg_num, int *newside); + +// Copy texture maps in newseg to nsp. +extern void copy_uvs_seg_to_seg(segment *nsp,segment *newseg); + +// Return true if segment is concave. +extern int check_seg_concavity(segment *s); + +// Return N_found_segs = number of concave segments in mine. +// Segment ids stored at Found_segs +extern void find_concave_segs(void); + +// High level call. Check for concave segments, print warning message (using editor_status) +// if any concave segments. +// Calls find_concave_segs, therefore N_found_segs gets set, and Found_segs filled in. +extern void warn_if_concave_segments(void); + +// Warn if segment s is concave. +extern void warn_if_concave_segment(segment *s); + +// Add a vertex to the vertex list. +extern int med_add_vertex(vms_vector *vp); + +// Add a vertex to the vertex list which may be identical to another vertex (in terms of coordinates). +// Don't scan list, looking for presence of a vertex with same coords, add this one. +extern int med_create_duplicate_vertex(vms_vector *vp); + +// Create a new segment, duplicating exactly, including vertex ids and children, the passed segment. +extern int med_create_duplicate_segment(segment *sp); + +// Returns the index of a free segment. +// Scans the Segments array. +extern int get_free_segment_number(void); + +// Diagnostic message. +extern void diagnostic_message(const char *format, ... ); + +// Status Icon. +extern void print_status_icon( char icon[1], int position ); +extern void clear_status_icon( char icon[1], int position ); + +// Editor status message. +extern void editor_status(const char *format, ... ); + +// Variables in editor.c that the k*.c files need + +#define UF_NONE 0x000 //nothing has changed +#define UF_WORLD_CHANGED 0x001 //something added or deleted +#define UF_VIEWPOINT_MOVED 0x002 //what we're watching has moved + +#define UF_GAME_VIEW_CHANGED 0x004 //the game window changed +#define UF_ED_STATE_CHANGED 0x008 //something like curside,curseg changed + +#define UF_ALL 0xffffffff //all flags + +extern uint Update_flags; +extern int Funky_chase_mode; +extern vms_angvec Seg_orientation; +extern vms_vector Seg_scale; +extern int mine_changed; +extern int ModeFlag; +extern editor_view *current_view; + +//the view for the different windows +extern editor_view LargeView; +extern editor_view TopView; +extern editor_view FrontView; +extern editor_view RightView; + +extern void set_view_target_from_segment(segment *sp); +extern int SafetyCheck(); + +extern void editor_status( const char *format, ...); + +extern int MacroNumEvents; +extern int MacroStatus; + +//extern int Highest_vertex_index; // Highest index in Vertices and Vertex_active, an efficiency hack +//extern int Highest_segment_index; // Highest index in Segments, an efficiency hack +extern int Lock_view_to_cursegp; // !0 means whenever cursegp changes, view it + +// eglobal.c +extern int Num_tilings; // number of tilings/wall +extern int Degenerate_segment_found; + +extern byte Been_visited[]; // List of segments visited in a recursive search, if element n set, segment n done been visited + +// Initializes autosave system. +// Sets global Autosave_count to 0. +extern void init_autosave(void); + +// Closes autosave system. +// Deletes all autosaved files. +extern void close_autosave(void); + +// Saves current mine to name.miX where name = suffix of mine name and X = Autosave_count. +// For example, if name = "cookie.min", and Autosave_count = 3, then writes "cookie.mi3". +// Increments Autosave_count, wrapping from 9 to 0. +// (If there is no current mine name, assume "temp.min") +// Call med_save_mine to save the mine. +extern void autosave_mine(char *name); + +// Timed autosave +extern void TimedAutosave(char *name); +extern void set_editor_time_of_day(); + +// Undo function +extern int undo(void); +extern char mine_filename[128]; +extern char undo_status[10][100]; + +// group.c +int AttachSegmentNewAng(vms_angvec *pbh); +int RotateSegmentNew(vms_angvec *pbh); +int rotate_segment_new(vms_angvec *pbh); + +//get & free vertices +int alloc_vert(); +void free_vert(int vert_num); + +// The current robot type declared in eglobal.c +extern int Cur_robot_type; + +// From med.c +extern int DisplayCurrentRobotType(void); +extern short Cur_object_index; + +extern int render_3d_in_big_window; +extern void move_object_to_mouse_click(void); + +//these are instances of canvases, pointed to by variables below +extern grs_canvas _canv_editor_game; //the game on the editor screen + +//these are pointers to our canvases +extern grs_canvas *Canv_editor; //the editor screen +extern grs_canvas *Canv_editor_game; //the game on the editor screen + +extern grs_canvas *canv_offscreen; //for off-screen rendering +extern grs_canvas *Pad_text_canvas; // Keypad text + +//where the editor is looking +extern vms_vector Ed_view_target; + +extern int gamestate_not_restored; + +extern UI_WINDOW * EditorWindow; + +extern int Large_view_index; + +extern UI_GADGET_USERBOX * GameViewBox; +extern UI_GADGET_USERBOX * LargeViewBox; +extern UI_GADGET_USERBOX * GroupViewBox; + +extern med_point_2_vec(grs_canvas *canv,vms_vector *v,short sx,short sy); + +//shutdown ui on the editor screen +close_editor_screen(void); + +// From eobject.c +extern int place_object(segment *segp, vms_vector *object_pos, int object_type); + +// from ksegsize.c +extern void med_extract_up_vector_from_segment_side(segment *sp, int sidenum, vms_vector *vp); +extern void med_extract_right_vector_from_segment_side(segment *sp, int sidenum, vms_vector *vp); +extern void med_extract_forward_vector_from_segment_side(segment *sp, int sidenum, vms_vector *vp); + +// In medmisc.c +extern void draw_world_from_game(void); + +// In medrobot.c +extern void close_all_windows(void); + +// In seguvs.c + +// Amount to stretch a texture map by. +// The two different ones are for the two dimensions of a texture map. +extern fix Stretch_scale_x, Stretch_scale_y; + +#endif + diff --git a/main/editor/kdefs.h b/main/editor/kdefs.h new file mode 100644 index 00000000..ae3bf02d --- /dev/null +++ b/main/editor/kdefs.h @@ -0,0 +1,336 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +// In khelp.c +int DoHelp(); + +// In kcurve.c +int InitCurve(); +int GenerateCurve(); +int DecreaseR4(); +int IncreaseR4(); +int DecreaseR1(); +int IncreaseR1(); +int DeleteCurve(); +int SetCurve(); + +// In kmine.c +int SaveMine(); +int LoadMine(); +int MineMenu(); +int CreateNewMine(); +int LoadOldMine(); + +int SaveSituation(); +int LoadSituation(); + +// In kgame.c +void SetPlayerPosition(void); +int SaveGameData(); +int LoadGameData(); +int LoadMineOnly(); +void ResetFilename(); + +// In group.c +int LoadGroup(); +int SaveGroup(); +int PrevGroup(); +int NextGroup(); +int CreateGroup(); +int SubtractFromGroup(); +int DeleteGroup(); +int MarkGroupSegment(); +int MoveGroup(void); +int CopyGroup(void); +int AttachSegmentNew(); +int UngroupSegment(); +int GroupSegment(); +int Degroup(); +int RotateGroup(); + +// In segment.c +void ToggleBottom(); +void make_curside_bottom_side(); +int select_segment_by_number(); +int select_segment_with_powerup(); + +// In editor.c +int UndoCommand(); + +// In kview.c +int ZoomOut(); +int ZoomIn(); +int MoveAway(); +int MoveCloser(); +int ToggleChaseMode(); + +// In kbuild.c +int CreateBridge(); +int FormJoint(); +int CreateAdjacentJoint(); +int CreateAdjacentJointsSegment(); +int CreateAdjacentJointsAll(); +int CreateSloppyAdjacentJoint(); +int CreateSloppyAdjacentJointsGroup(); + +// In ksegmove.c +int DecreaseHeading(); +int IncreaseHeading(); +int DecreasePitch(); +int IncreasePitch(); +int DecreaseBank(); +int IncreaseBank(); + +// In ksegsel.c +int SelectCurrentSegForward(); +int SelectCurrentSegBackward(); +int SelectNextSide(); +int SelectPrevSide(); +int CopySegToMarked(); +int SelectBottom(); +int SelectFront(); +int SelectTop(); +int SelectBack(); +int SelectLeft(); +int SelectRight(); + +// In ksegsize.c +int IncreaseSegLength(); +int DecreaseSegLength(); +int DecreaseSegWidth(); +int IncreaseSegWidth(); +int IncreaseSegHeight(); +int DecreaseSegHeight(); +int ToggleSegSizeMode(); +int PerturbCurside(); +int PerturbCursideBig(); + +int IncreaseSegLengthBig(); +int DecreaseSegLengthBig(); +int DecreaseSegWidthBig(); +int IncreaseSegWidthBig(); +int IncreaseSegHeightBig(); +int DecreaseSegHeightBig(); + +int IncreaseSegLengthDefault(); +int DecreaseSegLengthDefault(); +int IncreaseSegWidthDefault(); +int DecreaseSegWidthDefault(); +int IncreaseSegHeightDefault(); +int DecreaseSegHeightDefault(); + +// In ktmap.c +int AssignTexture(); +int AssignTexture2(); +int ClearTexture2(); +int PropagateTextures(); +int PropagateTexturesMove(); +int PropagateTexturesMoveUVs(); +int PropagateTexturesUVs(); +int PropagateTexturesSelected(); + +//--//// In macro.c +//--//int MacroMenu(); +//--//int MacroPlayFast(); +//--//int MacroPlayNormal(); +//--//int MacroRecordAll(); +//--//int MacroRecordKeys(); +//--//int MacroSave(); +//--//int MacroLoad(); + +// In editor.c +int medlisp_update_screen(); +int medlisp_delete_segment(void); +int medlisp_scale_segment(void); +int medlisp_rotate_segment(void); +int medlisp_add_segment(); +int AttachSegment(); +int DeleteSegment(); +int DosShell(); +int CallLisp(); +int ExitEditor(); +int ShowAbout(); +int ExchangeMarkandCurseg(); +int CopySegtoMarked(); +int med_keypad_goto_prev(); +int med_keypad_goto_next(); +int med_keypad_goto(); +int med_increase_tilings(); +int med_decrease_tilings(); +int ToggleAutosave(); +int MarkStart(); +int MarkEnd(); + +// Texture.c +int TexFlipX(); +int TexFlipY(); +int TexSlideUp(); +int TexSlideLeft(); +int TexSetDefault(); +int TexSetDefaultSelected(); +int TexSlideRight(); +int TexRotateLeft(); +int TexSlideDown(); +int TexRotateRight(); +int TexSelectActiveEdge(); +int TexRotate90Degrees(); +int TexIncreaseTiling(); +int TexDecreaseTiling(); +int TexSlideUpBig(); +int TexSlideLeftBig(); +int TexSlideRightBig(); +int TexRotateLeftBig(); +int TexSlideDownBig(); +int TexRotateRightBig(); +int TexStretchDown(); +int TexStretchUp(); +int TexChangeAll(); +int TexChangeAll2(); + +// object.c +int ObjectPlaceObject(); +int ObjectMakeCoop(); +int ObjectPlaceObjectTmap(); +int ObjectDelete(); +int ObjectMoveForward(); +int ObjectMoveLeft(); +int ObjectSetDefault(); +int ObjectMoveRight(); +int ObjectMoveBack(); +int ObjectMoveDown(); +int ObjectMoveUp(); +int ObjectMoveNearer(); +int ObjectMoveFurther(); +int ObjectSelectNextinSegment(); +int ObjectSelectNextType(); +int ObjectDecreaseBank(); +int ObjectIncreaseBank(); +int ObjectDecreasePitch(); +int ObjectIncreasePitch(); +int ObjectDecreaseHeading(); +int ObjectIncreaseHeading(); +int ObjectResetObject(); + + +// elight.c +int LightSelectNextVertex(); +int LightSelectNextEdge(); +int LightCopyIntensity(); +int LightCopyIntensitySegment(); +int LightDecreaseLightVertex(); +int LightIncreaseLightVertex(); +int LightDecreaseLightSide(); +int LightIncreaseLightSide(); +int LightDecreaseLightSegment(); +int LightIncreaseLightSegment(); +int LightSetMaximum(); +int LightSetDefault(); +int LightSetDefaultAll(); +int LightAmbientLighting(); + +// seguvs.c +int fix_bogus_uvs_on_side(); +int fix_bogus_uvs_all(); +void set_average_light_on_curside(void); +void set_average_light_on_all(void); +void set_average_light_on_all_quick(void); + +// Miscellaneous, please put in correct file if you have time +int IncreaseDrawDepth(); +int DecreaseDrawDepth(); +int GotoGame(); +int GotoGameScreen(); +int DropIntoDebugger(); +int CreateDefaultNewSegment(); +int CreateDefaultNewSegmentandAttach(); +int ClearSelectedList(); +int ClearFoundList(); +int SortSelectedList(); +int SetPlayerFromCurseg(); +int SetPlayerFromCursegAndRotate(); +int SetPlayerFromCursegMinusOne(); +int FindConcaveSegs(); +int SelectNextFoundSeg(); +int SelectPreviousFoundSeg(void); +int do_reset_orient(); +int GameZoomOut(); +int GameZoomIn(); + +// John's temp page stuff +int medtmp_set_page(); + +// In objpage.c +int objpage_goto_next_object(); + +// In medsel.c +extern int SortSelectedList(void); +extern int SelectNextFoundSeg(void); +extern int SelectPreviousFoundSeg(void); + +// In wall.c +extern int wall_add_blastable(void); +extern int wall_add_door(void); +extern int wall_add_closed_wall(void); +extern int wall_add_external_wall(void); +extern int wall_lock_door(void); +extern int wall_unlock_door(void); +extern int wall_automate_door(void); +extern int wall_deautomate_door(void); +extern int wall_add_illusion(void); +extern int wall_remove(void); +extern int wall_restore_all(void); +extern int wall_assign_door_1(void); +extern int wall_assign_door_2(void); +extern int wall_assign_door_3(void); +extern int wall_assign_door_4(void); +extern int wall_assign_door_5(void); +extern int wall_assign_door_6(void); +extern int wall_assign_door_7(void); +extern int wall_assign_door_8(void); +extern int do_wall_dialog(void); +extern int do_trigger_dialog(void); +extern int check_walls(void); +extern int delete_all_walls(void); +extern int delete_all_controlcen_triggers(void); + +// In centers.c +extern int do_centers_dialog(void); + +// In switch.c +//extern int trigger_add_damage(void); +//extern int trigger_add_blank(void); +//extern int trigger_add_exit(void); +//extern int trigger_add_repair(void); +//extern int trigger_control(void); +//extern int trigger_remove(void); +//extern int trigger_add_if_control_center_dead(void); +extern int bind_wall_to_control_trigger(void); + +// In med.c +extern int fuelcen_create_from_curseg(); +extern int repaircen_create_from_curseg(); +extern int controlcen_create_from_curseg(); +extern int robotmaker_create_from_curseg(); +extern int fuelcen_reset_all(); +extern void RestoreGameState(); +extern int fuelcen_delete_from_curseg(); +extern int goal_blue_create_from_curseg(); +extern int goal_red_create_from_curseg(); + +// In editor\robot.c +extern int do_robot_dialog(); +extern int do_object_dialog(); + +// In editor\hostage.c +extern int do_hostage_dialog(); + diff --git a/main/editor/texpage.h b/main/editor/texpage.h new file mode 100644 index 00000000..fc48c676 --- /dev/null +++ b/main/editor/texpage.h @@ -0,0 +1,31 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + + +#ifndef _TEXPAGE_H +#define _TEXPAGE_H + +#include "ui.h" + +extern int TextureLights; +extern int TextureEffects; +extern int TextureMetals; + +int texpage_grab_current(int n); +int texpage_goto_first(); +void texpage_init( UI_WINDOW * win ); +void texpage_close(); +void texpage_do(); + +#endif diff --git a/main/effects.c b/main/effects.c new file mode 100644 index 00000000..f4dbd463 --- /dev/null +++ b/main/effects.c @@ -0,0 +1,169 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + +#ifdef RCS +static char rcsid[] = "$Id: effects.c,v 1.1.1.1 2001-01-19 03:30:00 bradleyb Exp $"; +#endif + +#include +#include +#include +#include +#include + +#include "gr.h" +#include "inferno.h" +#include "game.h" +#include "vclip.h" +#include "effects.h" +#include "bm.h" +#include "mono.h" +#include "u_mem.h" +#include "textures.h" +#include "cntrlcen.h" +#include "error.h" + +int Num_effects; +eclip Effects[MAX_EFFECTS]; + +void init_special_effects() +{ + int i; + + for (i=0;iflags & EF_STOPPED) + continue; + + ec->time_left -= FrameTime; + + while (ec->time_left < 0) { + + ec->time_left += ec->vc.frame_time; + + ec->frame_count++; + if (ec->frame_count >= ec->vc.num_frames) { + if (ec->flags & EF_ONE_SHOT) { + Assert(ec->segnum!=-1); + Assert(ec->sidenum>=0 && ec->sidenum<6); + Assert(ec->dest_bm_num!=0 && Segments[ec->segnum].sides[ec->sidenum].tmap_num2!=0); + Segments[ec->segnum].sides[ec->sidenum].tmap_num2 = ec->dest_bm_num | (Segments[ec->segnum].sides[ec->sidenum].tmap_num2&0xc000); //replace with destoyed + ec->flags &= ~EF_ONE_SHOT; + ec->segnum = -1; //done with this + } + + ec->frame_count = 0; + } + } + + if (ec->flags & EF_CRITICAL) + continue; + + if (ec->crit_clip!=-1 && Control_center_destroyed) { + int n = ec->crit_clip; + + //*ec->bm_ptr = &GameBitmaps[Effects[n].vc.frames[Effects[n].frame_count].index]; + if (ec->changing_wall_texture != -1) + Textures[ec->changing_wall_texture] = Effects[n].vc.frames[Effects[n].frame_count]; + + if (ec->changing_object_texture != -1) + ObjBitmaps[ec->changing_object_texture] = Effects[n].vc.frames[Effects[n].frame_count]; + + } + else { + // *ec->bm_ptr = &GameBitmaps[ec->vc.frames[ec->frame_count].index]; + if (ec->changing_wall_texture != -1) + Textures[ec->changing_wall_texture] = ec->vc.frames[ec->frame_count]; + + if (ec->changing_object_texture != -1) + ObjBitmaps[ec->changing_object_texture] = ec->vc.frames[ec->frame_count]; + } + + } +} + +void restore_effect_bitmap_icons() +{ + int i; + + for (i=0;ibm_ptr != -1); + + ec->flags |= EF_STOPPED; + + ec->frame_count = 0; + //*ec->bm_ptr = &GameBitmaps[ec->vc.frames[0].index]; + + if (ec->changing_wall_texture != -1) + Textures[ec->changing_wall_texture] = ec->vc.frames[0]; + + if (ec->changing_object_texture != -1) + ObjBitmaps[ec->changing_object_texture] = ec->vc.frames[0]; + +} + +//restart a stopped effect +void restart_effect(int effect_num) +{ + Effects[effect_num].flags &= ~EF_STOPPED; + + //Assert(Effects[effect_num].bm_ptr != -1); +} + diff --git a/main/effects.h b/main/effects.h new file mode 100644 index 00000000..b85157e4 --- /dev/null +++ b/main/effects.h @@ -0,0 +1,66 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + + +#ifndef _EFFECTS_H +#define _EFFECTS_H + +#include "vclip.h" + +#define MAX_EFFECTS 110 + +//flags for eclips. If no flags are set, always plays + +#define EF_CRITICAL 1 //this doesn't get played directly (only when mine critical) +#define EF_ONE_SHOT 2 //this is a special that gets played once +#define EF_STOPPED 4 //this has been stopped + +typedef struct eclip { + vclip vc; //imbedded vclip + fix time_left; //for sequencing + int frame_count; //for sequencing + short changing_wall_texture; //Which element of Textures array to replace. + short changing_object_texture; //Which element of ObjBitmapPtrs array to replace. + int flags; //see above + int crit_clip; //use this clip instead of above one when mine critical + int dest_bm_num; //use this bitmap when monitor destroyed + int dest_vclip; //what vclip to play when exploding + int dest_eclip; //what eclip to play when exploding + fix dest_size; //3d size of explosion + int sound_num; //what sound this makes + int segnum,sidenum; //what seg & side, for one-shot clips +} __pack__ eclip; + +extern int Num_effects; +extern eclip Effects[MAX_EFFECTS]; + +// Set up special effects. +extern void init_special_effects(); + +// Clear any active one-shots +void reset_special_effects(); + +// Function called in game loop to do effects. +extern void do_special_effects(); + +// Restore bitmap +extern void restore_effect_bitmap_icons(); + +//stop an effect from animating. Show first frame. +void stop_effect(int effect_num); + +//restart a stopped effect +void restart_effect(int effect_num); + +#endif diff --git a/main/endlevel.c b/main/endlevel.c new file mode 100644 index 00000000..9a15b2b5 --- /dev/null +++ b/main/endlevel.c @@ -0,0 +1,1676 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +#ifdef RCS +static char rcsid[] = "$Id: endlevel.c,v 1.1.1.1 2001-01-19 03:30:01 bradleyb Exp $"; +#endif + +#include + +//#define SLEW_ON 1 + +//#define _MARK_ON + +#include + + +#include +#include + +#include "fix.h" +#include "vecmat.h" +#include "gr.h" +#include "3d.h" +#include "error.h" +#include "palette.h" +#include "iff.h" +#include "mono.h" +#include "texmap.h" +#include "fvi.h" +#include "u_mem.h" +#include "sounds.h" + +#include "inferno.h" +#include "endlevel.h" +#include "object.h" +#include "game.h" +#include "screens.h" +#include "gauges.h" +#include "wall.h" +#include "terrain.h" +#include "polyobj.h" +#include "bm.h" +#include "gameseq.h" +#include "newdemo.h" +#include "multi.h" +#include "vclip.h" +#include "fireball.h" +#include "network.h" +#include "text.h" +#include "digi.h" +#include "cfile.h" +#include "compbit.h" +#include "songs.h" +#include "movie.h" +#include "render.h" + +typedef struct flythrough_data { + object *obj; + vms_angvec angles; //orientation in angles + vms_vector step; //how far in a second + vms_vector angstep; //rotation per second + fix speed; //how fast object is moving + vms_vector headvec; //where we want to be pointing + int first_time; //flag for if first time through + fix offset_frac; //how far off-center as portion of way + fix offset_dist; //how far currently off-center +} flythrough_data; + +//endlevel sequence states + +#define EL_OFF 0 //not in endlevel +#define EL_FLYTHROUGH 1 //auto-flythrough in tunnel +#define EL_LOOKBACK 2 //looking back at player +#define EL_OUTSIDE 3 //flying outside for a while +#define EL_STOPPED 4 //stopped, watching explosion +#define EL_PANNING 5 //panning around, watching player +#define EL_CHASING 6 //chasing player to station + +#define SHORT_SEQUENCE 1 //if defined, end sequnce when panning starts +//#define STATION_ENABLED 1 //if defined, load & use space station model + +int Endlevel_sequence = 0; + +extern fix player_speed; + +int transition_segnum,exit_segnum; + +object *endlevel_camera; + +#define FLY_SPEED i2f(50) + +void start_endlevel_flythrough(int n,object *obj,fix speed); + +#ifdef D2_OEM +char movie_table[] = { 'a','a','a','a','d','d','d','d' }; +#else +char movie_table[] = { 'a','b','c', + #ifndef SHAREWARE + 'a', + 'd','f','d','f', + 'g','h','i','g', + 'j','k','l','j', + 'm','o','m','o', + 'p','q','p','q' + #endif + }; +#endif + +#define N_MOVIES (sizeof(movie_table) / sizeof(*movie_table)) + +#ifndef SHAREWARE +#ifdef D2_OEM +char movie_table_secret[] = {'a','d'}; +#else +char movie_table_secret[] = {'a','d','g','j','m','p'}; +#endif +#define N_MOVIES_SECRET (sizeof(movie_table_secret) / sizeof(*movie_table_secret)) +#else +#define N_MOVIES_SECRET 0 +#endif + + +#define FLY_ACCEL i2f(5) + +fix cur_fly_speed,desired_fly_speed; + +extern int matt_find_connect_side(int seg0,int seg1); + +grs_bitmap *satellite_bitmap,*station_bitmap,*terrain_bitmap; //!!*exit_bitmap, +vms_vector satellite_pos,satellite_upvec; +//!!grs_bitmap **exit_bitmap_list[1]; +int station_modelnum,exit_modelnum,destroyed_exit_modelnum; + +vms_vector station_pos = {0xf8c4<<10,0x3c1c<<12,0x372<<10}; + +#ifdef STATION_ENABLED +grs_bitmap *station_bitmap; +grs_bitmap **station_bitmap_list[1]; +int station_modelnum; +#endif + +vms_vector mine_exit_point; +vms_vector mine_ground_exit_point; +vms_vector mine_side_exit_point; +vms_matrix mine_exit_orient; + +int outside_mine; + +void start_endlevel_flythrough(int n,object *obj,fix speed); + +grs_bitmap terrain_bm_instance; +grs_bitmap satellite_bm_instance; + +//find delta between two angles +fixang delta_ang(fixang a,fixang b) +{ + fixang delta0,delta1; + + return (abs(delta0 = a - b) < abs(delta1 = b - a)) ? delta0 : delta1; + +} + +//return though which side of seg0 is seg1 +int matt_find_connect_side(int seg0,int seg1) +{ + segment *Seg=&Segments[seg0]; + int i; + + for (i=MAX_SIDES_PER_SEGMENT;i--;) if (Seg->children[i]==seg1) return i; + + return -1; +} + +extern int Kmatrix_nomovie_message; + +#if defined(D2_OEM) || defined(COMPILATION) +#define MOVIE_REQUIRED 0 +#else +#define MOVIE_REQUIRED 1 +#endif + +//returns movie played status. see movie.h +int start_endlevel_movie() +{ + char movie_name[] = "esa.mve"; + int r; + ubyte save_pal[768]; + + Assert(Current_mission_num == 0); //only play movie for built-in mission + + Assert(N_MOVIES >= Last_level); + Assert(N_MOVIES_SECRET >= -Last_secret_level); + + #ifndef D2_OEM + if (Current_level_num == Last_level) + return 1; //don't play movie + #endif + + if (Current_level_num > 0) + movie_name[2] = movie_table[Current_level_num-1]; + else { + #ifndef SHAREWARE + return 0; //no escapes for secret level + #else + Error("Invalid level number <%d>",Current_level_num); + #endif + } + + memcpy(save_pal,gr_palette,768); + + #ifndef SHAREWARE + r=PlayMovie(movie_name,(Game_mode & GM_MULTI)?0:MOVIE_REQUIRED); + #else + return 0; // movie not played for shareware + #endif + + if (Newdemo_state == ND_STATE_PLAYBACK) { + set_screen_mode(SCREEN_GAME); + memcpy(gr_palette,save_pal,768); + } + +#ifdef NETWORK + if (r==MOVIE_NOT_PLAYED && (Game_mode & GM_MULTI)) + Kmatrix_nomovie_message=1; + else + Kmatrix_nomovie_message=0; +#endif + + return (r); + +} + +#ifdef SHAREWARE +void +free_endlevel_data() +{ + if (terrain_bm_instance.bm_data) + d_free(terrain_bm_instance.bm_data); + + if (satellite_bm_instance.bm_data) + d_free(satellite_bm_instance.bm_data); +} + +init_endlevel() +{ + //##satellite_bitmap = bm_load("earth.bbm"); + //##terrain_bitmap = bm_load("moon.bbm"); + //## + //##load_terrain("matt5b.bbm"); //load bitmap as height array + //##//load_terrain("ttest2.bbm"); //load bitmap as height array + + #ifdef STATION_ENABLED + station_bitmap = bm_load("steel3.bbm"); + station_bitmap_list[0] = &station_bitmap; + + station_modelnum = load_polygon_model("station.pof",1,station_bitmap_list,NULL); + #endif + +//!! exit_bitmap = bm_load("steel1.bbm"); +//!! exit_bitmap_list[0] = &exit_bitmap; + +//!! exit_modelnum = load_polygon_model("exit01.pof",1,exit_bitmap_list,NULL); +//!! destroyed_exit_modelnum = load_polygon_model("exit01d.pof",1,exit_bitmap_list,NULL); + + generate_starfield(); + + atexit(free_endlevel_data); + + terrain_bm_instance.bm_data = satellite_bm_instance.bm_data = NULL; +} +#endif //SHAREWARE + +object external_explosion; +int ext_expl_playing,mine_destroyed; + +extern fix flash_scale; + +vms_angvec exit_angles={-0xa00,0,0}; + +vms_matrix surface_orient; + +int endlevel_data_loaded=0; +extern char last_palette_loaded[]; + +void start_endlevel_sequence() +{ + int i; + int movie_played; + #if defined(MACINTOSH) && defined(SHAREWARE) + static int inited = 0; + + if (!inited) { + load_exit_models(); + inited = 1; + } + #endif + + if (Newdemo_state == ND_STATE_RECORDING) // stop demo recording + Newdemo_state = ND_STATE_PAUSED; + + if (Newdemo_state == ND_STATE_PLAYBACK) { // don't do this if in playback mode + if (Current_mission_num == 0) //only play movie for built-in mission + start_endlevel_movie(); + strcpy(last_palette_loaded,""); //force palette load next time + return; + } + + if (Player_is_dead || ConsoleObject->flags&OF_SHOULD_BE_DEAD) + return; //don't start if dead! + + // Dematerialize Buddy! + for (i=0; i<=Highest_object_index; i++) + if (Objects[i].type == OBJ_ROBOT) + if (Robot_info[Objects[i].id].companion) { + object_create_explosion(Objects[i].segnum, &Objects[i].pos, F1_0*7/2, VCLIP_POWERUP_DISAPPEARANCE ); + Objects[i].flags |= OF_SHOULD_BE_DEAD; + } + + Players[Player_num].homing_object_dist = -F1_0; // Turn off homing sound. + + reset_rear_view(); //turn off rear view if set + +#ifdef NETWORK + if (Game_mode & GM_MULTI) { + multi_send_endlevel_start(0); + network_do_frame(1, 1); + } +#endif + + if (Current_mission_num == 0) { //only play movie for built-in mission + + //try playing movie. If it plays, great. if not, do rendered ending + + if (!(Game_mode & GM_MULTI)) + movie_played = start_endlevel_movie(); + + #ifdef SHAREWARE + if (movie_played == MOVIE_NOT_PLAYED) { //don't have movie. Do rendered sequence + #ifndef WINDOWS + start_rendered_endlevel_sequence(); + #endif + return; + } + #endif + + } + else + gr_palette_fade_out(gr_palette, 32, 0); + + PlayerFinishedLevel(0); //done with level +} + +#ifndef SHAREWARE + +void do_endlevel_frame() {Int3();} +void stop_endlevel_sequence() {Int3();} +void render_endlevel_frame(fix eye_offset) {Int3();} + +#else + +static int cockpit_mode_save; + +start_rendered_endlevel_sequence() +{ + int last_segnum,exit_side,tunnel_length; + + { + int segnum,old_segnum,entry_side,i; + + //count segments in exit tunnel + + old_segnum = ConsoleObject->segnum; + exit_side = find_exit_side(ConsoleObject); + segnum = Segments[old_segnum].children[exit_side]; + tunnel_length = 0; + do { + entry_side = matt_find_connect_side(segnum,old_segnum); + exit_side = Side_opposite[entry_side]; + old_segnum = segnum; + segnum = Segments[segnum].children[exit_side]; + tunnel_length++; + } while (segnum >= 0); + + if (segnum != -2) { + PlayerFinishedLevel(0); //don't do special sequence + return; + } + + last_segnum = old_segnum; + + //now pick transition segnum 1/3 of the way in + + old_segnum = ConsoleObject->segnum; + exit_side = find_exit_side(ConsoleObject); + segnum = Segments[old_segnum].children[exit_side]; + i=tunnel_length/3; + while (i--) { + + entry_side = matt_find_connect_side(segnum,old_segnum); + exit_side = Side_opposite[entry_side]; + old_segnum = segnum; + segnum = Segments[segnum].children[exit_side]; + } + transition_segnum = segnum; + + } + + cockpit_mode_save = Cockpit_mode; + + #ifdef NETWORK + if (Game_mode & GM_MULTI) { + multi_send_endlevel_start(0); + network_do_frame(1, 1); + } + #endif + + #ifdef SHAREWARE + Assert(last_segnum == exit_segnum); + // songs_play_song( SONG_ENDLEVEL, 0 ); // JTS: Until we get an exit song, just don't worry + #endif + + Endlevel_sequence = EL_FLYTHROUGH; + + ConsoleObject->movement_type = MT_NONE; //movement handled by flythrough + ConsoleObject->control_type = CT_NONE; + + Game_suspended |= SUSP_ROBOTS; //robots don't move + + cur_fly_speed = desired_fly_speed = FLY_SPEED; + + start_endlevel_flythrough(0,ConsoleObject,cur_fly_speed); //initialize + + HUD_init_message( TXT_EXIT_SEQUENCE ); + + outside_mine = ext_expl_playing = 0; + + flash_scale = f1_0; + + //init_endlevel(); + + mine_destroyed=0; + +} + +extern flythrough_data fly_objects[]; + +extern object *slew_obj; + +vms_angvec player_angles,player_dest_angles; +vms_angvec camera_desired_angles,camera_cur_angles; + +#define CHASE_TURN_RATE (0x4000/4) //max turn per second + +//returns bitmask of which angles are at dest. bits 0,1,2 = p,b,h +int chase_angles(vms_angvec *cur_angles,vms_angvec *desired_angles) +{ + vms_angvec delta_angs,alt_angles,alt_delta_angs; + fix total_delta,alt_total_delta; + fix frame_turn; + int mask=0; + + delta_angs.p = desired_angles->p - cur_angles->p; + delta_angs.h = desired_angles->h - cur_angles->h; + delta_angs.b = desired_angles->b - cur_angles->b; +//delta_angs.b = 0; + +//printf("chasing angles...desired = %x %x %x, cur = %x %x %x ",desired_angles->p,desired_angles->b,desired_angles->h,cur_angles->p,cur_angles->b,cur_angles->h); + + total_delta = abs(delta_angs.p) + abs(delta_angs.b) + abs(delta_angs.h); + + alt_angles.p = f1_0/2 - cur_angles->p; + alt_angles.b = cur_angles->b + f1_0/2; + alt_angles.h = cur_angles->h + f1_0/2; + + alt_delta_angs.p = desired_angles->p - alt_angles.p; + alt_delta_angs.h = desired_angles->h - alt_angles.h; + alt_delta_angs.b = desired_angles->b - alt_angles.b; +//alt_delta_angs.b = 0; + + alt_total_delta = abs(alt_delta_angs.p) + abs(alt_delta_angs.b) + abs(alt_delta_angs.h); + +//printf("Total delta = %x, alt total_delta = %x\n",total_delta,alt_total_delta); + + if (alt_total_delta < total_delta) { + //mprintf((0,"FLIPPING ANGLES!\n")); + //printf("FLIPPING ANGLES!\n"); + *cur_angles = alt_angles; + delta_angs = alt_delta_angs; + } + + frame_turn = fixmul(FrameTime,CHASE_TURN_RATE); + + if (abs(delta_angs.p) < frame_turn) { + cur_angles->p = desired_angles->p; + mask |= 1; + } + else + if (delta_angs.p > 0) + cur_angles->p += frame_turn; + else + cur_angles->p -= frame_turn; + + if (abs(delta_angs.b) < frame_turn) { + cur_angles->b = desired_angles->b; + mask |= 2; + } + else + if (delta_angs.b > 0) + cur_angles->b += frame_turn; + else + cur_angles->b -= frame_turn; +//cur_angles->b = 0; + + if (abs(delta_angs.h) < frame_turn) { + cur_angles->h = desired_angles->h; + mask |= 4; + } + else + if (delta_angs.h > 0) + cur_angles->h += frame_turn; + else + cur_angles->h -= frame_turn; + + return mask; +} + +stop_endlevel_sequence() +{ + Interpolation_method = 0; + + gr_palette_fade_out(gr_palette, 32, 0); + + select_cockpit(cockpit_mode_save); + + Endlevel_sequence = EL_OFF; + + PlayerFinishedLevel(0); + +} + +#define VCLIP_BIG_PLAYER_EXPLOSION 58 + +//--unused-- vms_vector upvec = {0,f1_0,0}; + +//find the angle between the player's heading & the station +get_angs_to_object(vms_angvec *av,vms_vector *targ_pos,vms_vector *cur_pos) +{ + vms_vector tv; + + vm_vec_sub(&tv,targ_pos,cur_pos); + + vm_extract_angles_vector(av,&tv); +} + +do_endlevel_frame() +{ + #ifdef SHAREWARE + static fix timer; + static fix bank_rate; + #endif + vms_vector save_last_pos; + static fix explosion_wait1=0; + static fix explosion_wait2=0; + static fix ext_expl_halflife; + + save_last_pos = ConsoleObject->last_pos; //don't let move code change this + object_move_all(); + ConsoleObject->last_pos = save_last_pos; + + if (ext_expl_playing) { + + external_explosion.lifeleft -= FrameTime; + do_explosion_sequence(&external_explosion); + + if (external_explosion.lifeleft < ext_expl_halflife) + mine_destroyed = 1; + + if (external_explosion.flags & OF_SHOULD_BE_DEAD) + ext_expl_playing = 0; + } + + if (cur_fly_speed != desired_fly_speed) { + fix delta = desired_fly_speed - cur_fly_speed; + fix frame_accel = fixmul(FrameTime,FLY_ACCEL); + + if (abs(delta) < frame_accel) + cur_fly_speed = desired_fly_speed; + else + if (delta > 0) + cur_fly_speed += frame_accel; + else + cur_fly_speed -= frame_accel; + } + + //do big explosions + if (!outside_mine) { + + if (Endlevel_sequence==EL_OUTSIDE) { + vms_vector tvec; + + vm_vec_sub(&tvec,&ConsoleObject->pos,&mine_side_exit_point); + + if (vm_vec_dot(&tvec,&mine_exit_orient.fvec) > 0) { + object *tobj; + + outside_mine = 1; + + tobj = object_create_explosion(exit_segnum,&mine_side_exit_point,i2f(50),VCLIP_BIG_PLAYER_EXPLOSION); + + if (tobj) { + external_explosion = *tobj; + + tobj->flags |= OF_SHOULD_BE_DEAD; + + flash_scale = 0; //kill lights in mine + + ext_expl_halflife = tobj->lifeleft; + + ext_expl_playing = 1; + } + + digi_link_sound_to_pos( SOUND_BIG_ENDLEVEL_EXPLOSION, exit_segnum, 0, &mine_side_exit_point, 0, i2f(3)/4 ); + } + } + + //do explosions chasing player + if ((explosion_wait1-=FrameTime) < 0) { + vms_vector tpnt; + int segnum; + object *expl; + static int sound_count; + + vm_vec_scale_add(&tpnt,&ConsoleObject->pos,&ConsoleObject->orient.fvec,-ConsoleObject->size*5); + vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.rvec,(d_rand()-RAND_MAX/2)*15); + vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.uvec,(d_rand()-RAND_MAX/2)*15); + + segnum = find_point_seg(&tpnt,ConsoleObject->segnum); + + if (segnum != -1) { + expl = object_create_explosion(segnum,&tpnt,i2f(20),VCLIP_BIG_PLAYER_EXPLOSION); + if (d_rand()<10000 || ++sound_count==7) { //pseudo-random + digi_link_sound_to_pos( SOUND_TUNNEL_EXPLOSION, segnum, 0, &tpnt, 0, F1_0 ); + sound_count=0; + } + } + + explosion_wait1 = 0x2000 + d_rand()/4; + + } + } + + //do little explosions on walls + if (Endlevel_sequence >= EL_FLYTHROUGH && Endlevel_sequence < EL_OUTSIDE) + if ((explosion_wait2-=FrameTime) < 0) { + vms_vector tpnt; + fvi_query fq; + fvi_info hit_data; + + //create little explosion on wall + + vm_vec_copy_scale(&tpnt,&ConsoleObject->orient.rvec,(d_rand()-RAND_MAX/2)*100); + vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.uvec,(d_rand()-RAND_MAX/2)*100); + vm_vec_add2(&tpnt,&ConsoleObject->pos); + + if (Endlevel_sequence == EL_FLYTHROUGH) + vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.fvec,d_rand()*200); + else + vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.fvec,d_rand()*60); + + //find hit point on wall + + fq.p0 = &ConsoleObject->pos; + fq.p1 = &tpnt; + fq.startseg = ConsoleObject->segnum; + fq.rad = 0; + fq.thisobjnum = 0; + fq.ignore_obj_list = NULL; + fq.flags = 0; + + find_vector_intersection(&fq,&hit_data); + + if (hit_data.hit_type==HIT_WALL && hit_data.hit_seg!=-1) + object_create_explosion(hit_data.hit_seg,&hit_data.hit_pnt,i2f(3)+d_rand()*6,VCLIP_SMALL_EXPLOSION); + + explosion_wait2 = (0xa00 + d_rand()/8)/2; + } + + switch (Endlevel_sequence) { + + case EL_OFF: return; + + case EL_FLYTHROUGH: { + + do_endlevel_flythrough(0); + + if (ConsoleObject->segnum == transition_segnum) { + + #ifndef SHAREWARE + start_endlevel_movie(); + stop_endlevel_sequence(); + #else + + int objnum; + + //songs_play_song( SONG_ENDLEVEL, 0 ); + + Endlevel_sequence = EL_LOOKBACK; + + objnum = obj_create(OBJ_CAMERA, 0, + ConsoleObject->segnum,&ConsoleObject->pos,&ConsoleObject->orient,0, + CT_NONE,MT_NONE,RT_NONE); + + if (objnum == -1) { //can't get object, so abort + mprintf((1, "Can't get object for endlevel sequence. Aborting endlevel sequence.\n")); + stop_endlevel_sequence(); + return; + } + + Viewer = endlevel_camera = &Objects[objnum]; + + select_cockpit(CM_LETTERBOX); + + fly_objects[1] = fly_objects[0]; + fly_objects[1].obj = endlevel_camera; + fly_objects[1].speed = (5*cur_fly_speed)/4; + fly_objects[1].offset_frac = 0x4000; + + vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.fvec,i2f(7)); + + timer=0x20000; + + #endif + } + + break; + } + + +#ifdef SHAREWARE + case EL_LOOKBACK: { + + do_endlevel_flythrough(0); + do_endlevel_flythrough(1); + + if (timer>0) { + + timer -= FrameTime; + + if (timer < 0) //reduce speed + fly_objects[1].speed = fly_objects[0].speed; + } + + if (endlevel_camera->segnum == exit_segnum) { + vms_angvec cam_angles,exit_seg_angles; + + Endlevel_sequence = EL_OUTSIDE; + + timer = i2f(2); + + vm_vec_negate(&endlevel_camera->orient.fvec); + vm_vec_negate(&endlevel_camera->orient.rvec); + + vm_extract_angles_matrix(&cam_angles,&endlevel_camera->orient); + vm_extract_angles_matrix(&exit_seg_angles,&mine_exit_orient); + bank_rate = (-exit_seg_angles.b - cam_angles.b)/2; + + ConsoleObject->control_type = endlevel_camera->control_type = CT_NONE; + +#ifdef SLEW_ON + slew_obj = endlevel_camera; +#endif + } + + break; + } + + case EL_OUTSIDE: { + #ifndef SLEW_ON + vms_angvec cam_angles; + #endif + + vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed)); +#ifndef SLEW_ON + vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.fvec,fixmul(FrameTime,-2*cur_fly_speed)); + vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.uvec,fixmul(FrameTime,-cur_fly_speed/10)); + + vm_extract_angles_matrix(&cam_angles,&endlevel_camera->orient); + cam_angles.b += fixmul(bank_rate,FrameTime); + vm_angles_2_matrix(&endlevel_camera->orient,&cam_angles); +#endif + + timer -= FrameTime; + + if (timer < 0) { + + Endlevel_sequence = EL_STOPPED; + + vm_extract_angles_matrix(&player_angles,&ConsoleObject->orient); + + timer = i2f(3); + + } + + break; + } + + case EL_STOPPED: { + + get_angs_to_object(&player_dest_angles,&station_pos,&ConsoleObject->pos); + chase_angles(&player_angles,&player_dest_angles); + vm_angles_2_matrix(&ConsoleObject->orient,&player_angles); + + vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed)); + + timer -= FrameTime; + + if (timer < 0) { + + #ifdef SLEW_ON + slew_obj = endlevel_camera; + _do_slew_movement(endlevel_camera,1,1); + timer += FrameTime; //make time stop + break; + #else + + #ifdef SHORT_SEQUENCE + + stop_endlevel_sequence(); + + #else + Endlevel_sequence = EL_PANNING; + + vm_extract_angles_matrix(&camera_cur_angles,&endlevel_camera->orient); + + + timer = i2f(3); + + if (Game_mode & GM_MULTI) { // try to skip part of the seq if multiplayer + stop_endlevel_sequence(); + return; + } + + //mprintf((0,"Switching to pan...\n")); + #endif //SHORT_SEQUENCE + #endif //SLEW_ON + + } + break; + } + + #ifndef SHORT_SEQUENCE + case EL_PANNING: { + #ifndef SLEW_ON + int mask; + #endif + + get_angs_to_object(&player_dest_angles,&station_pos,&ConsoleObject->pos); + chase_angles(&player_angles,&player_dest_angles); + vm_angles_2_matrix(&ConsoleObject->orient,&player_angles); + vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed)); + + #ifdef SLEW_ON + _do_slew_movement(endlevel_camera,1,1); + #else + + get_angs_to_object(&camera_desired_angles,&ConsoleObject->pos,&endlevel_camera->pos); + mask = chase_angles(&camera_cur_angles,&camera_desired_angles); + vm_angles_2_matrix(&endlevel_camera->orient,&camera_cur_angles); + + if ((mask&5) == 5) { + + vms_vector tvec; + + Endlevel_sequence = EL_CHASING; + + vm_vec_normalized_dir_quick(&tvec,&station_pos,&ConsoleObject->pos); + vm_vector_2_matrix(&ConsoleObject->orient,&tvec,&surface_orient.uvec,NULL); + + desired_fly_speed *= 2; + + //mprintf((0,"Switching to chase...\n")); + + } + #endif + + break; + } + + case EL_CHASING: { + fix d,speed_scale; + + #ifdef SLEW_ON + _do_slew_movement(endlevel_camera,1,1); + #endif + + get_angs_to_object(&camera_desired_angles,&ConsoleObject->pos,&endlevel_camera->pos); + chase_angles(&camera_cur_angles,&camera_desired_angles); + + #ifndef SLEW_ON + vm_angles_2_matrix(&endlevel_camera->orient,&camera_cur_angles); + #endif + + d = vm_vec_dist_quick(&ConsoleObject->pos,&endlevel_camera->pos); + + speed_scale = fixdiv(d,i2f(0x20)); + if (dpos); + chase_angles(&player_angles,&player_dest_angles); + vm_angles_2_matrix(&ConsoleObject->orient,&player_angles); + + vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed)); + #ifndef SLEW_ON + vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.fvec,fixmul(FrameTime,fixmul(speed_scale,cur_fly_speed))); + + if (vm_vec_dist(&ConsoleObject->pos,&station_pos) < i2f(10)) + stop_endlevel_sequence(); + #endif + + break; + + } + #endif //ifdef SHORT_SEQUENCE +#endif + + } +} + + +#define MIN_D 0x100 + +//find which side to fly out of +find_exit_side(object *obj) +{ + int i; + vms_vector prefvec,segcenter,sidevec; + fix best_val=-f2_0; + int best_side; + segment *pseg = &Segments[obj->segnum]; + + //find exit side + + vm_vec_normalized_dir_quick(&prefvec,&obj->pos,&obj->last_pos); + + compute_segment_center(&segcenter,pseg); + + best_side=-1; + for (i=MAX_SIDES_PER_SEGMENT;--i >= 0;) { + fix d; + + if (pseg->children[i]!=-1) { + + compute_center_point_on_side(&sidevec,pseg,i); + vm_vec_normalized_dir_quick(&sidevec,&sidevec,&segcenter); + d = vm_vec_dotprod(&sidevec,&prefvec); + + if (labs(d) < MIN_D) d=0; + + if (d > best_val) {best_val=d; best_side=i;} + + } + } + + Assert(best_side!=-1); + + return best_side; +} + +extern fix Render_zoom; //the player's zoom factor + +extern vms_vector Viewer_eye; //valid during render + +draw_exit_model() +{ + vms_vector model_pos; + int f=15,u=0; //21; + + vm_vec_scale_add(&model_pos,&mine_exit_point,&mine_exit_orient.fvec,i2f(f)); + vm_vec_scale_add2(&model_pos,&mine_exit_orient.uvec,i2f(u)); + + draw_polygon_model(&model_pos,&mine_exit_orient,NULL,(mine_destroyed)?destroyed_exit_modelnum:exit_modelnum,0,f1_0,NULL,NULL); + +} + +int exit_point_bmx,exit_point_bmy; + +fix satellite_size = i2f(400); + +#define SATELLITE_DIST i2f(1024) +#define SATELLITE_WIDTH satellite_size +#define SATELLITE_HEIGHT ((satellite_size*9)/4) //((satellite_size*5)/2) + +render_external_scene(fix eye_offset) +{ + + Viewer_eye = Viewer->pos; + + if (eye_offset) + vm_vec_scale_add2(&Viewer_eye,&Viewer->orient.rvec,eye_offset); + + g3_set_view_matrix(&Viewer->pos,&Viewer->orient,Render_zoom); + + //g3_draw_horizon(BM_XRGB(0,0,0),BM_XRGB(16,16,16)); //,-1); + gr_clear_canvas(BM_XRGB(0,0,0)); + + g3_start_instance_matrix(&vmd_zero_vector,&surface_orient); + draw_stars(); + g3_done_instance(); + + { //draw satellite + + vms_vector delta; + g3s_point p,top_pnt; + + g3_rotate_point(&p,&satellite_pos); + g3_rotate_delta_vec(&delta,&satellite_upvec); + + g3_add_delta_vec(&top_pnt,&p,&delta); + + if (! (p.p3_codes & CC_BEHIND)) { + int save_im = Interpolation_method; + //p.p3_flags &= ~PF_PROJECTED; + //g3_project_point(&p); + if (! (p.p3_flags & PF_OVERFLOW)) { + Interpolation_method = 0; + //gr_bitmapm(f2i(p.p3_sx)-32,f2i(p.p3_sy)-32,satellite_bitmap); + g3_draw_rod_tmap(satellite_bitmap,&p,SATELLITE_WIDTH,&top_pnt,SATELLITE_WIDTH,f1_0); + Interpolation_method = save_im; + } + } + } + + #ifdef STATION_ENABLED + draw_polygon_model(&station_pos,&vmd_identity_matrix,NULL,station_modelnum,0,f1_0,NULL,NULL); + #endif + + render_terrain(&mine_ground_exit_point,exit_point_bmx,exit_point_bmy); + + draw_exit_model(); + if (ext_expl_playing) + draw_fireball(&external_explosion); + + Lighting_on=0; + render_object(ConsoleObject); + Lighting_on=1; +} + +#define MAX_STARS 500 + +vms_vector stars[MAX_STARS]; + +generate_starfield() +{ + int i; + + for (i=0;ipos; + + if (Viewer->type == OBJ_PLAYER ) + vm_vec_scale_add2(&Viewer_eye,&Viewer->orient.fvec,(Viewer->size*3)/4); + + if (eye_offset) + vm_vec_scale_add2(&Viewer_eye,&Viewer->orient.rvec,eye_offset); + + #ifdef EDITOR + if (Function_mode==FMODE_EDITOR) + Viewer_eye = Viewer->pos; + #endif + + if (Endlevel_sequence >= EL_OUTSIDE) { + + start_seg_num = exit_segnum; + } + else { + start_seg_num = find_point_seg(&Viewer_eye,Viewer->segnum); + + if (start_seg_num==-1) + start_seg_num = Viewer->segnum; + } + + if (Endlevel_sequence == EL_LOOKBACK) { + vms_matrix headm,viewm; + vms_angvec angles = {0,0,0x7fff}; + + vm_angles_2_matrix(&headm,&angles); + vm_matrix_x_matrix(&viewm,&Viewer->orient,&headm); + g3_set_view_matrix(&Viewer_eye,&viewm,Render_zoom); + } + else + g3_set_view_matrix(&Viewer_eye,&Viewer->orient,Render_zoom); + + render_mine(start_seg_num,eye_offset, 0); +} + +void render_endlevel_frame(fix eye_offset) +{ + + g3_start_frame(); + + if (Endlevel_sequence < EL_OUTSIDE) + endlevel_render_mine(eye_offset); + #ifdef SHAREWARE + else + render_external_scene(eye_offset); + #endif + + g3_end_frame(); + +} + + +///////////////////////// copy of flythrough code for endlevel + + +#define MAX_FLY_OBJECTS 2 + +flythrough_data fly_objects[MAX_FLY_OBJECTS]; + +flythrough_data *flydata; + +int matt_find_connect_side(int seg0,int seg1); + +void compute_segment_center(vms_vector *vp,segment *sp); + +fixang delta_ang(fixang a,fixang b); +fixang interp_angle(fixang dest,fixang src,fixang step); + +#define DEFAULT_SPEED i2f(16) + +#define MIN_D 0x100 + +//if speed is zero, use default speed +start_endlevel_flythrough(int n,object *obj,fix speed) +{ + flydata = &fly_objects[n]; + + flydata->obj = obj; + + flydata->first_time = 1; + + flydata->speed = speed?speed:DEFAULT_SPEED; + + flydata->offset_frac = 0; +} + +static vms_angvec *angvec_add2_scale(vms_angvec *dest,vms_vector *src,fix s) +{ + dest->p += fixmul(src->x,s); + dest->b += fixmul(src->z,s); + dest->h += fixmul(src->y,s); + + return dest; +} + +#define MAX_ANGSTEP 0x4000 //max turn per second + +#define MAX_SLIDE_PER_SEGMENT 0x10000 + +do_endlevel_flythrough(int n) +{ + object *obj; + segment *pseg; + int old_player_seg; + + flydata = &fly_objects[n]; + obj = flydata->obj; + + old_player_seg = obj->segnum; + + //move the player for this frame + + if (!flydata->first_time) { + + vm_vec_scale_add2(&obj->pos,&flydata->step,FrameTime); + angvec_add2_scale(&flydata->angles,&flydata->angstep,FrameTime); + + vm_angles_2_matrix(&obj->orient,&flydata->angles); + } + + //check new player seg + + update_object_seg(obj); + pseg = &Segments[obj->segnum]; + + if (flydata->first_time || obj->segnum != old_player_seg) { //moved into new seg + vms_vector curcenter,nextcenter; + fix step_size,seg_time; + short entry_side,exit_side; //what sides we entry and leave through + vms_vector dest_point; //where we are heading (center of exit_side) + vms_angvec dest_angles; //where we want to be pointing + vms_matrix dest_orient; + int up_side; + + //find new exit side + + if (!flydata->first_time) { + + entry_side = matt_find_connect_side(obj->segnum,old_player_seg); + exit_side = Side_opposite[entry_side]; + } + + if (flydata->first_time || entry_side==-1 || pseg->children[exit_side]==-1) + exit_side = find_exit_side(obj); + + { //find closest side to align to + fix d,largest_d=-f1_0; + int i; + + for (i=0;i<6;i++) { + #ifdef COMPACT_SEGS + vms_vector v1; + get_side_normal(pseg, i, 0, &v1 ); + d = vm_vec_dot(&v1,&flydata->obj->orient.uvec); + #else + d = vm_vec_dot(&pseg->sides[i].normals[0],&flydata->obj->orient.uvec); + #endif + if (d > largest_d) {largest_d = d; up_side=i;} + } + + } + + //update target point & angles + + compute_center_point_on_side(&dest_point,pseg,exit_side); + + //update target point and movement points + + //offset object sideways + if (flydata->offset_frac) { + int s0=-1,s1,i; + vms_vector s0p,s1p; + fix dist; + + for (i=0;i<6;i++) + if (i!=entry_side && i!=exit_side && i!=up_side && i!=Side_opposite[up_side]) + if (s0==-1) + s0 = i; + else + s1 = i; + + compute_center_point_on_side(&s0p,pseg,s0); + compute_center_point_on_side(&s1p,pseg,s1); + dist = fixmul(vm_vec_dist(&s0p,&s1p),flydata->offset_frac); + + if (dist-flydata->offset_dist > MAX_SLIDE_PER_SEGMENT) + dist = flydata->offset_dist + MAX_SLIDE_PER_SEGMENT; + + flydata->offset_dist = dist; + + vm_vec_scale_add2(&dest_point,&obj->orient.rvec,dist); + + } + + vm_vec_sub(&flydata->step,&dest_point,&obj->pos); + step_size = vm_vec_normalize_quick(&flydata->step); + vm_vec_scale(&flydata->step,flydata->speed); + + compute_segment_center(&curcenter,pseg); + compute_segment_center(&nextcenter,&Segments[pseg->children[exit_side]]); + vm_vec_sub(&flydata->headvec,&nextcenter,&curcenter); + + #ifdef COMPACT_SEGS + { + vms_vector _v1; + get_side_normal(pseg, up_side, 0, &_v1 ); + vm_vector_2_matrix(&dest_orient,&flydata->headvec,&_v1,NULL); + } + #else + vm_vector_2_matrix(&dest_orient,&flydata->headvec,&pseg->sides[up_side].normals[0],NULL); + #endif + vm_extract_angles_matrix(&dest_angles,&dest_orient); + + if (flydata->first_time) + vm_extract_angles_matrix(&flydata->angles,&obj->orient); + + seg_time = fixdiv(step_size,flydata->speed); //how long through seg + + if (seg_time) { + flydata->angstep.x = max(-MAX_ANGSTEP,min(MAX_ANGSTEP,fixdiv(delta_ang(flydata->angles.p,dest_angles.p),seg_time))); + flydata->angstep.z = max(-MAX_ANGSTEP,min(MAX_ANGSTEP,fixdiv(delta_ang(flydata->angles.b,dest_angles.b),seg_time))); + flydata->angstep.y = max(-MAX_ANGSTEP,min(MAX_ANGSTEP,fixdiv(delta_ang(flydata->angles.h,dest_angles.h),seg_time))); + + } + else { + flydata->angles = dest_angles; + flydata->angstep.x = flydata->angstep.y = flydata->angstep.z = 0; + } + } + + flydata->first_time=0; +} + +#define JOY_NULL 15 +#define ROT_SPEED 8 //rate of rotation while key held down +#define VEL_SPEED (15) //rate of acceleration while key held down + +extern short old_joy_x,old_joy_y; //position last time around + +#include "key.h" +#include "joy.h" + +#ifdef SLEW_ON //this is a special routine for slewing around external scene +int _do_slew_movement(object *obj, int check_keys, int check_joy ) +{ + int moved = 0; + vms_vector svel, movement; //scaled velocity (per this frame) + vms_matrix rotmat,new_pm; + int joy_x,joy_y,btns; + int joyx_moved,joyy_moved; + vms_angvec rotang; + + if (keyd_pressed[KEY_PAD5]) + vm_vec_zero(&obj->phys_info.velocity); + + if (check_keys) { + obj->phys_info.velocity.x += VEL_SPEED * (key_down_time(KEY_PAD9) - key_down_time(KEY_PAD7)); + obj->phys_info.velocity.y += VEL_SPEED * (key_down_time(KEY_PADMINUS) - key_down_time(KEY_PADPLUS)); + obj->phys_info.velocity.z += VEL_SPEED * (key_down_time(KEY_PAD8) - key_down_time(KEY_PAD2)); + + rotang.pitch = (key_down_time(KEY_LBRACKET) - key_down_time(KEY_RBRACKET))/ROT_SPEED; + rotang.bank = (key_down_time(KEY_PAD1) - key_down_time(KEY_PAD3))/ROT_SPEED; + rotang.head = (key_down_time(KEY_PAD6) - key_down_time(KEY_PAD4))/ROT_SPEED; + } + else + rotang.pitch = rotang.bank = rotang.head = 0; + + //check for joystick movement + + if (check_joy && joy_present) { + joy_get_pos(&joy_x,&joy_y); + btns=joy_get_btns(); + + joyx_moved = (abs(joy_x - old_joy_x)>JOY_NULL); + joyy_moved = (abs(joy_y - old_joy_y)>JOY_NULL); + + if (abs(joy_x) < JOY_NULL) joy_x = 0; + if (abs(joy_y) < JOY_NULL) joy_y = 0; + + if (btns) + if (!rotang.pitch) rotang.pitch = fixmul(-joy_y * 512,FrameTime); else; + else + if (joyy_moved) obj->phys_info.velocity.z = -joy_y * 8192; + + if (!rotang.head) rotang.head = fixmul(joy_x * 512,FrameTime); + + if (joyx_moved) old_joy_x = joy_x; + if (joyy_moved) old_joy_y = joy_y; + } + + moved = rotang.pitch | rotang.bank | rotang.head; + + vm_angles_2_matrix(&rotmat,&rotang); + vm_matrix_x_matrix(&new_pm,&obj->orient,&rotmat); + obj->orient = new_pm; + vm_transpose_matrix(&new_pm); //make those columns rows + + moved |= obj->phys_info.velocity.x | obj->phys_info.velocity.y | obj->phys_info.velocity.z; + + svel = obj->phys_info.velocity; + vm_vec_scale(&svel,FrameTime); //movement in this frame + vm_vec_rotate(&movement,&svel,&new_pm); + + vm_vec_add2(&obj->pos,&movement); + + moved |= (movement.x || movement.y || movement.z); + + return moved; +} +#endif + +#define LINE_LEN 80 +#define NUM_VARS 8 + +#define STATION_DIST i2f(1024) + +int convert_ext( char *dest, char *ext ) +{ + char *t; + + t = strchr(dest,'.'); + + if (t && (t-dest <= 8)) { + t[1] = ext[0]; + t[2] = ext[1]; + t[3] = ext[2]; + return 1; + } + else + return 0; +} + +//called for each level to load & setup the exit sequence +load_endlevel_data(int level_num) +{ + char filename[13]; + char line[LINE_LEN],*p; + CFILE *ifile; + int var,segnum,sidenum; + int exit_side, i; + int have_binary = 0; + + endlevel_data_loaded = 0; //not loaded yet + +try_again: + ; + + if (level_num<0) //secret level + strcpy(filename,Secret_level_names[-level_num-1]); + else //normal level + strcpy(filename,Level_names[level_num-1]); + + if (!convert_ext(filename,"END")) + Error("Error converting filename <%s> for endlevel data\n",filename); + + ifile = cfopen(filename,"rb"); + + if (!ifile) { + + convert_ext(filename,"TXB"); + + ifile = cfopen(filename,"rb"); + + if (!ifile) + if (level_num==1) { + Error("Cannot load file text of binary version of <%s>",filename); + } + else { + level_num = 1; + goto try_again; + } + + have_binary = 1; + } + + //ok...this parser is pretty simple. It ignores comments, but + //everything else must be in the right place + + var = 0; + + while (cfgets(line,LINE_LEN,ifile)) { + + if (have_binary) { + for (i = 0; i < strlen(line) - 1; i++) { + encode_rotate_left(&(line[i])); + line[i] = line[i] ^ BITMAP_TBL_XOR; + encode_rotate_left(&(line[i])); + } + p = line; + } + + if ((p=strchr(line,';'))!=NULL) + *p = 0; //cut off comment + + for (p=line+strlen(line)-1;p>line && isspace(*p);*p--=0); + for (p=line;isspace(*p);p++); + + if (!*p) //empty line + continue; + + switch (var) { + + case 0: { //ground terrain + int iff_error, i; + ubyte pal[768]; + + if (terrain_bm_instance.bm_data) + d_free(terrain_bm_instance.bm_data); + + Assert(terrain_bm_instance.bm_data == NULL); + + iff_error = iff_read_bitmap(p,&terrain_bm_instance,BM_LINEAR,pal); + if (iff_error != IFF_NO_ERROR) { + mprintf((1, "File %s - IFF error: %s",p,iff_errormsg(iff_error))); + Error("File %s - IFF error: %s",p,iff_errormsg(iff_error)); + } + + terrain_bitmap = &terrain_bm_instance; + + gr_remap_bitmap_good( terrain_bitmap, pal, iff_transparent_color, -1); + + break; + } + + case 1: //height map + + load_terrain(p); + break; + + + case 2: + + sscanf(p,"%d,%d",&exit_point_bmx,&exit_point_bmy); + break; + + case 3: //exit heading + + exit_angles.h = i2f(atoi(p))/360; + break; + + case 4: { //planet bitmap + int iff_error; + ubyte pal[768]; + + if (satellite_bm_instance.bm_data) + d_free(satellite_bm_instance.bm_data); + + iff_error = iff_read_bitmap(p,&satellite_bm_instance,BM_LINEAR,pal); + if (iff_error != IFF_NO_ERROR) { + mprintf((1, "File %s - IFF error: %s",p,iff_errormsg(iff_error))); + Error("File %s - IFF error: %s",p,iff_errormsg(iff_error)); + } + + satellite_bitmap = &satellite_bm_instance; + gr_remap_bitmap_good( satellite_bitmap, pal, iff_transparent_color, -1); + + break; + } + + case 5: //earth pos + case 7: { //station pos + vms_matrix tm; + vms_angvec ta; + int pitch,head; + + sscanf(p,"%d,%d",&head,&pitch); + + ta.h = i2f(head)/360; + ta.p = -i2f(pitch)/360; + ta.b = 0; + + vm_angles_2_matrix(&tm,&ta); + + if (var==5) + satellite_pos = tm.fvec; + //vm_vec_copy_scale(&satellite_pos,&tm.fvec,SATELLITE_DIST); + else + station_pos = tm.fvec; + + break; + } + + case 6: //planet size + satellite_size = i2f(atoi(p)); + break; + } + + var++; + + } + + Assert(var == NUM_VARS); + + + // OK, now the data is loaded. Initialize everything + + //find the exit sequence by searching all segments for a side with + //children == -2 + + for (segnum=0,exit_segnum=-1;exit_segnum==-1 && segnum<=Highest_segment_index;segnum++) + for (sidenum=0;sidenum<6;sidenum++) + if (Segments[segnum].children[sidenum] == -2) { + exit_segnum = segnum; + exit_side = sidenum; + break; + } + + Assert(exit_segnum!=-1); + + compute_segment_center(&mine_exit_point,&Segments[exit_segnum]); + extract_orient_from_segment(&mine_exit_orient,&Segments[exit_segnum]); + compute_center_point_on_side(&mine_side_exit_point,&Segments[exit_segnum],exit_side); + + vm_vec_scale_add(&mine_ground_exit_point,&mine_exit_point,&mine_exit_orient.uvec,-i2f(20)); + + //compute orientation of surface + { + vms_vector tv; + vms_matrix exit_orient,tm; + + vm_angles_2_matrix(&exit_orient,&exit_angles); + vm_transpose_matrix(&exit_orient); + vm_matrix_x_matrix(&surface_orient,&mine_exit_orient,&exit_orient); + + vm_copy_transpose_matrix(&tm,&surface_orient); + vm_vec_rotate(&tv,&station_pos,&tm); + vm_vec_scale_add(&station_pos,&mine_exit_point,&tv,STATION_DIST); + +vm_vec_rotate(&tv,&satellite_pos,&tm); +vm_vec_scale_add(&satellite_pos,&mine_exit_point,&tv,SATELLITE_DIST); + +vm_vector_2_matrix(&tm,&tv,&surface_orient.uvec,NULL); +vm_vec_copy_scale(&satellite_upvec,&tm.uvec,SATELLITE_HEIGHT); + + + } + + cfclose(ifile); + + endlevel_data_loaded = 1; + +} + +#endif + diff --git a/main/endlevel.h b/main/endlevel.h new file mode 100644 index 00000000..08d44dbc --- /dev/null +++ b/main/endlevel.h @@ -0,0 +1,47 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + + +#ifndef _OUTSIDE_H +#define _OUTSIDE_H + +#include "object.h" + +extern int Endlevel_sequence; +void do_endlevel_frame(); +void stop_endlevel_sequence(); +void start_endlevel_sequence(); +void render_endlevel_frame(fix eye_offset); + +#ifdef SHAREWARE + +render_external_scene(); +draw_exit_model(); +init_endlevel(); + +extern grs_bitmap *terrain_bitmap; //*satellite_bitmap,*station_bitmap, +extern int exit_segnum; + +//@@extern vms_vector mine_exit_point; +//@@extern object external_explosion; +//@@extern int ext_expl_playing; + +//called for each level to load & setup the exit sequence +load_endlevel_data(int level_num); + +extern int exit_modelnum,destroyed_exit_modelnum; + +#endif + +#endif diff --git a/main/escort.c b/main/escort.c new file mode 100644 index 00000000..9c1fe75b --- /dev/null +++ b/main/escort.c @@ -0,0 +1,1976 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + + +#include +#include // for printf() +#include // for rand() and qsort() +#include // for memset() + +#include "inferno.h" +#include "mono.h" +#include "fix.h" +#include "vecmat.h" +#include "gr.h" +#include "3d.h" +#include "palette.h" + +#include "object.h" +#include "error.h" +#include "ai.h" +#include "robot.h" +#include "fvi.h" +#include "physics.h" +#include "wall.h" +#include "player.h" +#include "fireball.h" +#include "game.h" +#include "powerup.h" +#include "cntrlcen.h" +#include "gauges.h" +#include "key.h" +#include "fuelcen.h" +#include "sounds.h" +#include "screens.h" +#include "text.h" +#include "gamefont.h" +#include "newmenu.h" +#include "playsave.h" +#include "gameseq.h" +#include "automap.h" +#include "laser.h" +#include "pa_enabl.h" + +#ifdef EDITOR +#include "editor\editor.h" +#endif + +extern void multi_send_stolen_items(); +void say_escort_goal(int goal_num); +void show_escort_menu(char *msg); + + +char *Escort_goal_text[MAX_ESCORT_GOALS] = { + "BLUE KEY", + "YELLOW KEY", + "RED KEY", + "REACTOR", + "EXIT", + "ENERGY", + "ENERGYCEN", + "SHIELD", + "POWERUP", + "ROBOT", + "HOSTAGES", + "SPEW", + "SCRAM", + "EXIT", + "BOSS", + "MARKER 1", + "MARKER 2", + "MARKER 3", + "MARKER 4", + "MARKER 5", + "MARKER 6", + "MARKER 7", + "MARKER 8", + "MARKER 9", +// -- too much work -- "KAMIKAZE " +}; + +int Max_escort_length = 200; +int Escort_kill_object = -1; +ubyte Stolen_items[MAX_STOLEN_ITEMS]; +int Stolen_item_index; +fix Escort_last_path_created = 0; +int Escort_goal_object = ESCORT_GOAL_UNSPECIFIED, Escort_special_goal = -1, Escort_goal_index = -1, Buddy_messages_suppressed = 0; +fix Buddy_sorry_time; +int Buddy_objnum, Buddy_allowed_to_talk; +int Looking_for_marker; +int Last_buddy_key; + +fix Last_buddy_message_time; + +//if change this length, change in playsave.c also +#define GUIDEBOT_NAME_LEN 9 +char guidebot_name[GUIDEBOT_NAME_LEN+1] = "GUIDE-BOT"; +char real_guidebot_name[GUIDEBOT_NAME_LEN+1] = "GUIDE-BOT"; + +void init_buddy_for_level(void) +{ + int i; + + Buddy_allowed_to_talk = 0; + Buddy_objnum = -1; + Escort_goal_object = ESCORT_GOAL_UNSPECIFIED; + Escort_special_goal = -1; + Escort_goal_index = -1; + Buddy_messages_suppressed = 0; + + for (i=0; i<=Highest_object_index; i++) + if (Robot_info[Objects[i].id].companion) + break; + if (i <= Highest_object_index) + Buddy_objnum = i; + + Buddy_sorry_time = -F1_0; + + Looking_for_marker = -1; + Last_buddy_key = -1; +} + +// ----------------------------------------------------------------------------- +// See if segment from curseg through sidenum is reachable. +// Return true if it is reachable, else return false. +int segment_is_reachable(int curseg, int sidenum) +{ + int wall_num, rval; + segment *segp = &Segments[curseg]; + + if (!IS_CHILD(segp->children[sidenum])) + return 0; + + wall_num = segp->sides[sidenum].wall_num; + + // If no wall, then it is reachable + if (wall_num == -1) + return 1; + + rval = ai_door_is_openable(NULL, segp, sidenum); + + return rval; + +// -- MK, 10/17/95 -- +// -- MK, 10/17/95 -- // Hmm, a closed wall. I think this mean not reachable. +// -- MK, 10/17/95 -- if (Walls[wall_num].type == WALL_CLOSED) +// -- MK, 10/17/95 -- return 0; +// -- MK, 10/17/95 -- +// -- MK, 10/17/95 -- if (Walls[wall_num].type == WALL_DOOR) { +// -- MK, 10/17/95 -- if (Walls[wall_num].keys == KEY_NONE) { +// -- MK, 10/17/95 -- return 1; // @MK, 10/17/95: Be consistent with ai_door_is_openable +// -- MK, 10/17/95 -- // -- if (Walls[wall_num].flags & WALL_DOOR_LOCKED) +// -- MK, 10/17/95 -- // -- return 0; +// -- MK, 10/17/95 -- // -- else +// -- MK, 10/17/95 -- // -- return 1; +// -- MK, 10/17/95 -- } else if (Walls[wall_num].keys == KEY_BLUE) +// -- MK, 10/17/95 -- return (Players[Player_num].flags & PLAYER_FLAGS_BLUE_KEY); +// -- MK, 10/17/95 -- else if (Walls[wall_num].keys == KEY_GOLD) +// -- MK, 10/17/95 -- return (Players[Player_num].flags & PLAYER_FLAGS_GOLD_KEY); +// -- MK, 10/17/95 -- else if (Walls[wall_num].keys == KEY_RED) +// -- MK, 10/17/95 -- return (Players[Player_num].flags & PLAYER_FLAGS_RED_KEY); +// -- MK, 10/17/95 -- else +// -- MK, 10/17/95 -- Int3(); // Impossible! Doesn't have no key, but doesn't have any key! +// -- MK, 10/17/95 -- } else +// -- MK, 10/17/95 -- return 1; +// -- MK, 10/17/95 -- +// -- MK, 10/17/95 -- Int3(); // Hmm, thought 'if' above had to return! +// -- MK, 10/17/95 -- return 0; + +} + + +// ----------------------------------------------------------------------------- +// Create a breadth-first list of segments reachable from current segment. +// max_segs is maximum number of segments to search. Use MAX_SEGMENTS to search all. +// On exit, *length <= max_segs. +// Input: +// start_seg +// Output: +// bfs_list: array of shorts, each reachable segment. Includes start segment. +// length: number of elements in bfs_list +void create_bfs_list(int start_seg, short bfs_list[], int *length, int max_segs) +{ + int i, head, tail; + byte visited[MAX_SEGMENTS]; + + for (i=0; ichildren[i]; + + if (IS_CHILD(connected_seg) && (visited[connected_seg] == 0)) { + if (segment_is_reachable(curseg, i)) { + bfs_list[head++] = connected_seg; + if (head >= max_segs) + break; + visited[connected_seg] = 1; + Assert(head < MAX_SEGMENTS); + } + } + } + } + + *length = head; + +} + +// ----------------------------------------------------------------------------- +// Return true if ok for buddy to talk, else return false. +// Buddy is allowed to talk if the segment he is in does not contain a blastable wall that has not been blasted +// AND he has never yet, since being initialized for level, been allowed to talk. +int ok_for_buddy_to_talk(void) +{ + int i; + segment *segp; + + if (Objects[Buddy_objnum].type != OBJ_ROBOT) { + Buddy_allowed_to_talk = 0; + return 0; + } + + if (Buddy_allowed_to_talk) + return 1; + + if ((Objects[Buddy_objnum].type == OBJ_ROBOT) && (Buddy_objnum <= Highest_object_index) && !Robot_info[Objects[Buddy_objnum].id].companion) { + for (i=0; i<=Highest_object_index; i++) + if (Robot_info[Objects[i].id].companion) + break; + if (i > Highest_object_index) + return 0; + else + Buddy_objnum = i; + } + + segp = &Segments[Objects[Buddy_objnum].segnum]; + + for (i=0; isides[i].wall_num; + + if (wall_num != -1) { + if ((Walls[wall_num].type == WALL_BLASTABLE) && !(Walls[wall_num].flags & WALL_BLASTED)) + return 0; + } + + // Check one level deeper. + if (IS_CHILD(segp->children[i])) { + int j; + segment *csegp = &Segments[segp->children[i]]; + + for (j=0; jsides[j].wall_num; + + if (wall2 != -1) { + if ((Walls[wall2].type == WALL_BLASTABLE) && !(Walls[wall2].flags & WALL_BLASTED)) + return 0; + } + } + } + } + + Buddy_allowed_to_talk = 1; + return 1; +} + +// -------------------------------------------------------------------------------------------- +void detect_escort_goal_accomplished(int index) +{ + int i,j; + int detected = 0; + + if (!Buddy_allowed_to_talk) + return; + + // If goal is to go away, how can it be achieved? + if (Escort_special_goal == ESCORT_GOAL_SCRAM) + return; + +// See if goal found was a key. Need to handle default goals differently. +// Note, no buddy_met_goal sound when blow up reactor or exit. Not great, but ok +// since for reactor, noisy, for exit, buddy is disappearing. +if ((Escort_special_goal == -1) && (Escort_goal_index == index)) { + detected = 1; + goto dega_ok; +} + +if ((Escort_goal_index <= ESCORT_GOAL_RED_KEY) && (index >= 0)) { + if (Objects[index].type == OBJ_POWERUP) { + if (Objects[index].id == POW_KEY_BLUE) { + if (Escort_goal_index == ESCORT_GOAL_BLUE_KEY) { + detected = 1; + goto dega_ok; + } + } else if (Objects[index].id == POW_KEY_GOLD) { + if (Escort_goal_index == ESCORT_GOAL_GOLD_KEY) { + detected = 1; + goto dega_ok; + } + } else if (Objects[index].id == POW_KEY_RED) { + if (Escort_goal_index == ESCORT_GOAL_RED_KEY) { + detected = 1; + goto dega_ok; + } + } + } +} + if (Escort_special_goal != -1) + { + if (Escort_special_goal == ESCORT_GOAL_ENERGYCEN) { + if (index == -4) + detected = 1; + else { + for (i=0; i GameTime)) { + if (ok_for_buddy_to_talk()) { + char gb_str[16], new_format[128]; + va_list args; + int t; + + va_start(args, format ); + vsprintf(new_format, format, args); + va_end(args); + + gb_str[0] = 1; + gb_str[1] = BM_XRGB(28, 0, 0); + strcpy(&gb_str[2], guidebot_name); + t = strlen(gb_str); + gb_str[t] = ':'; + gb_str[t+1] = 1; + gb_str[t+2] = BM_XRGB(0, 31, 0); + gb_str[t+3] = 0; + + HUD_init_message("%s %s", gb_str, new_format); + + Last_buddy_message_time = GameTime; + } + } + +} + +// ----------------------------------------------------------------------------- +void thief_message(char * format, ... ) +{ + + char gb_str[16], new_format[128]; + va_list args; + + va_start(args, format ); + vsprintf(new_format, format, args); + va_end(args); + + gb_str[0] = 1; + gb_str[1] = BM_XRGB(28, 0, 0); + strcpy(&gb_str[2], "THIEF:"); + gb_str[8] = 1; + gb_str[9] = BM_XRGB(0, 31, 0); + gb_str[10] = 0; + + HUD_init_message("%s %s", gb_str, new_format); + +} + +// ----------------------------------------------------------------------------- +// Return true if marker #id has been placed. +int marker_exists_in_mine(int id) +{ + int i; + + for (i=0; i<=Highest_object_index; i++) + if (Objects[i].type == OBJ_MARKER) + if (Objects[i].id == id) + return 1; + + return 0; +} + +// ----------------------------------------------------------------------------- +void set_escort_special_goal(int special_key) +{ + int marker_key; + + Buddy_messages_suppressed = 0; + + if (!Buddy_allowed_to_talk) { + ok_for_buddy_to_talk(); + if (!Buddy_allowed_to_talk) { + int i; + + for (i=0; i<=Highest_object_index; i++) + if ((Objects[i].type == OBJ_ROBOT) && Robot_info[Objects[i].id].companion) { + HUD_init_message("%s has not been released.",guidebot_name); + break; + } + if (i == Highest_object_index+1) + HUD_init_message("No Guide-Bot in mine."); + + return; + } + } + + special_key = special_key & (~KEY_SHIFTED); + + marker_key = special_key; + + #ifdef MACINTOSH + switch(special_key) { + case KEY_5: + marker_key = KEY_1+4; + break; + case KEY_6: + marker_key = KEY_1+5; + break; + case KEY_7: + marker_key = KEY_1+6; + break; + case KEY_8: + marker_key = KEY_1+7; + break; + case KEY_9: + marker_key = KEY_1+8; + break; + case KEY_0: + marker_key = KEY_1+9; + break; + } + #endif + + if (Last_buddy_key == special_key) + { + if ((Looking_for_marker == -1) && (special_key != KEY_0)) { + if (marker_exists_in_mine(marker_key - KEY_1)) + Looking_for_marker = marker_key - KEY_1; + else { + Last_buddy_message_time = 0; // Force this message to get through. + buddy_message("Marker %i not placed.", marker_key - KEY_1 + 1); + Looking_for_marker = -1; + } + } else { + Looking_for_marker = -1; + } + } + + Last_buddy_key = special_key; + + if (special_key == KEY_0) + Looking_for_marker = -1; + + if ( Looking_for_marker != -1 ) { + Escort_special_goal = ESCORT_GOAL_MARKER1 + marker_key - KEY_1; + } else { + switch (special_key) { + case KEY_1: Escort_special_goal = ESCORT_GOAL_ENERGY; break; + case KEY_2: Escort_special_goal = ESCORT_GOAL_ENERGYCEN; break; + case KEY_3: Escort_special_goal = ESCORT_GOAL_SHIELD; break; + case KEY_4: Escort_special_goal = ESCORT_GOAL_POWERUP; break; + case KEY_5: Escort_special_goal = ESCORT_GOAL_ROBOT; break; + case KEY_6: Escort_special_goal = ESCORT_GOAL_HOSTAGE; break; + case KEY_7: Escort_special_goal = ESCORT_GOAL_SCRAM; break; + case KEY_8: Escort_special_goal = ESCORT_GOAL_PLAYER_SPEW; break; + case KEY_9: Escort_special_goal = ESCORT_GOAL_EXIT; break; + case KEY_0: Escort_special_goal = -1; break; + default: + Int3(); // Oops, called with illegal key value. + } + } + + Last_buddy_message_time = GameTime - 2*F1_0; // Allow next message to come through. + + say_escort_goal(Escort_special_goal); + // -- Escort_goal_object = escort_set_goal_object(); + + Escort_goal_object = ESCORT_GOAL_UNSPECIFIED; +} + +// -- old, pre-bfs, way -- // ----------------------------------------------------------------------------- +// -- old, pre-bfs, way -- // Return object of interest. +// -- old, pre-bfs, way -- int exists_in_mine(int objtype, int objid) +// -- old, pre-bfs, way -- { +// -- old, pre-bfs, way -- int i; +// -- old, pre-bfs, way -- +// -- old, pre-bfs, way -- mprintf((0, "exists_in_mine, type == %i, id == %i\n", objtype, objid)); +// -- old, pre-bfs, way -- +// -- old, pre-bfs, way -- if (objtype == FUELCEN_CHECK) { +// -- old, pre-bfs, way -- for (i=0; i<=Highest_segment_index; i++) +// -- old, pre-bfs, way -- if (Segments[i].special == SEGMENT_IS_FUELCEN) +// -- old, pre-bfs, way -- return i; +// -- old, pre-bfs, way -- } else { +// -- old, pre-bfs, way -- for (i=0; i<=Highest_object_index; i++) { +// -- old, pre-bfs, way -- if (Objects[i].type == objtype) { +// -- old, pre-bfs, way -- // Don't find escort robots if looking for robot! +// -- old, pre-bfs, way -- if ((Objects[i].type == OBJ_ROBOT) && (Robot_info[Objects[i].id].companion)) +// -- old, pre-bfs, way -- continue; +// -- old, pre-bfs, way -- +// -- old, pre-bfs, way -- if (objid == -1) { +// -- old, pre-bfs, way -- if ((objtype == OBJ_POWERUP) && (Objects[i].id != POW_KEY_BLUE) && (Objects[i].id != POW_KEY_GOLD) && (Objects[i].id != POW_KEY_RED)) +// -- old, pre-bfs, way -- return i; +// -- old, pre-bfs, way -- else +// -- old, pre-bfs, way -- return i; +// -- old, pre-bfs, way -- } else if (Objects[i].id == objid) +// -- old, pre-bfs, way -- return i; +// -- old, pre-bfs, way -- } +// -- old, pre-bfs, way -- } +// -- old, pre-bfs, way -- } +// -- old, pre-bfs, way -- +// -- old, pre-bfs, way -- return -1; +// -- old, pre-bfs, way -- +// -- old, pre-bfs, way -- } + +// ----------------------------------------------------------------------------- +// Return id of boss. +int get_boss_id(void) +{ + int i; + + for (i=0; i<=Highest_object_index; i++) + if (Objects[i].type == OBJ_ROBOT) + if (Robot_info[Objects[i].id].boss_flag) + return Objects[i].id; + + return -1; +} + +// ----------------------------------------------------------------------------- +// Return object index if object of objtype, objid exists in mine, else return -1 +// "special" is used to find objects spewed by player which is hacked into flags field of powerup. +int exists_in_mine_2(int segnum, int objtype, int objid, int special) +{ + if (Segments[segnum].objects != -1) { + int objnum = Segments[segnum].objects; + + while (objnum != -1) { + object *curobjp = &Objects[objnum]; + + if (special == ESCORT_GOAL_PLAYER_SPEW) { + if (curobjp->flags & OF_PLAYER_DROPPED) + return objnum; + } + + if (curobjp->type == objtype) { + // Don't find escort robots if looking for robot! + if ((curobjp->type == OBJ_ROBOT) && (Robot_info[curobjp->id].companion)) + ; + else if (objid == -1) { + if ((objtype == OBJ_POWERUP) && (curobjp->id != POW_KEY_BLUE) && (curobjp->id != POW_KEY_GOLD) && (curobjp->id != POW_KEY_RED)) + return objnum; + else + return objnum; + } else if (curobjp->id == objid) + return objnum; + } + + if (objtype == OBJ_POWERUP) + if (curobjp->contains_count) + if (curobjp->contains_type == OBJ_POWERUP) + if (curobjp->contains_id == objid) + return objnum; + + objnum = curobjp->next; + } + } + + return -1; +} + +// ----------------------------------------------------------------------------- +// Return nearest object of interest. +// If special == ESCORT_GOAL_PLAYER_SPEW, then looking for any object spewed by player. +// -1 means object does not exist in mine. +// -2 means object does exist in mine, but buddy-bot can't reach it (eg, behind triggered wall) +int exists_in_mine(int start_seg, int objtype, int objid, int special) +{ + int segindex, segnum; + short bfs_list[MAX_SEGMENTS]; + int length; + +// mprintf((0, "exists_in_mine, type == %i, id == %i\n", objtype, objid)); + + create_bfs_list(start_seg, bfs_list, &length, MAX_SEGMENTS); + + if (objtype == FUELCEN_CHECK) { + for (segindex=0; segindex