mirror of https://gitlab.com/nakst/essence
Merge branch 'doom' into 'master'
Doom Port See merge request nakst/essence!10
This commit is contained in:
commit
f94c0645e7
apps
doom.ini
doom
am_map.cam_map.hconfig.hd_englsh.hd_event.cd_event.hd_items.cd_items.hd_iwad.cd_iwad.hd_loop.cd_loop.hd_main.cd_main.hd_mode.cd_mode.hd_net.cd_player.hd_textur.hd_think.hd_ticcmd.hdoomdata.hdoomdef.hdoomkeys.hdoomstat.cdoomstat.hdoomtype.hdstrings.cdstrings.h
essence
f_finale.cf_finale.hf_wipe.cf_wipe.hg_game.cg_game.hgusconf.cgusconf.hhu_lib.chu_lib.hhu_stuff.chu_stuff.hi_input.ci_joystick.ci_joystick.hi_scale.ci_scale.hi_sound.ci_sound.hi_swap.hi_system.ci_system.hi_timer.ci_timer.hi_video.ci_video.hinfo.cinfo.hm_argv.cm_argv.hm_bbox.cm_bbox.hm_cheat.cm_cheat.hm_config.cm_config.hm_controls.cm_controls.hm_fixed.cm_fixed.hm_menu.cm_menu.hm_misc.cm_misc.hm_random.cm_random.hmemio.cmemio.hmus2mid.cmus2mid.hnet_client.cnet_client.hnet_dedicated.hnet_defs.hnet_gui.hnet_io.hnet_loop.hnet_packet.hnet_query.hnet_server.hp_ceilng.cp_doors.cp_enemy.cp_floor.cp_inter.cp_inter.h
|
@ -0,0 +1,11 @@
|
|||
[general]
|
||||
name=DOOM
|
||||
permission_all_files=1
|
||||
use_single_instance=1
|
||||
|
||||
[build]
|
||||
source=apps/doom/essence/main.c
|
||||
|
||||
[embed]
|
||||
$Icons/16=res/DOOM/icon16.png
|
||||
$Icons/32=res/DOOM/icon32.png
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// AutoMap module.
|
||||
//
|
||||
|
||||
#ifndef __AMMAP_H__
|
||||
#define __AMMAP_H__
|
||||
|
||||
#include "d_event.h"
|
||||
#include "m_cheat.h"
|
||||
|
||||
// Used by ST StatusBar stuff.
|
||||
#define AM_MSGHEADER (('a'<<24)+('m'<<16))
|
||||
#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8))
|
||||
#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8))
|
||||
|
||||
|
||||
// Called by main loop.
|
||||
boolean AM_Responder (event_t* ev);
|
||||
|
||||
// Called by main loop.
|
||||
void AM_Ticker (void);
|
||||
|
||||
// Called by main loop,
|
||||
// called instead of view drawer if automap active.
|
||||
void AM_Drawer (void);
|
||||
|
||||
// Called to force the automap to quit
|
||||
// if the level is completed while it is up.
|
||||
void AM_Stop (void);
|
||||
|
||||
|
||||
extern cheatseq_t cheat_amap;
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef __CONFIG__
|
||||
#define __CONFIG__
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "Doom Essence"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "Doom Essence 0.1"
|
||||
|
||||
/* Change this when you create your awesome forked version */
|
||||
#define PROGRAM_PREFIX "doomessence"
|
||||
|
||||
/* Enables multiplayer support (network games) */
|
||||
#undef FEATURE_MULTIPLAYER
|
||||
|
||||
/* Enables sound output */
|
||||
#undef FEATURE_SOUND
|
||||
|
||||
/* Enabled console debug */
|
||||
#undef FEATURE_CONSOLE
|
||||
|
||||
/* Define to the directory where all game files are located */
|
||||
#define FILES_DIR "|Settings:/WAD"
|
||||
|
||||
/* Define temporary directory path */
|
||||
#define TMP_DIR "|Settings:/TMP"
|
||||
|
||||
/* Define screen resolution */
|
||||
#define RES_X 640
|
||||
#define RES_Y 400
|
||||
|
||||
/* Define game configs */
|
||||
#define INITIAL_HEALTH 100
|
||||
#define INITIAL_BULLETS 50
|
||||
#define MAX_HEALTH 200
|
||||
#define MAX_ARMOR 200
|
||||
#define GREEN_ARMOR_CLASS 1
|
||||
#define BLUE_ARMOR_CLASS 2
|
||||
#define MAX_SOULSPHERE 200
|
||||
#define SOULSPHERE_HEALTH 100
|
||||
#define MEGASPHERE_HEALTH 200
|
||||
#define GOD_MODE_HEALTH 100
|
||||
#define IDFA_ARMOR 200
|
||||
#define IDFA_ARMOR_CLASS 2
|
||||
#define IDKFA_ARMOR 200
|
||||
#define IDKFA_ARMOR_CLASS 2
|
||||
#define BFG_CELLS_PER_SHOT 40
|
||||
#define SPECIES_INFIGHTING 0
|
||||
|
||||
#endif
|
|
@ -0,0 +1,693 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Printed strings for translation.
|
||||
// English language support (default).
|
||||
//
|
||||
|
||||
#ifndef __D_ENGLSH__
|
||||
#define __D_ENGLSH__
|
||||
|
||||
//
|
||||
// Printed strings for translation
|
||||
//
|
||||
|
||||
//
|
||||
// D_Main.C
|
||||
//
|
||||
#define D_DEVSTR "Development mode ON.\n"
|
||||
#define D_CDROM "CD-ROM Version: default.cfg from c:\\doomdata\n"
|
||||
|
||||
//
|
||||
// M_Menu.C
|
||||
//
|
||||
#define PRESSKEY "press a key."
|
||||
#define PRESSYN "press y or n."
|
||||
#define QUITMSG "are you sure you want to\nquit this great game?"
|
||||
#define LOADNET "you can't do load while in a net game!\n\n"PRESSKEY
|
||||
#define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY
|
||||
#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n"PRESSKEY
|
||||
#define SAVEDEAD "you can't save if you aren't playing!\n\n"PRESSKEY
|
||||
#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN
|
||||
#define QLPROMPT "do you want to quickload the game named\n\n'%s'?\n\n"PRESSYN
|
||||
|
||||
#define NEWGAME \
|
||||
"you can't start a new game\n"\
|
||||
"while in a network game.\n\n"PRESSKEY
|
||||
|
||||
#define NIGHTMARE \
|
||||
"are you sure? this skill level\n"\
|
||||
"isn't even remotely fair.\n\n"PRESSYN
|
||||
|
||||
#define SWSTRING \
|
||||
"this is the shareware version of doom.\n\n"\
|
||||
"you need to order the entire trilogy.\n\n"PRESSKEY
|
||||
|
||||
#define MSGOFF "Messages OFF"
|
||||
#define MSGON "Messages ON"
|
||||
#define NETEND "you can't end a netgame!\n\n"PRESSKEY
|
||||
#define ENDGAME "are you sure you want to end the game?\n\n"PRESSYN
|
||||
|
||||
#define DOSY "(press y to quit to essence.)"
|
||||
|
||||
#define DETAILHI "High detail"
|
||||
#define DETAILLO "Low detail"
|
||||
#define GAMMALVL0 "Gamma correction OFF"
|
||||
#define GAMMALVL1 "Gamma correction level 1"
|
||||
#define GAMMALVL2 "Gamma correction level 2"
|
||||
#define GAMMALVL3 "Gamma correction level 3"
|
||||
#define GAMMALVL4 "Gamma correction level 4"
|
||||
#define EMPTYSTRING "empty slot"
|
||||
|
||||
//
|
||||
// P_inter.C
|
||||
//
|
||||
#define GOTARMOR "Picked up the armor."
|
||||
#define GOTMEGA "Picked up the MegaArmor!"
|
||||
#define GOTHTHBONUS "Picked up a health bonus."
|
||||
#define GOTARMBONUS "Picked up an armor bonus."
|
||||
#define GOTSTIM "Picked up a stimpack."
|
||||
#define GOTMEDINEED "Picked up a medikit that you REALLY need!"
|
||||
#define GOTMEDIKIT "Picked up a medikit."
|
||||
#define GOTSUPER "Supercharge!"
|
||||
|
||||
#define GOTBLUECARD "Picked up a blue keycard."
|
||||
#define GOTYELWCARD "Picked up a yellow keycard."
|
||||
#define GOTREDCARD "Picked up a red keycard."
|
||||
#define GOTBLUESKUL "Picked up a blue skull key."
|
||||
#define GOTYELWSKUL "Picked up a yellow skull key."
|
||||
#define GOTREDSKULL "Picked up a red skull key."
|
||||
|
||||
#define GOTINVUL "Invulnerability!"
|
||||
#define GOTBERSERK "Berserk!"
|
||||
#define GOTINVIS "Partial Invisibility"
|
||||
#define GOTSUIT "Radiation Shielding Suit"
|
||||
#define GOTMAP "Computer Area Map"
|
||||
#define GOTVISOR "Light Amplification Visor"
|
||||
#define GOTMSPHERE "MegaSphere!"
|
||||
|
||||
#define GOTCLIP "Picked up a clip."
|
||||
#define GOTCLIPBOX "Picked up a box of bullets."
|
||||
#define GOTROCKET "Picked up a rocket."
|
||||
#define GOTROCKBOX "Picked up a box of rockets."
|
||||
#define GOTCELL "Picked up an energy cell."
|
||||
#define GOTCELLBOX "Picked up an energy cell pack."
|
||||
#define GOTSHELLS "Picked up 4 shotgun shells."
|
||||
#define GOTSHELLBOX "Picked up a box of shotgun shells."
|
||||
#define GOTBACKPACK "Picked up a backpack full of ammo!"
|
||||
|
||||
#define GOTBFG9000 "You got the BFG9000! Oh, yes."
|
||||
#define GOTCHAINGUN "You got the chaingun!"
|
||||
#define GOTCHAINSAW "A chainsaw! Find some meat!"
|
||||
#define GOTLAUNCHER "You got the rocket launcher!"
|
||||
#define GOTPLASMA "You got the plasma gun!"
|
||||
#define GOTSHOTGUN "You got the shotgun!"
|
||||
#define GOTSHOTGUN2 "You got the super shotgun!"
|
||||
|
||||
//
|
||||
// P_Doors.C
|
||||
//
|
||||
#define PD_BLUEO "You need a blue key to activate this object"
|
||||
#define PD_REDO "You need a red key to activate this object"
|
||||
#define PD_YELLOWO "You need a yellow key to activate this object"
|
||||
#define PD_BLUEK "You need a blue key to open this door"
|
||||
#define PD_REDK "You need a red key to open this door"
|
||||
#define PD_YELLOWK "You need a yellow key to open this door"
|
||||
|
||||
//
|
||||
// G_game.C
|
||||
//
|
||||
#define GGSAVED "game saved."
|
||||
|
||||
//
|
||||
// HU_stuff.C
|
||||
//
|
||||
#define HUSTR_MSGU "[Message unsent]"
|
||||
|
||||
#define HUSTR_E1M1 "E1M1: Hangar"
|
||||
#define HUSTR_E1M2 "E1M2: Nuclear Plant"
|
||||
#define HUSTR_E1M3 "E1M3: Toxin Refinery"
|
||||
#define HUSTR_E1M4 "E1M4: Command Control"
|
||||
#define HUSTR_E1M5 "E1M5: Phobos Lab"
|
||||
#define HUSTR_E1M6 "E1M6: Central Processing"
|
||||
#define HUSTR_E1M7 "E1M7: Computer Station"
|
||||
#define HUSTR_E1M8 "E1M8: Phobos Anomaly"
|
||||
#define HUSTR_E1M9 "E1M9: Military Base"
|
||||
|
||||
#define HUSTR_E2M1 "E2M1: Deimos Anomaly"
|
||||
#define HUSTR_E2M2 "E2M2: Containment Area"
|
||||
#define HUSTR_E2M3 "E2M3: Refinery"
|
||||
#define HUSTR_E2M4 "E2M4: Deimos Lab"
|
||||
#define HUSTR_E2M5 "E2M5: Command Center"
|
||||
#define HUSTR_E2M6 "E2M6: Halls of the Damned"
|
||||
#define HUSTR_E2M7 "E2M7: Spawning Vats"
|
||||
#define HUSTR_E2M8 "E2M8: Tower of Babel"
|
||||
#define HUSTR_E2M9 "E2M9: Fortress of Mystery"
|
||||
|
||||
#define HUSTR_E3M1 "E3M1: Hell Keep"
|
||||
#define HUSTR_E3M2 "E3M2: Slough of Despair"
|
||||
#define HUSTR_E3M3 "E3M3: Pandemonium"
|
||||
#define HUSTR_E3M4 "E3M4: House of Pain"
|
||||
#define HUSTR_E3M5 "E3M5: Unholy Cathedral"
|
||||
#define HUSTR_E3M6 "E3M6: Mt. Erebus"
|
||||
#define HUSTR_E3M7 "E3M7: Limbo"
|
||||
#define HUSTR_E3M8 "E3M8: Dis"
|
||||
#define HUSTR_E3M9 "E3M9: Warrens"
|
||||
|
||||
#define HUSTR_E4M1 "E4M1: Hell Beneath"
|
||||
#define HUSTR_E4M2 "E4M2: Perfect Hatred"
|
||||
#define HUSTR_E4M3 "E4M3: Sever The Wicked"
|
||||
#define HUSTR_E4M4 "E4M4: Unruly Evil"
|
||||
#define HUSTR_E4M5 "E4M5: They Will Repent"
|
||||
#define HUSTR_E4M6 "E4M6: Against Thee Wickedly"
|
||||
#define HUSTR_E4M7 "E4M7: And Hell Followed"
|
||||
#define HUSTR_E4M8 "E4M8: Unto The Cruel"
|
||||
#define HUSTR_E4M9 "E4M9: Fear"
|
||||
|
||||
#define HUSTR_1 "level 1: entryway"
|
||||
#define HUSTR_2 "level 2: underhalls"
|
||||
#define HUSTR_3 "level 3: the gantlet"
|
||||
#define HUSTR_4 "level 4: the focus"
|
||||
#define HUSTR_5 "level 5: the waste tunnels"
|
||||
#define HUSTR_6 "level 6: the crusher"
|
||||
#define HUSTR_7 "level 7: dead simple"
|
||||
#define HUSTR_8 "level 8: tricks and traps"
|
||||
#define HUSTR_9 "level 9: the pit"
|
||||
#define HUSTR_10 "level 10: refueling base"
|
||||
#define HUSTR_11 "level 11: 'o' of destruction!"
|
||||
|
||||
#define HUSTR_12 "level 12: the factory"
|
||||
#define HUSTR_13 "level 13: downtown"
|
||||
#define HUSTR_14 "level 14: the inmost dens"
|
||||
#define HUSTR_15 "level 15: industrial zone"
|
||||
#define HUSTR_16 "level 16: suburbs"
|
||||
#define HUSTR_17 "level 17: tenements"
|
||||
#define HUSTR_18 "level 18: the courtyard"
|
||||
#define HUSTR_19 "level 19: the citadel"
|
||||
#define HUSTR_20 "level 20: gotcha!"
|
||||
|
||||
#define HUSTR_21 "level 21: nirvana"
|
||||
#define HUSTR_22 "level 22: the catacombs"
|
||||
#define HUSTR_23 "level 23: barrels o' fun"
|
||||
#define HUSTR_24 "level 24: the chasm"
|
||||
#define HUSTR_25 "level 25: bloodfalls"
|
||||
#define HUSTR_26 "level 26: the abandoned mines"
|
||||
#define HUSTR_27 "level 27: monster condo"
|
||||
#define HUSTR_28 "level 28: the spirit world"
|
||||
#define HUSTR_29 "level 29: the living end"
|
||||
#define HUSTR_30 "level 30: icon of sin"
|
||||
|
||||
#define HUSTR_31 "level 31: wolfenstein"
|
||||
#define HUSTR_32 "level 32: grosse"
|
||||
|
||||
#define PHUSTR_1 "level 1: congo"
|
||||
#define PHUSTR_2 "level 2: well of souls"
|
||||
#define PHUSTR_3 "level 3: aztec"
|
||||
#define PHUSTR_4 "level 4: caged"
|
||||
#define PHUSTR_5 "level 5: ghost town"
|
||||
#define PHUSTR_6 "level 6: baron's lair"
|
||||
#define PHUSTR_7 "level 7: caughtyard"
|
||||
#define PHUSTR_8 "level 8: realm"
|
||||
#define PHUSTR_9 "level 9: abattoire"
|
||||
#define PHUSTR_10 "level 10: onslaught"
|
||||
#define PHUSTR_11 "level 11: hunted"
|
||||
|
||||
#define PHUSTR_12 "level 12: speed"
|
||||
#define PHUSTR_13 "level 13: the crypt"
|
||||
#define PHUSTR_14 "level 14: genesis"
|
||||
#define PHUSTR_15 "level 15: the twilight"
|
||||
#define PHUSTR_16 "level 16: the omen"
|
||||
#define PHUSTR_17 "level 17: compound"
|
||||
#define PHUSTR_18 "level 18: neurosphere"
|
||||
#define PHUSTR_19 "level 19: nme"
|
||||
#define PHUSTR_20 "level 20: the death domain"
|
||||
|
||||
#define PHUSTR_21 "level 21: slayer"
|
||||
#define PHUSTR_22 "level 22: impossible mission"
|
||||
#define PHUSTR_23 "level 23: tombstone"
|
||||
#define PHUSTR_24 "level 24: the final frontier"
|
||||
#define PHUSTR_25 "level 25: the temple of darkness"
|
||||
#define PHUSTR_26 "level 26: bunker"
|
||||
#define PHUSTR_27 "level 27: anti-christ"
|
||||
#define PHUSTR_28 "level 28: the sewers"
|
||||
#define PHUSTR_29 "level 29: odyssey of noises"
|
||||
#define PHUSTR_30 "level 30: the gateway of hell"
|
||||
|
||||
#define PHUSTR_31 "level 31: cyberden"
|
||||
#define PHUSTR_32 "level 32: go 2 it"
|
||||
|
||||
#define THUSTR_1 "level 1: system control"
|
||||
#define THUSTR_2 "level 2: human bbq"
|
||||
#define THUSTR_3 "level 3: power control"
|
||||
#define THUSTR_4 "level 4: wormhole"
|
||||
#define THUSTR_5 "level 5: hanger"
|
||||
#define THUSTR_6 "level 6: open season"
|
||||
#define THUSTR_7 "level 7: prison"
|
||||
#define THUSTR_8 "level 8: metal"
|
||||
#define THUSTR_9 "level 9: stronghold"
|
||||
#define THUSTR_10 "level 10: redemption"
|
||||
#define THUSTR_11 "level 11: storage facility"
|
||||
|
||||
#define THUSTR_12 "level 12: crater"
|
||||
#define THUSTR_13 "level 13: nukage processing"
|
||||
#define THUSTR_14 "level 14: steel works"
|
||||
#define THUSTR_15 "level 15: dead zone"
|
||||
#define THUSTR_16 "level 16: deepest reaches"
|
||||
#define THUSTR_17 "level 17: processing area"
|
||||
#define THUSTR_18 "level 18: mill"
|
||||
#define THUSTR_19 "level 19: shipping/respawning"
|
||||
#define THUSTR_20 "level 20: central processing"
|
||||
|
||||
#define THUSTR_21 "level 21: administration center"
|
||||
#define THUSTR_22 "level 22: habitat"
|
||||
#define THUSTR_23 "level 23: lunar mining project"
|
||||
#define THUSTR_24 "level 24: quarry"
|
||||
#define THUSTR_25 "level 25: baron's den"
|
||||
#define THUSTR_26 "level 26: ballistyx"
|
||||
#define THUSTR_27 "level 27: mount pain"
|
||||
#define THUSTR_28 "level 28: heck"
|
||||
#define THUSTR_29 "level 29: river styx"
|
||||
#define THUSTR_30 "level 30: last call"
|
||||
|
||||
#define THUSTR_31 "level 31: pharaoh"
|
||||
#define THUSTR_32 "level 32: caribbean"
|
||||
|
||||
#define HUSTR_CHATMACRO1 "I'm ready to kick butt!"
|
||||
#define HUSTR_CHATMACRO2 "I'm OK."
|
||||
#define HUSTR_CHATMACRO3 "I'm not looking too good!"
|
||||
#define HUSTR_CHATMACRO4 "Help!"
|
||||
#define HUSTR_CHATMACRO5 "You suck!"
|
||||
#define HUSTR_CHATMACRO6 "Next time, scumbag..."
|
||||
#define HUSTR_CHATMACRO7 "Come here!"
|
||||
#define HUSTR_CHATMACRO8 "I'll take care of it."
|
||||
#define HUSTR_CHATMACRO9 "Yes"
|
||||
#define HUSTR_CHATMACRO0 "No"
|
||||
|
||||
#define HUSTR_TALKTOSELF1 "You mumble to yourself"
|
||||
#define HUSTR_TALKTOSELF2 "Who's there?"
|
||||
#define HUSTR_TALKTOSELF3 "You scare yourself"
|
||||
#define HUSTR_TALKTOSELF4 "You start to rave"
|
||||
#define HUSTR_TALKTOSELF5 "You've lost it..."
|
||||
|
||||
#define HUSTR_MESSAGESENT "[Message Sent]"
|
||||
|
||||
// The following should NOT be changed unless it seems
|
||||
// just AWFULLY necessary
|
||||
|
||||
#define HUSTR_PLRGREEN "Green: "
|
||||
#define HUSTR_PLRINDIGO "Indigo: "
|
||||
#define HUSTR_PLRBROWN "Brown: "
|
||||
#define HUSTR_PLRRED "Red: "
|
||||
|
||||
#define HUSTR_KEYGREEN 'g'
|
||||
#define HUSTR_KEYINDIGO 'i'
|
||||
#define HUSTR_KEYBROWN 'b'
|
||||
#define HUSTR_KEYRED 'r'
|
||||
|
||||
//
|
||||
// AM_map.C
|
||||
//
|
||||
|
||||
#define AMSTR_FOLLOWON "Follow Mode ON"
|
||||
#define AMSTR_FOLLOWOFF "Follow Mode OFF"
|
||||
|
||||
#define AMSTR_GRIDON "Grid ON"
|
||||
#define AMSTR_GRIDOFF "Grid OFF"
|
||||
|
||||
#define AMSTR_MARKEDSPOT "Marked Spot"
|
||||
#define AMSTR_MARKSCLEARED "All Marks Cleared"
|
||||
|
||||
//
|
||||
// ST_stuff.C
|
||||
//
|
||||
|
||||
#define STSTR_MUS "Music Change"
|
||||
#define STSTR_NOMUS "IMPOSSIBLE SELECTION"
|
||||
#define STSTR_DQDON "Degreelessness Mode On"
|
||||
#define STSTR_DQDOFF "Degreelessness Mode Off"
|
||||
|
||||
#define STSTR_KFAADDED "Very Happy Ammo Added"
|
||||
#define STSTR_FAADDED "Ammo (no keys) Added"
|
||||
|
||||
#define STSTR_NCON "No Clipping Mode ON"
|
||||
#define STSTR_NCOFF "No Clipping Mode OFF"
|
||||
|
||||
#define STSTR_BEHOLD "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp"
|
||||
#define STSTR_BEHOLDX "Power-up Toggled"
|
||||
|
||||
#define STSTR_CHOPPERS "... doesn't suck - GM"
|
||||
#define STSTR_CLEV "Changing Level..."
|
||||
|
||||
//
|
||||
// F_Finale.C
|
||||
//
|
||||
#define E1TEXT \
|
||||
"Once you beat the big badasses and\n"\
|
||||
"clean out the moon base you're supposed\n"\
|
||||
"to win, aren't you? Aren't you? Where's\n"\
|
||||
"your fat reward and ticket home? What\n"\
|
||||
"the hell is this? It's not supposed to\n"\
|
||||
"end this way!\n"\
|
||||
"\n" \
|
||||
"It stinks like rotten meat, but looks\n"\
|
||||
"like the lost Deimos base. Looks like\n"\
|
||||
"you're stuck on The Shores of Hell.\n"\
|
||||
"The only way out is through.\n"\
|
||||
"\n"\
|
||||
"To continue the DOOM experience, play\n"\
|
||||
"The Shores of Hell and its amazing\n"\
|
||||
"sequel, Inferno!\n"
|
||||
|
||||
|
||||
#define E2TEXT \
|
||||
"You've done it! The hideous cyber-\n"\
|
||||
"demon lord that ruled the lost Deimos\n"\
|
||||
"moon base has been slain and you\n"\
|
||||
"are triumphant! But ... where are\n"\
|
||||
"you? You clamber to the edge of the\n"\
|
||||
"moon and look down to see the awful\n"\
|
||||
"truth.\n" \
|
||||
"\n"\
|
||||
"Deimos floats above Hell itself!\n"\
|
||||
"You've never heard of anyone escaping\n"\
|
||||
"from Hell, but you'll make the bastards\n"\
|
||||
"sorry they ever heard of you! Quickly,\n"\
|
||||
"you rappel down to the surface of\n"\
|
||||
"Hell.\n"\
|
||||
"\n" \
|
||||
"Now, it's on to the final chapter of\n"\
|
||||
"DOOM! -- Inferno."
|
||||
|
||||
|
||||
#define E3TEXT \
|
||||
"The loathsome spiderdemon that\n"\
|
||||
"masterminded the invasion of the moon\n"\
|
||||
"bases and caused so much death has had\n"\
|
||||
"its ass kicked for all time.\n"\
|
||||
"\n"\
|
||||
"A hidden doorway opens and you enter.\n"\
|
||||
"You've proven too tough for Hell to\n"\
|
||||
"contain, and now Hell at last plays\n"\
|
||||
"fair -- for you emerge from the door\n"\
|
||||
"to see the green fields of Earth!\n"\
|
||||
"Home at last.\n" \
|
||||
"\n"\
|
||||
"You wonder what's been happening on\n"\
|
||||
"Earth while you were battling evil\n"\
|
||||
"unleashed. It's good that no Hell-\n"\
|
||||
"spawn could have come through that\n"\
|
||||
"door with you ..."
|
||||
|
||||
|
||||
#define E4TEXT \
|
||||
"the spider mastermind must have sent forth\n"\
|
||||
"its legions of hellspawn before your\n"\
|
||||
"final confrontation with that terrible\n"\
|
||||
"beast from hell. but you stepped forward\n"\
|
||||
"and brought forth eternal damnation and\n"\
|
||||
"suffering upon the horde as a true hero\n"\
|
||||
"would in the face of something so evil.\n"\
|
||||
"\n"\
|
||||
"besides, someone was gonna pay for what\n"\
|
||||
"happened to daisy, your pet rabbit.\n"\
|
||||
"\n"\
|
||||
"but now, you see spread before you more\n"\
|
||||
"potential pain and gibbitude as a nation\n"\
|
||||
"of demons run amok among our cities.\n"\
|
||||
"\n"\
|
||||
"next stop, hell on earth!"
|
||||
|
||||
|
||||
// after level 6, put this:
|
||||
|
||||
#define C1TEXT \
|
||||
"YOU HAVE ENTERED DEEPLY INTO THE INFESTED\n" \
|
||||
"STARPORT. BUT SOMETHING IS WRONG. THE\n" \
|
||||
"MONSTERS HAVE BROUGHT THEIR OWN REALITY\n" \
|
||||
"WITH THEM, AND THE STARPORT'S TECHNOLOGY\n" \
|
||||
"IS BEING SUBVERTED BY THEIR PRESENCE.\n" \
|
||||
"\n"\
|
||||
"AHEAD, YOU SEE AN OUTPOST OF HELL, A\n" \
|
||||
"FORTIFIED ZONE. IF YOU CAN GET PAST IT,\n" \
|
||||
"YOU CAN PENETRATE INTO THE HAUNTED HEART\n" \
|
||||
"OF THE STARBASE AND FIND THE CONTROLLING\n" \
|
||||
"SWITCH WHICH HOLDS EARTH'S POPULATION\n" \
|
||||
"HOSTAGE."
|
||||
|
||||
// After level 11, put this:
|
||||
|
||||
#define C2TEXT \
|
||||
"YOU HAVE WON! YOUR VICTORY HAS ENABLED\n" \
|
||||
"HUMANKIND TO EVACUATE EARTH AND ESCAPE\n"\
|
||||
"THE NIGHTMARE. NOW YOU ARE THE ONLY\n"\
|
||||
"HUMAN LEFT ON THE FACE OF THE PLANET.\n"\
|
||||
"CANNIBAL MUTATIONS, CARNIVOROUS ALIENS,\n"\
|
||||
"AND EVIL SPIRITS ARE YOUR ONLY NEIGHBORS.\n"\
|
||||
"YOU SIT BACK AND WAIT FOR DEATH, CONTENT\n"\
|
||||
"THAT YOU HAVE SAVED YOUR SPECIES.\n"\
|
||||
"\n"\
|
||||
"BUT THEN, EARTH CONTROL BEAMS DOWN A\n"\
|
||||
"MESSAGE FROM SPACE: \"SENSORS HAVE LOCATED\n"\
|
||||
"THE SOURCE OF THE ALIEN INVASION. IF YOU\n"\
|
||||
"GO THERE, YOU MAY BE ABLE TO BLOCK THEIR\n"\
|
||||
"ENTRY. THE ALIEN BASE IS IN THE HEART OF\n"\
|
||||
"YOUR OWN HOME CITY, NOT FAR FROM THE\n"\
|
||||
"STARPORT.\" SLOWLY AND PAINFULLY YOU GET\n"\
|
||||
"UP AND RETURN TO THE FRAY."
|
||||
|
||||
|
||||
// After level 20, put this:
|
||||
|
||||
#define C3TEXT \
|
||||
"YOU ARE AT THE CORRUPT HEART OF THE CITY,\n"\
|
||||
"SURROUNDED BY THE CORPSES OF YOUR ENEMIES.\n"\
|
||||
"YOU SEE NO WAY TO DESTROY THE CREATURES'\n"\
|
||||
"ENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\n"\
|
||||
"TEETH AND PLUNGE THROUGH IT.\n"\
|
||||
"\n"\
|
||||
"THERE MUST BE A WAY TO CLOSE IT ON THE\n"\
|
||||
"OTHER SIDE. WHAT DO YOU CARE IF YOU'VE\n"\
|
||||
"GOT TO GO THROUGH HELL TO GET TO IT?"
|
||||
|
||||
|
||||
// After level 29, put this:
|
||||
|
||||
#define C4TEXT \
|
||||
"THE HORRENDOUS VISAGE OF THE BIGGEST\n"\
|
||||
"DEMON YOU'VE EVER SEEN CRUMBLES BEFORE\n"\
|
||||
"YOU, AFTER YOU PUMP YOUR ROCKETS INTO\n"\
|
||||
"HIS EXPOSED BRAIN. THE MONSTER SHRIVELS\n"\
|
||||
"UP AND DIES, ITS THRASHING LIMBS\n"\
|
||||
"DEVASTATING UNTOLD MILES OF HELL'S\n"\
|
||||
"SURFACE.\n"\
|
||||
"\n"\
|
||||
"YOU'VE DONE IT. THE INVASION IS OVER.\n"\
|
||||
"EARTH IS SAVED. HELL IS A WRECK. YOU\n"\
|
||||
"WONDER WHERE BAD FOLKS WILL GO WHEN THEY\n"\
|
||||
"DIE, NOW. WIPING THE SWEAT FROM YOUR\n"\
|
||||
"FOREHEAD YOU BEGIN THE LONG TREK BACK\n"\
|
||||
"HOME. REBUILDING EARTH OUGHT TO BE A\n"\
|
||||
"LOT MORE FUN THAN RUINING IT WAS.\n"
|
||||
|
||||
|
||||
|
||||
// Before level 31, put this:
|
||||
|
||||
#define C5TEXT \
|
||||
"CONGRATULATIONS, YOU'VE FOUND THE SECRET\n"\
|
||||
"LEVEL! LOOKS LIKE IT'S BEEN BUILT BY\n"\
|
||||
"HUMANS, RATHER THAN DEMONS. YOU WONDER\n"\
|
||||
"WHO THE INMATES OF THIS CORNER OF HELL\n"\
|
||||
"WILL BE."
|
||||
|
||||
|
||||
// Before level 32, put this:
|
||||
|
||||
#define C6TEXT \
|
||||
"CONGRATULATIONS, YOU'VE FOUND THE\n"\
|
||||
"SUPER SECRET LEVEL! YOU'D BETTER\n"\
|
||||
"BLAZE THROUGH THIS ONE!\n"
|
||||
|
||||
|
||||
// after map 06
|
||||
|
||||
#define P1TEXT \
|
||||
"You gloat over the steaming carcass of the\n"\
|
||||
"Guardian. With its death, you've wrested\n"\
|
||||
"the Accelerator from the stinking claws\n"\
|
||||
"of Hell. You relax and glance around the\n"\
|
||||
"room. Damn! There was supposed to be at\n"\
|
||||
"least one working prototype, but you can't\n"\
|
||||
"see it. The demons must have taken it.\n"\
|
||||
"\n"\
|
||||
"You must find the prototype, or all your\n"\
|
||||
"struggles will have been wasted. Keep\n"\
|
||||
"moving, keep fighting, keep killing.\n"\
|
||||
"Oh yes, keep living, too."
|
||||
|
||||
|
||||
// after map 11
|
||||
|
||||
#define P2TEXT \
|
||||
"Even the deadly Arch-Vile labyrinth could\n"\
|
||||
"not stop you, and you've gotten to the\n"\
|
||||
"prototype Accelerator which is soon\n"\
|
||||
"efficiently and permanently deactivated.\n"\
|
||||
"\n"\
|
||||
"You're good at that kind of thing."
|
||||
|
||||
|
||||
// after map 20
|
||||
|
||||
#define P3TEXT \
|
||||
"You've bashed and battered your way into\n"\
|
||||
"the heart of the devil-hive. Time for a\n"\
|
||||
"Search-and-Destroy mission, aimed at the\n"\
|
||||
"Gatekeeper, whose foul offspring is\n"\
|
||||
"cascading to Earth. Yeah, he's bad. But\n"\
|
||||
"you know who's worse!\n"\
|
||||
"\n"\
|
||||
"Grinning evilly, you check your gear, and\n"\
|
||||
"get ready to give the bastard a little Hell\n"\
|
||||
"of your own making!"
|
||||
|
||||
// after map 30
|
||||
|
||||
#define P4TEXT \
|
||||
"The Gatekeeper's evil face is splattered\n"\
|
||||
"all over the place. As its tattered corpse\n"\
|
||||
"collapses, an inverted Gate forms and\n"\
|
||||
"sucks down the shards of the last\n"\
|
||||
"prototype Accelerator, not to mention the\n"\
|
||||
"few remaining demons. You're done. Hell\n"\
|
||||
"has gone back to pounding bad dead folks \n"\
|
||||
"instead of good live ones. Remember to\n"\
|
||||
"tell your grandkids to put a rocket\n"\
|
||||
"launcher in your coffin. If you go to Hell\n"\
|
||||
"when you die, you'll need it for some\n"\
|
||||
"final cleaning-up ..."
|
||||
|
||||
// before map 31
|
||||
|
||||
#define P5TEXT \
|
||||
"You've found the second-hardest level we\n"\
|
||||
"got. Hope you have a saved game a level or\n"\
|
||||
"two previous. If not, be prepared to die\n"\
|
||||
"aplenty. For master marines only."
|
||||
|
||||
// before map 32
|
||||
|
||||
#define P6TEXT \
|
||||
"Betcha wondered just what WAS the hardest\n"\
|
||||
"level we had ready for ya? Now you know.\n"\
|
||||
"No one gets out alive."
|
||||
|
||||
|
||||
#define T1TEXT \
|
||||
"You've fought your way out of the infested\n"\
|
||||
"experimental labs. It seems that UAC has\n"\
|
||||
"once again gulped it down. With their\n"\
|
||||
"high turnover, it must be hard for poor\n"\
|
||||
"old UAC to buy corporate health insurance\n"\
|
||||
"nowadays..\n"\
|
||||
"\n"\
|
||||
"Ahead lies the military complex, now\n"\
|
||||
"swarming with diseased horrors hot to get\n"\
|
||||
"their teeth into you. With luck, the\n"\
|
||||
"complex still has some warlike ordnance\n"\
|
||||
"laying around."
|
||||
|
||||
|
||||
#define T2TEXT \
|
||||
"You hear the grinding of heavy machinery\n"\
|
||||
"ahead. You sure hope they're not stamping\n"\
|
||||
"out new hellspawn, but you're ready to\n"\
|
||||
"ream out a whole herd if you have to.\n"\
|
||||
"They might be planning a blood feast, but\n"\
|
||||
"you feel about as mean as two thousand\n"\
|
||||
"maniacs packed into one mad killer.\n"\
|
||||
"\n"\
|
||||
"You don't plan to go down easy."
|
||||
|
||||
|
||||
#define T3TEXT \
|
||||
"The vista opening ahead looks real damn\n"\
|
||||
"familiar. Smells familiar, too -- like\n"\
|
||||
"fried excrement. You didn't like this\n"\
|
||||
"place before, and you sure as hell ain't\n"\
|
||||
"planning to like it now. The more you\n"\
|
||||
"brood on it, the madder you get.\n"\
|
||||
"Hefting your gun, an evil grin trickles\n"\
|
||||
"onto your face. Time to take some names."
|
||||
|
||||
#define T4TEXT \
|
||||
"Suddenly, all is silent, from one horizon\n"\
|
||||
"to the other. The agonizing echo of Hell\n"\
|
||||
"fades away, the nightmare sky turns to\n"\
|
||||
"blue, the heaps of monster corpses start \n"\
|
||||
"to evaporate along with the evil stench \n"\
|
||||
"that filled the air. Jeeze, maybe you've\n"\
|
||||
"done it. Have you really won?\n"\
|
||||
"\n"\
|
||||
"Something rumbles in the distance.\n"\
|
||||
"A blue light begins to glow inside the\n"\
|
||||
"ruined skull of the demon-spitter."
|
||||
|
||||
|
||||
#define T5TEXT \
|
||||
"What now? Looks totally different. Kind\n"\
|
||||
"of like King Tut's condo. Well,\n"\
|
||||
"whatever's here can't be any worse\n"\
|
||||
"than usual. Can it? Or maybe it's best\n"\
|
||||
"to let sleeping gods lie.."
|
||||
|
||||
|
||||
#define T6TEXT \
|
||||
"Time for a vacation. You've burst the\n"\
|
||||
"bowels of hell and by golly you're ready\n"\
|
||||
"for a break. You mutter to yourself,\n"\
|
||||
"Maybe someone else can kick Hell's ass\n"\
|
||||
"next time around. Ahead lies a quiet town,\n"\
|
||||
"with peaceful flowing water, quaint\n"\
|
||||
"buildings, and presumably no Hellspawn.\n"\
|
||||
"\n"\
|
||||
"As you step off the transport, you hear\n"\
|
||||
"the stomp of a cyberdemon's iron shoe."
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Character cast strings F_FINALE.C
|
||||
//
|
||||
#define CC_ZOMBIE "ZOMBIEMAN"
|
||||
#define CC_SHOTGUN "SHOTGUN GUY"
|
||||
#define CC_HEAVY "HEAVY WEAPON DUDE"
|
||||
#define CC_IMP "IMP"
|
||||
#define CC_DEMON "DEMON"
|
||||
#define CC_LOST "LOST SOUL"
|
||||
#define CC_CACO "CACODEMON"
|
||||
#define CC_HELL "HELL KNIGHT"
|
||||
#define CC_BARON "BARON OF HELL"
|
||||
#define CC_ARACH "ARACHNOTRON"
|
||||
#define CC_PAIN "PAIN ELEMENTAL"
|
||||
#define CC_REVEN "REVENANT"
|
||||
#define CC_MANCU "MANCUBUS"
|
||||
#define CC_ARCH "ARCH-VILE"
|
||||
#define CC_SPIDER "THE SPIDER MASTERMIND"
|
||||
#define CC_CYBER "THE CYBERDEMON"
|
||||
#define CC_HERO "OUR HERO"
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,60 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//
|
||||
// DESCRIPTION: Event handling.
|
||||
//
|
||||
// Events are asynchronous inputs generally generated by the game user.
|
||||
// Events can be discarded if no responder claims them
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "d_event.h"
|
||||
|
||||
#define MAXEVENTS 64
|
||||
|
||||
static event_t events[MAXEVENTS];
|
||||
static int eventhead;
|
||||
static int eventtail;
|
||||
|
||||
//
|
||||
// D_PostEvent
|
||||
// Called by the I/O functions when input is detected
|
||||
//
|
||||
void D_PostEvent(event_t* ev)
|
||||
{
|
||||
events[eventhead] = *ev;
|
||||
eventhead = (eventhead + 1) % MAXEVENTS;
|
||||
}
|
||||
|
||||
// Read an event from the queue.
|
||||
event_t *D_PopEvent(void)
|
||||
{
|
||||
event_t *result;
|
||||
|
||||
// No more events waiting.
|
||||
if (eventtail == eventhead)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = &events[eventtail];
|
||||
|
||||
// Advance to the next event in the queue.
|
||||
|
||||
eventtail = (eventtail + 1) % MAXEVENTS;
|
||||
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
#ifndef __D_EVENT__
|
||||
#define __D_EVENT__
|
||||
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
|
||||
//
|
||||
// Event handling.
|
||||
//
|
||||
|
||||
// Input event types.
|
||||
typedef enum
|
||||
{
|
||||
ev_keydown,
|
||||
ev_keyup,
|
||||
ev_mouse,
|
||||
ev_joystick,
|
||||
ev_quit
|
||||
} evtype_t;
|
||||
|
||||
// Event structure.
|
||||
typedef struct
|
||||
{
|
||||
evtype_t type;
|
||||
|
||||
// Event-related data that depends on the type of event:
|
||||
//
|
||||
// ev_keydown/ev_keyup:
|
||||
// data1: Key code (from doomkeys.h) of the key that was
|
||||
// pressed or released.
|
||||
// data2: Ascii text of the character that was pressed,
|
||||
// shifted appropriately (eg. '$' if 4 was pressed
|
||||
// while shift was held).
|
||||
//
|
||||
// ev_mouse:
|
||||
// data1: Bitfield of buttons currently held down.
|
||||
// (bit 0 = left; bit 1 = right; bit 2 = middle).
|
||||
// data2: X axis mouse movement (turn).
|
||||
// data3: Y axis mouse movement (forward/backward).
|
||||
//
|
||||
// ev_joystick:
|
||||
// data1: Bitfield of buttons currently pressed.
|
||||
// data2: X axis mouse movement (turn).
|
||||
// data3: Y axis mouse movement (forward/backward).
|
||||
// data4: Third axis mouse movement (strafe).
|
||||
|
||||
int data1, data2, data3, data4;
|
||||
} event_t;
|
||||
|
||||
|
||||
//
|
||||
// Button/action code definitions.
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
// Press "Fire".
|
||||
BT_ATTACK = 1,
|
||||
// Use button, to open doors, activate switches.
|
||||
BT_USE = 2,
|
||||
|
||||
// Flag: game events, not really buttons.
|
||||
BT_SPECIAL = 128,
|
||||
BT_SPECIALMASK = 3,
|
||||
|
||||
// Flag, weapon change pending.
|
||||
// If true, the next 3 bits hold weapon num.
|
||||
BT_CHANGE = 4,
|
||||
// The 3bit weapon mask and shift, convenience.
|
||||
BT_WEAPONMASK = (8+16+32),
|
||||
BT_WEAPONSHIFT = 3,
|
||||
|
||||
// Pause the game.
|
||||
BTS_PAUSE = 1,
|
||||
// Save the game at each console.
|
||||
BTS_SAVEGAME = 2,
|
||||
|
||||
// Savegame slot numbers
|
||||
// occupy the second byte of buttons.
|
||||
BTS_SAVEMASK = (4+8+16),
|
||||
BTS_SAVESHIFT = 2,
|
||||
|
||||
} buttoncode_t;
|
||||
|
||||
// villsa [STRIFE] Strife specific buttons
|
||||
// TODO - not finished
|
||||
typedef enum
|
||||
{
|
||||
// Player view look up
|
||||
BT2_LOOKUP = 1,
|
||||
// Player view look down
|
||||
BT2_LOOKDOWN = 2,
|
||||
// Center player's view
|
||||
BT2_CENTERVIEW = 4,
|
||||
// Use inventory item
|
||||
BT2_INVUSE = 8,
|
||||
// Drop inventory item
|
||||
BT2_INVDROP = 16,
|
||||
// Jump up and down
|
||||
BT2_JUMP = 32,
|
||||
// Use medkit
|
||||
BT2_HEALTH = 128,
|
||||
|
||||
} buttoncode2_t;
|
||||
|
||||
// Called by IO functions when input is detected.
|
||||
void D_PostEvent (event_t *ev);
|
||||
|
||||
// Read an event from the event queue
|
||||
|
||||
event_t *D_PopEvent(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,128 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
|
||||
|
||||
// We are referring to sprite numbers.
|
||||
#include "info.h"
|
||||
|
||||
#include "d_items.h"
|
||||
|
||||
|
||||
//
|
||||
// PSPRITE ACTIONS for waepons.
|
||||
// This struct controls the weapon animations.
|
||||
//
|
||||
// Each entry is:
|
||||
// ammo/amunition type
|
||||
// upstate
|
||||
// downstate
|
||||
// readystate
|
||||
// atkstate, i.e. attack/fire/hit frame
|
||||
// flashstate, muzzle flash
|
||||
//
|
||||
weaponinfo_t weaponinfo[NUMWEAPONS] =
|
||||
{
|
||||
{
|
||||
// fist
|
||||
am_noammo,
|
||||
S_PUNCHUP,
|
||||
S_PUNCHDOWN,
|
||||
S_PUNCH,
|
||||
S_PUNCH1,
|
||||
S_NULL
|
||||
},
|
||||
{
|
||||
// pistol
|
||||
am_clip,
|
||||
S_PISTOLUP,
|
||||
S_PISTOLDOWN,
|
||||
S_PISTOL,
|
||||
S_PISTOL1,
|
||||
S_PISTOLFLASH
|
||||
},
|
||||
{
|
||||
// shotgun
|
||||
am_shell,
|
||||
S_SGUNUP,
|
||||
S_SGUNDOWN,
|
||||
S_SGUN,
|
||||
S_SGUN1,
|
||||
S_SGUNFLASH1
|
||||
},
|
||||
{
|
||||
// chaingun
|
||||
am_clip,
|
||||
S_CHAINUP,
|
||||
S_CHAINDOWN,
|
||||
S_CHAIN,
|
||||
S_CHAIN1,
|
||||
S_CHAINFLASH1
|
||||
},
|
||||
{
|
||||
// missile launcher
|
||||
am_misl,
|
||||
S_MISSILEUP,
|
||||
S_MISSILEDOWN,
|
||||
S_MISSILE,
|
||||
S_MISSILE1,
|
||||
S_MISSILEFLASH1
|
||||
},
|
||||
{
|
||||
// plasma rifle
|
||||
am_cell,
|
||||
S_PLASMAUP,
|
||||
S_PLASMADOWN,
|
||||
S_PLASMA,
|
||||
S_PLASMA1,
|
||||
S_PLASMAFLASH1
|
||||
},
|
||||
{
|
||||
// bfg 9000
|
||||
am_cell,
|
||||
S_BFGUP,
|
||||
S_BFGDOWN,
|
||||
S_BFG,
|
||||
S_BFG1,
|
||||
S_BFGFLASH1
|
||||
},
|
||||
{
|
||||
// chainsaw
|
||||
am_noammo,
|
||||
S_SAWUP,
|
||||
S_SAWDOWN,
|
||||
S_SAW,
|
||||
S_SAW1,
|
||||
S_NULL
|
||||
},
|
||||
{
|
||||
// super shotgun
|
||||
am_shell,
|
||||
S_DSGUNUP,
|
||||
S_DSGUNDOWN,
|
||||
S_DSGUN,
|
||||
S_DSGUN1,
|
||||
S_DSGUNFLASH1
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Items: key cards, artifacts, weapon, ammunition.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __D_ITEMS__
|
||||
#define __D_ITEMS__
|
||||
|
||||
#include "doomdef.h"
|
||||
|
||||
|
||||
|
||||
// Weapon info: sprite frames, ammunition use.
|
||||
typedef struct
|
||||
{
|
||||
ammotype_t ammo;
|
||||
int upstate;
|
||||
int downstate;
|
||||
int readystate;
|
||||
int atkstate;
|
||||
int flashstate;
|
||||
|
||||
} weaponinfo_t;
|
||||
|
||||
extern weaponinfo_t weaponinfo[NUMWEAPONS];
|
||||
|
||||
#endif
|
|
@ -0,0 +1,427 @@
|
|||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Search for and locate an IWAD file, and initialize according
|
||||
// to the IWAD type.
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "doomkeys.h"
|
||||
#include "d_iwad.h"
|
||||
#include "i_system.h"
|
||||
#include "m_argv.h"
|
||||
#include "m_config.h"
|
||||
#include "m_misc.h"
|
||||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
static const iwad_t iwads[] =
|
||||
{
|
||||
{ "doom2.wad", doom2, commercial, "Doom II" },
|
||||
{ "plutonia.wad", pack_plut, commercial, "Final Doom: Plutonia Experiment" },
|
||||
{ "tnt.wad", pack_tnt, commercial, "Final Doom: TNT: Evilution" },
|
||||
{ "doom.wad", doom, retail, "Doom" },
|
||||
{ "doom1.wad", doom, shareware, "Doom Shareware" },
|
||||
{ "chex.wad", pack_chex, shareware, "Chex Quest" },
|
||||
{ "hacx.wad", pack_hacx, commercial, "Hacx" },
|
||||
{ "freedm.wad", doom2, commercial, "FreeDM" },
|
||||
{ "freedoom2.wad", doom2, commercial, "Freedoom: Phase 2" },
|
||||
{ "freedoom1.wad", doom, retail, "Freedoom: Phase 1" },
|
||||
{ "heretic.wad", heretic, retail, "Heretic" },
|
||||
{ "heretic1.wad", heretic, shareware, "Heretic Shareware" },
|
||||
{ "hexen.wad", hexen, commercial, "Hexen" },
|
||||
{ "strife1.wad", strife, commercial, "Strife" },
|
||||
};
|
||||
|
||||
// Array of locations to search for IWAD files
|
||||
//
|
||||
// "128 IWAD search directories should be enough for anybody".
|
||||
|
||||
#define MAX_IWAD_DIRS 128
|
||||
|
||||
static boolean iwad_dirs_built = false;
|
||||
static char *iwad_dirs[MAX_IWAD_DIRS];
|
||||
static int num_iwad_dirs = 0;
|
||||
|
||||
static void AddIWADDir(char *dir)
|
||||
{
|
||||
if (num_iwad_dirs < MAX_IWAD_DIRS)
|
||||
{
|
||||
iwad_dirs[num_iwad_dirs] = dir;
|
||||
++num_iwad_dirs;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the specified path is a path to a file
|
||||
// of the specified name.
|
||||
|
||||
static boolean DirIsFile(char *path, char *filename)
|
||||
{
|
||||
size_t path_len;
|
||||
size_t filename_len;
|
||||
|
||||
path_len = ES_strlen(path);
|
||||
filename_len = ES_strlen(filename);
|
||||
|
||||
return path_len >= filename_len + 1
|
||||
&& path[path_len - filename_len - 1] == DIR_SEPARATOR
|
||||
&& !ES_strcasecmp(&path[path_len - filename_len], filename);
|
||||
}
|
||||
|
||||
// Check if the specified directory contains the specified IWAD
|
||||
// file, returning the full path to the IWAD if found, or NULL
|
||||
// if not found.
|
||||
|
||||
static char *CheckDirectoryHasIWAD(char *dir, char *iwadname)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
// As a special case, the "directory" may refer directly to an
|
||||
// IWAD file if the path comes from DOOMWADDIR or DOOMWADPATH.
|
||||
|
||||
if (DirIsFile(dir, iwadname) && M_FileExists(dir))
|
||||
{
|
||||
return ES_strdup(dir);
|
||||
}
|
||||
|
||||
// Construct the full path to the IWAD if it is located in
|
||||
// this directory, and check if it exists.
|
||||
|
||||
if (!ES_strcmp(dir, "."))
|
||||
{
|
||||
filename = ES_strdup(iwadname);
|
||||
}
|
||||
else
|
||||
{
|
||||
filename = M_StringJoin(dir, DIR_SEPARATOR_S, iwadname, NULL);
|
||||
}
|
||||
|
||||
ES_debugf("Trying IWAD file:%s\n", filename);
|
||||
|
||||
if (M_FileExists(filename))
|
||||
{
|
||||
return filename;
|
||||
}
|
||||
|
||||
ES_free(filename);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Search a directory to try to find an IWAD
|
||||
// Returns the location of the IWAD if found, otherwise NULL.
|
||||
|
||||
static char *SearchDirectoryForIWAD(char *dir, int mask, GameMission_t *mission)
|
||||
{
|
||||
char *filename;
|
||||
size_t i;
|
||||
|
||||
for (i=0; i<arrlen(iwads); ++i)
|
||||
{
|
||||
if (((1 << iwads[i].mission) & mask) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
filename = CheckDirectoryHasIWAD(dir, iwads[i].name);
|
||||
|
||||
if (filename != NULL)
|
||||
{
|
||||
*mission = iwads[i].mission;
|
||||
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// When given an IWAD with the '-iwad' parameter,
|
||||
// attempt to identify it by its name.
|
||||
|
||||
static GameMission_t IdentifyIWADByName(char *name, int mask)
|
||||
{
|
||||
size_t i;
|
||||
GameMission_t mission;
|
||||
char *p;
|
||||
|
||||
p = ES_strchr(name, DIR_SEPARATOR);
|
||||
|
||||
if (p != NULL)
|
||||
{
|
||||
name = p + 1;
|
||||
}
|
||||
|
||||
mission = none;
|
||||
|
||||
for (i=0; i<arrlen(iwads); ++i)
|
||||
{
|
||||
// Check if the filename is this IWAD name.
|
||||
|
||||
// Only use supported missions:
|
||||
|
||||
if (((1 << iwads[i].mission) & mask) == 0)
|
||||
continue;
|
||||
|
||||
// Check if it ends in this IWAD name.
|
||||
|
||||
if (!ES_strcasecmp(name, iwads[i].name))
|
||||
{
|
||||
mission = iwads[i].mission;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mission;
|
||||
}
|
||||
|
||||
//
|
||||
// Build a list of IWAD files
|
||||
//
|
||||
|
||||
static void BuildIWADDirList(void)
|
||||
{
|
||||
AddIWADDir (FILES_DIR);
|
||||
|
||||
// Don't run this function again.
|
||||
|
||||
iwad_dirs_built = true;
|
||||
}
|
||||
|
||||
//
|
||||
// Searches WAD search paths for an WAD with a specific filename.
|
||||
//
|
||||
|
||||
char *D_FindWADByName(char *name)
|
||||
{
|
||||
char *path;
|
||||
int i;
|
||||
|
||||
// Absolute path?
|
||||
|
||||
if (M_FileExists(name))
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
BuildIWADDirList();
|
||||
|
||||
// Search through all IWAD paths for a file with the given name.
|
||||
|
||||
for (i=0; i<num_iwad_dirs; ++i)
|
||||
{
|
||||
// As a special case, if this is in DOOMWADDIR or DOOMWADPATH,
|
||||
// the "directory" may actually refer directly to an IWAD
|
||||
// file.
|
||||
|
||||
if (DirIsFile(iwad_dirs[i], name) && M_FileExists(iwad_dirs[i]))
|
||||
{
|
||||
return ES_strdup(iwad_dirs[i]);
|
||||
}
|
||||
|
||||
// Construct a string for the full path
|
||||
|
||||
path = M_StringJoin(iwad_dirs[i], DIR_SEPARATOR_S, name, NULL);
|
||||
|
||||
if (M_FileExists(path))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
ES_free(path);
|
||||
}
|
||||
|
||||
// File not found
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// D_TryWADByName
|
||||
//
|
||||
// Searches for a WAD by its filename, or passes through the filename
|
||||
// if not found.
|
||||
//
|
||||
|
||||
char *D_TryFindWADByName(char *filename)
|
||||
{
|
||||
char *result;
|
||||
|
||||
result = D_FindWADByName(filename);
|
||||
|
||||
if (result != NULL)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// FindIWAD
|
||||
// Checks availability of IWAD files by name,
|
||||
// to determine whether registered/commercial features
|
||||
// should be executed (notably loading PWADs).
|
||||
//
|
||||
|
||||
char *D_FindIWAD(int mask, GameMission_t *mission)
|
||||
{
|
||||
char *result;
|
||||
char *iwadfile;
|
||||
int iwadparm;
|
||||
int i;
|
||||
|
||||
// Check for the -iwad parameter
|
||||
|
||||
//!
|
||||
// Specify an IWAD file to use.
|
||||
//
|
||||
// @arg <file>
|
||||
//
|
||||
|
||||
iwadparm = M_CheckParmWithArgs("-iwad", 1);
|
||||
|
||||
if (iwadparm)
|
||||
{
|
||||
// Search through IWAD dirs for an IWAD with the given name.
|
||||
|
||||
iwadfile = myargv[iwadparm + 1];
|
||||
|
||||
result = D_FindWADByName(iwadfile);
|
||||
|
||||
if (result == NULL)
|
||||
{
|
||||
I_Error("IWAD file '%s' not found!", iwadfile);
|
||||
}
|
||||
|
||||
*mission = IdentifyIWADByName(result, mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search through the list and look for an IWAD
|
||||
|
||||
ES_debugf("-iwad not specified, trying a few iwad names\n");
|
||||
|
||||
result = NULL;
|
||||
|
||||
BuildIWADDirList();
|
||||
|
||||
for (i=0; result == NULL && i<num_iwad_dirs; ++i)
|
||||
{
|
||||
result = SearchDirectoryForIWAD(iwad_dirs[i], mask, mission);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Find all IWADs in the IWAD search path matching the given mask.
|
||||
|
||||
const iwad_t **D_FindAllIWADs(int mask)
|
||||
{
|
||||
const iwad_t **result;
|
||||
int result_len;
|
||||
char *filename;
|
||||
size_t i;
|
||||
|
||||
result = ES_malloc(sizeof(iwad_t *) * (arrlen(iwads) + 1));
|
||||
result_len = 0;
|
||||
|
||||
// Try to find all IWADs
|
||||
|
||||
for (i=0; i<arrlen(iwads); ++i)
|
||||
{
|
||||
if (((1 << iwads[i].mission) & mask) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
filename = D_FindWADByName(iwads[i].name);
|
||||
|
||||
if (filename != NULL)
|
||||
{
|
||||
result[result_len] = &iwads[i];
|
||||
++result_len;
|
||||
}
|
||||
}
|
||||
|
||||
// End of list
|
||||
|
||||
result[result_len] = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the IWAD name used for savegames.
|
||||
//
|
||||
|
||||
char *D_SaveGameIWADName(GameMission_t gamemission)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
// Determine the IWAD name to use for savegames.
|
||||
// This determines the directory the savegame files get put into.
|
||||
//
|
||||
// Note that we match on gamemission rather than on IWAD name.
|
||||
// This ensures that doom1.wad and doom.wad saves are stored
|
||||
// in the same place.
|
||||
|
||||
for (i=0; i<arrlen(iwads); ++i)
|
||||
{
|
||||
if (gamemission == iwads[i].mission)
|
||||
{
|
||||
return iwads[i].name;
|
||||
}
|
||||
}
|
||||
|
||||
// Default fallback:
|
||||
|
||||
return "unknown.wad";
|
||||
}
|
||||
|
||||
char *D_SuggestIWADName(GameMission_t mission, GameMode_t mode)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < arrlen(iwads); ++i)
|
||||
{
|
||||
if (iwads[i].mission == mission && iwads[i].mode == mode)
|
||||
{
|
||||
return iwads[i].name;
|
||||
}
|
||||
}
|
||||
|
||||
return "unknown.wad";
|
||||
}
|
||||
|
||||
char *D_SuggestGameName(GameMission_t mission, GameMode_t mode)
|
||||
{
|
||||
for (size_t i = 0; i < arrlen(iwads); ++i)
|
||||
{
|
||||
if (iwads[i].mission == mission
|
||||
&& (mode == indetermined || iwads[i].mode == mode))
|
||||
{
|
||||
return iwads[i].description;
|
||||
}
|
||||
}
|
||||
|
||||
return "Unknown game?";
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Find IWAD and initialize according to IWAD type.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __D_IWAD__
|
||||
#define __D_IWAD__
|
||||
|
||||
#include "d_mode.h"
|
||||
|
||||
#define IWAD_MASK_DOOM ((1 << doom) \
|
||||
| (1 << doom2) \
|
||||
| (1 << pack_tnt) \
|
||||
| (1 << pack_plut) \
|
||||
| (1 << pack_chex) \
|
||||
| (1 << pack_hacx))
|
||||
#define IWAD_MASK_HERETIC (1 << heretic)
|
||||
#define IWAD_MASK_HEXEN (1 << hexen)
|
||||
#define IWAD_MASK_STRIFE (1 << strife)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
GameMission_t mission;
|
||||
GameMode_t mode;
|
||||
char *description;
|
||||
} iwad_t;
|
||||
|
||||
char *D_FindWADByName(char *filename);
|
||||
char *D_TryFindWADByName(char *filename);
|
||||
char *D_FindIWAD(int mask, GameMission_t *mission);
|
||||
const iwad_t **D_FindAllIWADs(int mask);
|
||||
char *D_SaveGameIWADName(GameMission_t gamemission);
|
||||
char *D_SuggestIWADName(GameMission_t mission, GameMode_t mode);
|
||||
char *D_SuggestGameName(GameMission_t mission, GameMode_t mode);
|
||||
void D_CheckCorrectIWAD(GameMission_t mission);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,687 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Main loop code.
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "d_event.h"
|
||||
#include "d_loop.h"
|
||||
#include "d_ticcmd.h"
|
||||
|
||||
#include "i_system.h"
|
||||
#include "i_timer.h"
|
||||
#include "i_video.h"
|
||||
|
||||
#include "m_argv.h"
|
||||
#include "m_fixed.h"
|
||||
|
||||
#include "net_client.h"
|
||||
#include "net_gui.h"
|
||||
#include "net_io.h"
|
||||
#include "net_query.h"
|
||||
#include "net_server.h"
|
||||
#include "net_loop.h"
|
||||
|
||||
// The complete set of data for a particular tic.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ticcmd_t cmds[NET_MAXPLAYERS];
|
||||
boolean ingame[NET_MAXPLAYERS];
|
||||
} ticcmd_set_t;
|
||||
|
||||
//
|
||||
// gametic is the tic about to (or currently being) run
|
||||
// maketic is the tic that hasn't had control made for it yet
|
||||
// recvtic is the latest tic received from the server.
|
||||
//
|
||||
// a gametic cannot be run until ticcmds are received for it
|
||||
// from all players.
|
||||
//
|
||||
|
||||
static ticcmd_set_t ticdata[BACKUPTICS];
|
||||
|
||||
// The index of the next tic to be made (with a call to BuildTiccmd).
|
||||
|
||||
static int maketic;
|
||||
|
||||
// The number of complete tics received from the server so far.
|
||||
|
||||
static int recvtic;
|
||||
|
||||
// The number of tics that have been run (using RunTic) so far.
|
||||
|
||||
int gametic;
|
||||
|
||||
// When set to true, a single tic is run each time TryRunTics() is called.
|
||||
// This is used for -timedemo mode.
|
||||
|
||||
boolean singletics = false;
|
||||
|
||||
// Index of the local player.
|
||||
|
||||
static int localplayer;
|
||||
|
||||
// Used for original sync code.
|
||||
|
||||
static int skiptics = 0;
|
||||
|
||||
// Reduce the bandwidth needed by sampling game input less and transmitting
|
||||
// less. If ticdup is 2, sample half normal, 3 = one third normal, etc.
|
||||
|
||||
int ticdup;
|
||||
|
||||
// Amount to offset the timer for game sync.
|
||||
|
||||
fixed_t offsetms;
|
||||
|
||||
// Use new client syncronisation code
|
||||
|
||||
static boolean new_sync = true;
|
||||
|
||||
// Callback functions for loop code.
|
||||
|
||||
static loop_interface_t *loop_interface = NULL;
|
||||
|
||||
// Current players in the multiplayer game.
|
||||
// This is distinct from playeringame[] used by the game code, which may
|
||||
// modify playeringame[] when playing back multiplayer demos.
|
||||
|
||||
static boolean local_playeringame[NET_MAXPLAYERS];
|
||||
|
||||
// Requested player class "sent" to the server on connect.
|
||||
// If we are only doing a single player game then this needs to be remembered
|
||||
// and saved in the game settings.
|
||||
|
||||
static int player_class;
|
||||
|
||||
|
||||
// 35 fps clock adjusted by offsetms milliseconds
|
||||
|
||||
static int GetAdjustedTime(void)
|
||||
{
|
||||
int time_ms;
|
||||
|
||||
time_ms = I_GetTimeMS();
|
||||
|
||||
if (new_sync)
|
||||
{
|
||||
// Use the adjustments from net_client.c only if we are
|
||||
// using the new sync mode.
|
||||
|
||||
time_ms += (offsetms / FRACUNIT);
|
||||
}
|
||||
|
||||
return (time_ms * TICRATE) / 1000;
|
||||
}
|
||||
|
||||
static boolean BuildNewTic(void)
|
||||
{
|
||||
int gameticdiv;
|
||||
ticcmd_t cmd;
|
||||
|
||||
gameticdiv = gametic/ticdup;
|
||||
|
||||
I_StartTic ();
|
||||
loop_interface->ProcessEvents();
|
||||
|
||||
// Always run the menu
|
||||
|
||||
loop_interface->RunMenu();
|
||||
|
||||
if (drone)
|
||||
{
|
||||
// In drone mode, do not generate any ticcmds.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (new_sync)
|
||||
{
|
||||
// If playing single player, do not allow tics to buffer
|
||||
// up very far
|
||||
|
||||
if (!net_client_connected && maketic - gameticdiv > 2)
|
||||
return false;
|
||||
|
||||
// Never go more than ~200ms ahead
|
||||
|
||||
if (maketic - gameticdiv > 8)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (maketic - gameticdiv >= 5)
|
||||
return false;
|
||||
}
|
||||
|
||||
ES_memset(&cmd, 0, sizeof(ticcmd_t));
|
||||
loop_interface->BuildTiccmd(&cmd, maketic);
|
||||
|
||||
#ifdef FEATURE_MULTIPLAYER
|
||||
|
||||
if (net_client_connected)
|
||||
{
|
||||
NET_CL_SendTiccmd(&cmd, maketic);
|
||||
}
|
||||
|
||||
#endif
|
||||
ticdata[maketic % BACKUPTICS].cmds[localplayer] = cmd;
|
||||
ticdata[maketic % BACKUPTICS].ingame[localplayer] = true;
|
||||
|
||||
++maketic;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// NetUpdate
|
||||
// Builds ticcmds for console player,
|
||||
// sends out a packet
|
||||
//
|
||||
int lasttime;
|
||||
|
||||
void NetUpdate (void)
|
||||
{
|
||||
int nowtime;
|
||||
int newtics;
|
||||
int i;
|
||||
|
||||
// If we are running with singletics (timing a demo), this
|
||||
// is all done separately.
|
||||
|
||||
if (singletics)
|
||||
return;
|
||||
|
||||
#ifdef FEATURE_MULTIPLAYER
|
||||
|
||||
// Run network subsystems
|
||||
|
||||
NET_CL_Run();
|
||||
NET_SV_Run();
|
||||
|
||||
#endif
|
||||
|
||||
// check time
|
||||
nowtime = GetAdjustedTime() / ticdup;
|
||||
newtics = nowtime - lasttime;
|
||||
|
||||
lasttime = nowtime;
|
||||
|
||||
if (skiptics <= newtics)
|
||||
{
|
||||
newtics -= skiptics;
|
||||
skiptics = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
skiptics -= newtics;
|
||||
newtics = 0;
|
||||
}
|
||||
|
||||
// build new ticcmds for console player
|
||||
|
||||
for (i=0 ; i < newtics; i++)
|
||||
{
|
||||
if (!BuildNewTic())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void D_Disconnected(void)
|
||||
{
|
||||
// In drone mode, the game cannot continue once disconnected.
|
||||
|
||||
if (drone)
|
||||
{
|
||||
I_Error("Disconnected from server in drone mode.");
|
||||
}
|
||||
|
||||
// disconnected from server
|
||||
|
||||
ES_debugf("Disconnected from server.\n");
|
||||
}
|
||||
|
||||
//
|
||||
// Invoked by the network engine when a complete set of ticcmds is
|
||||
// available.
|
||||
//
|
||||
|
||||
void D_ReceiveTic(ticcmd_t *ticcmds, boolean *players_mask)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
// Disconnected from server?
|
||||
|
||||
if (ticcmds == NULL && players_mask == NULL)
|
||||
{
|
||||
D_Disconnected();
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < NET_MAXPLAYERS; ++i)
|
||||
{
|
||||
if (!drone && i == localplayer)
|
||||
{
|
||||
// This is us. Don't overwrite it.
|
||||
}
|
||||
else
|
||||
{
|
||||
ticdata[recvtic % BACKUPTICS].cmds[i] = ticcmds[i];
|
||||
ticdata[recvtic % BACKUPTICS].ingame[i] = players_mask[i];
|
||||
}
|
||||
}
|
||||
|
||||
++recvtic;
|
||||
}
|
||||
|
||||
//
|
||||
// Start game loop
|
||||
//
|
||||
// Called after the screen is set but before the game starts running.
|
||||
//
|
||||
|
||||
void D_StartGameLoop(void)
|
||||
{
|
||||
lasttime = GetAdjustedTime() / ticdup;
|
||||
}
|
||||
|
||||
void D_StartNetGame(net_gamesettings_t *settings,
|
||||
netgame_startup_callback_t callback)
|
||||
{
|
||||
settings->consoleplayer = 0;
|
||||
settings->num_players = 1;
|
||||
settings->player_classes[0] = player_class;
|
||||
settings->new_sync = 0;
|
||||
settings->extratics = 1;
|
||||
settings->ticdup = 1;
|
||||
|
||||
ticdup = settings->ticdup;
|
||||
new_sync = settings->new_sync;
|
||||
}
|
||||
|
||||
boolean D_InitNetGame(net_connect_data_t *connect_data)
|
||||
{
|
||||
boolean result = false;
|
||||
#ifdef FEATURE_MULTIPLAYER
|
||||
net_addr_t *addr = NULL;
|
||||
int i;
|
||||
#endif
|
||||
|
||||
// Call D_QuitNetGame on exit:
|
||||
|
||||
I_AtExit(D_QuitNetGame, true);
|
||||
|
||||
player_class = connect_data->player_class;
|
||||
|
||||
#ifdef FEATURE_MULTIPLAYER
|
||||
|
||||
//!
|
||||
// @category net
|
||||
//
|
||||
// Start a multiplayer server, listening for connections.
|
||||
//
|
||||
|
||||
if (M_CheckParm("-server") > 0
|
||||
|| M_CheckParm("-privateserver") > 0)
|
||||
{
|
||||
NET_SV_Init();
|
||||
NET_SV_AddModule(&net_loop_server_module);
|
||||
NET_SV_AddModule(&net_sdl_module);
|
||||
NET_SV_RegisterWithMaster();
|
||||
|
||||
net_loop_client_module.InitClient();
|
||||
addr = net_loop_client_module.ResolveAddress(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
//!
|
||||
// @category net
|
||||
//
|
||||
// Automatically search the local LAN for a multiplayer
|
||||
// server and join it.
|
||||
//
|
||||
|
||||
i = M_CheckParm("-autojoin");
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
addr = NET_FindLANServer();
|
||||
|
||||
if (addr == NULL)
|
||||
{
|
||||
I_Error("No server found on local LAN");
|
||||
}
|
||||
}
|
||||
|
||||
//!
|
||||
// @arg <address>
|
||||
// @category net
|
||||
//
|
||||
// Connect to a multiplayer server running on the given
|
||||
// address.
|
||||
//
|
||||
|
||||
i = M_CheckParmWithArgs("-connect", 1);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
net_sdl_module.InitClient();
|
||||
addr = net_sdl_module.ResolveAddress(myargv[i+1]);
|
||||
|
||||
if (addr == NULL)
|
||||
{
|
||||
I_Error("Unable to resolve '%s'\n", myargv[i+1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (addr != NULL)
|
||||
{
|
||||
if (M_CheckParm("-drone") > 0)
|
||||
{
|
||||
connect_data->drone = true;
|
||||
}
|
||||
|
||||
if (!NET_CL_Connect(addr, connect_data))
|
||||
{
|
||||
I_Error("D_InitNetGame: Failed to connect to %s\n",
|
||||
NET_AddrToString(addr));
|
||||
}
|
||||
|
||||
ES_debuf("D_InitNetGame: Connected to %s\n", NET_AddrToString(addr));
|
||||
|
||||
// Wait for launch message received from server.
|
||||
|
||||
NET_WaitForLaunch();
|
||||
|
||||
result = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// D_QuitNetGame
|
||||
// Called before quitting to leave a net game
|
||||
// without hanging the other players
|
||||
//
|
||||
void D_QuitNetGame (void)
|
||||
{
|
||||
#ifdef FEATURE_MULTIPLAYER
|
||||
NET_SV_Shutdown();
|
||||
NET_CL_Disconnect();
|
||||
#endif
|
||||
}
|
||||
|
||||
static int GetLowTic(void)
|
||||
{
|
||||
int lowtic;
|
||||
|
||||
lowtic = maketic;
|
||||
|
||||
#ifdef FEATURE_MULTIPLAYER
|
||||
if (net_client_connected)
|
||||
{
|
||||
if (drone || recvtic < lowtic)
|
||||
{
|
||||
lowtic = recvtic;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return lowtic;
|
||||
}
|
||||
|
||||
static int frameon;
|
||||
static int frameskip[4];
|
||||
static int oldnettics;
|
||||
|
||||
static void OldNetSync(void)
|
||||
{
|
||||
unsigned int i;
|
||||
int keyplayer = -1;
|
||||
|
||||
frameon++;
|
||||
|
||||
// ideally maketic should be 1 - 3 tics above lowtic
|
||||
// if we are consistantly slower, speed up time
|
||||
|
||||
for (i=0 ; i<NET_MAXPLAYERS ; i++)
|
||||
{
|
||||
if (local_playeringame[i])
|
||||
{
|
||||
keyplayer = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (keyplayer < 0)
|
||||
{
|
||||
// If there are no players, we can never advance anyway
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (localplayer == keyplayer)
|
||||
{
|
||||
// the key player does not adapt
|
||||
}
|
||||
else
|
||||
{
|
||||
if (maketic <= recvtic)
|
||||
{
|
||||
lasttime--;
|
||||
}
|
||||
|
||||
frameskip[frameon & 3] = oldnettics > recvtic;
|
||||
oldnettics = maketic;
|
||||
|
||||
if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
|
||||
{
|
||||
skiptics = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if there are players in the game:
|
||||
|
||||
static boolean PlayersInGame(void)
|
||||
{
|
||||
boolean result = false;
|
||||
unsigned int i;
|
||||
|
||||
// If we are connected to a server, check if there are any players
|
||||
// in the game.
|
||||
if (net_client_connected)
|
||||
{
|
||||
for (i = 0; i < NET_MAXPLAYERS; ++i)
|
||||
{
|
||||
result = result || local_playeringame[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Whether single or multi-player, unless we are running as a drone,
|
||||
// we are in the game.
|
||||
|
||||
if (!drone)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// When using ticdup, certain values must be cleared out when running
|
||||
// the duplicate ticcmds.
|
||||
|
||||
static void TicdupSquash(ticcmd_set_t *set)
|
||||
{
|
||||
ticcmd_t *cmd;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < NET_MAXPLAYERS ; ++i)
|
||||
{
|
||||
cmd = &set->cmds[i];
|
||||
cmd->chatchar = 0;
|
||||
if (cmd->buttons & BT_SPECIAL)
|
||||
cmd->buttons = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// When running in single player mode, clear all the ingame[] array
|
||||
// except the local player.
|
||||
|
||||
static void SinglePlayerClear(ticcmd_set_t *set)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < NET_MAXPLAYERS; ++i)
|
||||
{
|
||||
if (i != localplayer)
|
||||
{
|
||||
set->ingame[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TryRunTics
|
||||
//
|
||||
|
||||
void TryRunTics (void)
|
||||
{
|
||||
int i;
|
||||
int lowtic;
|
||||
int entertic;
|
||||
static int oldentertics;
|
||||
int realtics;
|
||||
int availabletics;
|
||||
int counts;
|
||||
|
||||
// get real tics
|
||||
entertic = I_GetTime() / ticdup;
|
||||
realtics = entertic - oldentertics;
|
||||
oldentertics = entertic;
|
||||
|
||||
// in singletics mode, run a single tic every time this function
|
||||
// is called.
|
||||
|
||||
if (singletics)
|
||||
{
|
||||
BuildNewTic();
|
||||
}
|
||||
else
|
||||
{
|
||||
NetUpdate();
|
||||
}
|
||||
|
||||
lowtic = GetLowTic();
|
||||
|
||||
availabletics = lowtic - gametic/ticdup;
|
||||
|
||||
// decide how many tics to run
|
||||
|
||||
if (new_sync)
|
||||
{
|
||||
counts = availabletics;
|
||||
}
|
||||
else
|
||||
{
|
||||
// decide how many tics to run
|
||||
if (realtics < availabletics-1)
|
||||
counts = realtics+1;
|
||||
else if (realtics < availabletics)
|
||||
counts = realtics;
|
||||
else
|
||||
counts = availabletics;
|
||||
|
||||
if (counts < 1)
|
||||
counts = 1;
|
||||
|
||||
if (net_client_connected)
|
||||
{
|
||||
OldNetSync();
|
||||
}
|
||||
}
|
||||
|
||||
if (counts < 1) counts = 1;
|
||||
|
||||
// wait for new tics if needed
|
||||
while (!PlayersInGame() || lowtic < gametic/ticdup + counts)
|
||||
{
|
||||
NetUpdate();
|
||||
|
||||
lowtic = GetLowTic();
|
||||
|
||||
if (lowtic < gametic/ticdup) I_Error("TryRunTics: lowtic < gametic");
|
||||
|
||||
// Don't stay in this loop forever. The menu is still running,
|
||||
// so return to update the screen
|
||||
|
||||
if (I_GetTime() / ticdup - entertic > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
I_Sleep(1);
|
||||
}
|
||||
|
||||
// run the count * ticdup dics
|
||||
while (counts--)
|
||||
{
|
||||
ticcmd_set_t *set;
|
||||
|
||||
if (!PlayersInGame())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
set = &ticdata[(gametic / ticdup) % BACKUPTICS];
|
||||
|
||||
if (!net_client_connected)
|
||||
{
|
||||
SinglePlayerClear(set);
|
||||
}
|
||||
|
||||
for (i=0; i<ticdup; i++)
|
||||
{
|
||||
if (gametic/ticdup > lowtic) I_Error ("gametic>lowtic");
|
||||
|
||||
ES_memcpy(local_playeringame, set->ingame, sizeof(local_playeringame));
|
||||
|
||||
loop_interface->RunTic(set->cmds, set->ingame);
|
||||
gametic++;
|
||||
|
||||
// modify command for duplicated tics
|
||||
TicdupSquash(set);
|
||||
}
|
||||
|
||||
NetUpdate(); // check for new console commands
|
||||
}
|
||||
}
|
||||
|
||||
void D_RegisterLoopCallbacks(loop_interface_t *i)
|
||||
{
|
||||
loop_interface = i;
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Main loop stuff.
|
||||
//
|
||||
|
||||
#ifndef __D_LOOP__
|
||||
#define __D_LOOP__
|
||||
|
||||
#include "net_defs.h"
|
||||
|
||||
// Callback function invoked while waiting for the netgame to start.
|
||||
// The callback is invoked when new players are ready. The callback
|
||||
// should return true, or return false to abort startup.
|
||||
|
||||
typedef boolean (*netgame_startup_callback_t)(int ready_players,
|
||||
int num_players);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Read events from the event queue, and process them.
|
||||
|
||||
void (*ProcessEvents)();
|
||||
|
||||
// Given the current input state, fill in the fields of the specified
|
||||
// ticcmd_t structure with data for a new tic.
|
||||
|
||||
void (*BuildTiccmd)(ticcmd_t *cmd, int maketic);
|
||||
|
||||
// Advance the game forward one tic, using the specified player input.
|
||||
|
||||
void (*RunTic)(ticcmd_t *cmds, boolean *ingame);
|
||||
|
||||
// Run the menu (runs independently of the game).
|
||||
|
||||
void (*RunMenu)();
|
||||
} loop_interface_t;
|
||||
|
||||
// Register callback functions for the main loop code to use.
|
||||
void D_RegisterLoopCallbacks(loop_interface_t *i);
|
||||
|
||||
// Create any new ticcmds and broadcast to other players.
|
||||
void NetUpdate (void);
|
||||
|
||||
// Broadcasts special packets to other players
|
||||
// to notify of game exit
|
||||
void D_QuitNetGame (void);
|
||||
|
||||
//? how many ticks to run?
|
||||
void TryRunTics (void);
|
||||
|
||||
// Called at start of game loop to initialize timers
|
||||
void D_StartGameLoop(void);
|
||||
|
||||
// Initialize networking code and connect to server.
|
||||
|
||||
boolean D_InitNetGame(net_connect_data_t *connect_data);
|
||||
|
||||
// Start game with specified settings. The structure will be updated
|
||||
// with the actual settings for the game.
|
||||
|
||||
void D_StartNetGame(net_gamesettings_t *settings,
|
||||
netgame_startup_callback_t callback);
|
||||
|
||||
extern boolean singletics;
|
||||
extern int gametic, ticdup;
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// System specific interface stuff.
|
||||
//
|
||||
|
||||
#ifndef __D_MAIN__
|
||||
#define __D_MAIN__
|
||||
|
||||
#include "doomdef.h"
|
||||
|
||||
// Read events from all input devices
|
||||
|
||||
void D_ProcessEvents (void);
|
||||
|
||||
|
||||
//
|
||||
// BASE LEVEL
|
||||
//
|
||||
void D_PageTicker (void);
|
||||
void D_PageDrawer (void);
|
||||
void D_AdvanceDemo (void);
|
||||
void D_DoAdvanceDemo (void);
|
||||
void D_StartTitle (void);
|
||||
|
||||
void D_DoomMain (void);
|
||||
void D_DoomTick (void);
|
||||
|
||||
//
|
||||
// GLOBAL VARIABLES
|
||||
//
|
||||
|
||||
extern gameaction_t gameaction;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,208 @@
|
|||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Functions and definitions relating to the game type and operational
|
||||
// mode.
|
||||
//
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "d_mode.h"
|
||||
|
||||
// Valid game mode/mission combinations, with the number of
|
||||
// episodes/maps for each.
|
||||
|
||||
static struct
|
||||
{
|
||||
GameMission_t mission;
|
||||
GameMode_t mode;
|
||||
int episode;
|
||||
int map;
|
||||
} valid_modes[] = {
|
||||
{ pack_chex, shareware, 1, 5 },
|
||||
{ doom, shareware, 1, 9 },
|
||||
{ doom, registered, 3, 9 },
|
||||
{ doom, retail, 4, 9 },
|
||||
{ doom2, commercial, 1, 32 },
|
||||
{ pack_tnt, commercial, 1, 32 },
|
||||
{ pack_plut, commercial, 1, 32 },
|
||||
{ pack_hacx, commercial, 1, 32 },
|
||||
{ heretic, shareware, 1, 9 },
|
||||
{ heretic, registered, 3, 9 },
|
||||
{ heretic, retail, 5, 9 },
|
||||
{ hexen, commercial, 1, 60 },
|
||||
{ strife, commercial, 1, 34 },
|
||||
};
|
||||
|
||||
// Check that a gamemode+gamemission received over the network is valid.
|
||||
|
||||
boolean D_ValidGameMode(GameMission_t mission, GameMode_t mode)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i=0; i<arrlen(valid_modes); ++i)
|
||||
{
|
||||
if (valid_modes[i].mode == mode && valid_modes[i].mission == mission)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean D_ValidEpisodeMap(GameMission_t mission, GameMode_t mode,
|
||||
int episode, int map)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Hacks for Heretic secret episodes
|
||||
|
||||
if (mission == heretic)
|
||||
{
|
||||
if (mode == retail && episode == 6)
|
||||
{
|
||||
return map >= 1 && map <= 3;
|
||||
}
|
||||
else if (mode == registered && episode == 4)
|
||||
{
|
||||
return map == 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the table entry for this mission/mode combination.
|
||||
|
||||
for (i=0; i<arrlen(valid_modes); ++i)
|
||||
{
|
||||
if (mission == valid_modes[i].mission
|
||||
&& mode == valid_modes[i].mode)
|
||||
{
|
||||
return episode >= 1 && episode <= valid_modes[i].episode
|
||||
&& map >= 1 && map <= valid_modes[i].map;
|
||||
}
|
||||
}
|
||||
|
||||
// Unknown mode/mission combination
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the number of valid episodes for the specified mission/mode.
|
||||
|
||||
int D_GetNumEpisodes(GameMission_t mission, GameMode_t mode)
|
||||
{
|
||||
int episode;
|
||||
|
||||
episode = 1;
|
||||
|
||||
while (D_ValidEpisodeMap(mission, mode, episode, 1))
|
||||
{
|
||||
++episode;
|
||||
}
|
||||
|
||||
return episode - 1;
|
||||
}
|
||||
|
||||
// Table of valid versions
|
||||
|
||||
static struct {
|
||||
GameMission_t mission;
|
||||
GameVersion_t version;
|
||||
} valid_versions[] = {
|
||||
{ doom, exe_doom_1_9 },
|
||||
{ doom, exe_hacx },
|
||||
{ doom, exe_ultimate },
|
||||
{ doom, exe_final },
|
||||
{ doom, exe_final2 },
|
||||
{ doom, exe_chex },
|
||||
{ heretic, exe_heretic_1_3 },
|
||||
{ hexen, exe_hexen_1_1 },
|
||||
{ strife, exe_strife_1_2 },
|
||||
{ strife, exe_strife_1_31 },
|
||||
};
|
||||
|
||||
boolean D_ValidGameVersion(GameMission_t mission, GameVersion_t version)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
// All Doom variants can use the Doom versions.
|
||||
|
||||
if (mission == doom2 || mission == pack_plut || mission == pack_tnt
|
||||
|| mission == pack_hacx || mission == pack_chex)
|
||||
{
|
||||
mission = doom;
|
||||
}
|
||||
|
||||
for (i=0; i<arrlen(valid_versions); ++i)
|
||||
{
|
||||
if (valid_versions[i].mission == mission
|
||||
&& valid_versions[i].version == version)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Does this mission type use ExMy form, rather than MAPxy form?
|
||||
|
||||
boolean D_IsEpisodeMap(GameMission_t mission)
|
||||
{
|
||||
switch (mission)
|
||||
{
|
||||
case doom:
|
||||
case heretic:
|
||||
case pack_chex:
|
||||
return true;
|
||||
|
||||
case none:
|
||||
case hexen:
|
||||
case doom2:
|
||||
case pack_hacx:
|
||||
case pack_tnt:
|
||||
case pack_plut:
|
||||
case strife:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
char *D_GameMissionString(GameMission_t mission)
|
||||
{
|
||||
switch (mission)
|
||||
{
|
||||
case none:
|
||||
default:
|
||||
return "none";
|
||||
case doom:
|
||||
return "doom";
|
||||
case doom2:
|
||||
return "doom2";
|
||||
case pack_tnt:
|
||||
return "tnt";
|
||||
case pack_plut:
|
||||
return "plutonia";
|
||||
case pack_hacx:
|
||||
return "hacx";
|
||||
case pack_chex:
|
||||
return "chex";
|
||||
case heretic:
|
||||
return "heretic";
|
||||
case hexen:
|
||||
return "hexen";
|
||||
case strife:
|
||||
return "strife";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Functions and definitions relating to the game type and operational
|
||||
// mode.
|
||||
//
|
||||
|
||||
#ifndef __D_MODE__
|
||||
#define __D_MODE__
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
// The "mission" controls what game we are playing.
|
||||
|
||||
typedef enum
|
||||
{
|
||||
doom, // Doom 1
|
||||
doom2, // Doom 2
|
||||
pack_tnt, // Final Doom: TNT: Evilution
|
||||
pack_plut, // Final Doom: The Plutonia Experiment
|
||||
pack_chex, // Chex Quest (modded doom)
|
||||
pack_hacx, // Hacx (modded doom2)
|
||||
heretic, // Heretic
|
||||
hexen, // Hexen
|
||||
strife, // Strife
|
||||
|
||||
none
|
||||
} GameMission_t;
|
||||
|
||||
// The "mode" allows more accurate specification of the game mode we are
|
||||
// in: eg. shareware vs. registered. So doom1.wad and doom.wad are the
|
||||
// same mission, but a different mode.
|
||||
|
||||
typedef enum
|
||||
{
|
||||
shareware, // Doom/Heretic shareware
|
||||
registered, // Doom/Heretic registered
|
||||
commercial, // Doom II/Hexen
|
||||
retail, // Ultimate Doom
|
||||
indetermined // Unknown.
|
||||
} GameMode_t;
|
||||
|
||||
// What version are we emulating?
|
||||
|
||||
typedef enum
|
||||
{
|
||||
exe_doom_1_2, // Doom 1.2: shareware and registered
|
||||
exe_doom_1_666, // Doom 1.666: for shareware, registered and commercial
|
||||
exe_doom_1_7, // Doom 1.7/1.7a: "
|
||||
exe_doom_1_8, // Doom 1.8: "
|
||||
exe_doom_1_9, // Doom 1.9: "
|
||||
exe_hacx, // Hacx
|
||||
exe_ultimate, // Ultimate Doom (retail)
|
||||
exe_final, // Final Doom
|
||||
exe_final2, // Final Doom (alternate exe)
|
||||
exe_chex, // Chex Quest executable (based on Final Doom)
|
||||
|
||||
exe_heretic_1_3, // Heretic 1.3
|
||||
|
||||
exe_hexen_1_1, // Hexen 1.1
|
||||
exe_strife_1_2, // Strife v1.2
|
||||
exe_strife_1_31 // Strife v1.31
|
||||
} GameVersion_t;
|
||||
|
||||
// Skill level.
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sk_noitems = -1, // the "-skill 0" hack
|
||||
sk_baby = 0,
|
||||
sk_easy,
|
||||
sk_medium,
|
||||
sk_hard,
|
||||
sk_nightmare
|
||||
} skill_t;
|
||||
|
||||
boolean D_ValidGameMode(GameMission_t mission, GameMode_t mode);
|
||||
boolean D_ValidGameVersion(GameMission_t mission, GameVersion_t version);
|
||||
boolean D_ValidEpisodeMap(GameMission_t mission, GameMode_t mode,
|
||||
int episode, int map);
|
||||
int D_GetNumEpisodes(GameMission_t mission, GameMode_t mode);
|
||||
boolean D_IsEpisodeMap(GameMission_t mission);
|
||||
char *D_GameMissionString(GameMission_t mission);
|
||||
|
||||
#endif /* #ifndef __D_MODE__ */
|
|
@ -0,0 +1,271 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// DOOM Network game communication and protocol,
|
||||
// all OS independend parts.
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "d_main.h"
|
||||
#include "m_argv.h"
|
||||
#include "m_menu.h"
|
||||
#include "m_misc.h"
|
||||
#include "i_system.h"
|
||||
#include "i_timer.h"
|
||||
#include "i_video.h"
|
||||
#include "g_game.h"
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "w_checksum.h"
|
||||
#include "w_wad.h"
|
||||
|
||||
#include "d_loop.h"
|
||||
|
||||
ticcmd_t *netcmds;
|
||||
|
||||
// Called when a player leaves the game
|
||||
|
||||
static void PlayerQuitGame(player_t *player)
|
||||
{
|
||||
static char exitmsg[80];
|
||||
unsigned int player_num;
|
||||
|
||||
player_num = player - players;
|
||||
|
||||
// Do this the same way as Vanilla Doom does, to allow dehacked
|
||||
// replacements of this message
|
||||
|
||||
M_StringCopy(exitmsg, "Player 1 left the game",
|
||||
sizeof(exitmsg));
|
||||
|
||||
exitmsg[7] += player_num;
|
||||
|
||||
playeringame[player_num] = false;
|
||||
players[consoleplayer].message = exitmsg;
|
||||
|
||||
// TODO: check if it is sensible to do this:
|
||||
|
||||
if (demorecording)
|
||||
{
|
||||
G_CheckDemoStatus ();
|
||||
}
|
||||
}
|
||||
|
||||
static void RunTic(ticcmd_t *cmds, boolean *ingame)
|
||||
{
|
||||
extern boolean advancedemo;
|
||||
unsigned int i;
|
||||
|
||||
// Check for player quits.
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
if (!demoplayback && playeringame[i] && !ingame[i])
|
||||
{
|
||||
PlayerQuitGame(&players[i]);
|
||||
}
|
||||
}
|
||||
|
||||
netcmds = cmds;
|
||||
|
||||
// check that there are players in the game. if not, we cannot
|
||||
// run a tic.
|
||||
|
||||
if (advancedemo)
|
||||
D_DoAdvanceDemo ();
|
||||
|
||||
G_Ticker ();
|
||||
}
|
||||
|
||||
static loop_interface_t doom_loop_interface = {
|
||||
D_ProcessEvents,
|
||||
G_BuildTiccmd,
|
||||
RunTic,
|
||||
M_Ticker
|
||||
};
|
||||
|
||||
|
||||
// Load game settings from the specified structure and
|
||||
// set global variables.
|
||||
|
||||
static void LoadGameSettings(net_gamesettings_t *settings)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
deathmatch = settings->deathmatch;
|
||||
startepisode = settings->episode;
|
||||
startmap = settings->map;
|
||||
startskill = settings->skill;
|
||||
startloadgame = settings->loadgame;
|
||||
lowres_turn = settings->lowres_turn;
|
||||
nomonsters = settings->nomonsters;
|
||||
fastparm = settings->fast_monsters;
|
||||
respawnparm = settings->respawn_monsters;
|
||||
timelimit = settings->timelimit;
|
||||
consoleplayer = settings->consoleplayer;
|
||||
|
||||
if (lowres_turn)
|
||||
{
|
||||
ES_infof("Turning resolution is reduced; this is probably "
|
||||
"because there is a client recording a Vanilla demo.\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
playeringame[i] = i < settings->num_players;
|
||||
}
|
||||
}
|
||||
|
||||
// Save the game settings from global variables to the specified
|
||||
// game settings structure.
|
||||
|
||||
static void SaveGameSettings(net_gamesettings_t *settings)
|
||||
{
|
||||
// Fill in game settings structure with appropriate parameters
|
||||
// for the new game
|
||||
|
||||
settings->deathmatch = deathmatch;
|
||||
settings->episode = startepisode;
|
||||
settings->map = startmap;
|
||||
settings->skill = startskill;
|
||||
settings->loadgame = startloadgame;
|
||||
settings->gameversion = gameversion;
|
||||
settings->nomonsters = nomonsters;
|
||||
settings->fast_monsters = fastparm;
|
||||
settings->respawn_monsters = respawnparm;
|
||||
settings->timelimit = timelimit;
|
||||
|
||||
settings->lowres_turn = M_CheckParm("-record") > 0
|
||||
&& M_CheckParm("-longtics") == 0;
|
||||
}
|
||||
|
||||
static void InitConnectData(net_connect_data_t *connect_data)
|
||||
{
|
||||
connect_data->max_players = MAXPLAYERS;
|
||||
connect_data->drone = false;
|
||||
|
||||
//!
|
||||
// @category net
|
||||
//
|
||||
// Run as the left screen in three screen mode.
|
||||
//
|
||||
|
||||
if (M_CheckParm("-left") > 0)
|
||||
{
|
||||
viewangleoffset = ANG90;
|
||||
connect_data->drone = true;
|
||||
}
|
||||
|
||||
//!
|
||||
// @category net
|
||||
//
|
||||
// Run as the right screen in three screen mode.
|
||||
//
|
||||
|
||||
if (M_CheckParm("-right") > 0)
|
||||
{
|
||||
viewangleoffset = ANG270;
|
||||
connect_data->drone = true;
|
||||
}
|
||||
|
||||
//
|
||||
// Connect data
|
||||
//
|
||||
|
||||
// Game type fields:
|
||||
|
||||
connect_data->gamemode = gamemode;
|
||||
connect_data->gamemission = gamemission;
|
||||
|
||||
// Are we recording a demo? Possibly set lowres turn mode
|
||||
|
||||
connect_data->lowres_turn = M_CheckParm("-record") > 0
|
||||
&& M_CheckParm("-longtics") == 0;
|
||||
|
||||
// Read checksums of our WAD directory and dehacked information
|
||||
|
||||
W_Checksum(connect_data->wad_sha1sum);
|
||||
|
||||
// Are we playing with the Freedoom IWAD?
|
||||
|
||||
connect_data->is_freedoom = W_CheckNumForName("FREEDOOM") >= 0;
|
||||
}
|
||||
|
||||
void D_ConnectNetGame(void)
|
||||
{
|
||||
net_connect_data_t connect_data;
|
||||
|
||||
InitConnectData(&connect_data);
|
||||
netgame = D_InitNetGame(&connect_data);
|
||||
|
||||
//!
|
||||
// @category net
|
||||
//
|
||||
// Start the game playing as though in a netgame with a single
|
||||
// player. This can also be used to play back single player netgame
|
||||
// demos.
|
||||
//
|
||||
|
||||
if (M_CheckParm("-solo-net") > 0)
|
||||
{
|
||||
netgame = true;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// D_CheckNetGame
|
||||
// Works out player numbers among the net participants
|
||||
//
|
||||
void D_CheckNetGame (void)
|
||||
{
|
||||
net_gamesettings_t settings;
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
autostart = true;
|
||||
}
|
||||
|
||||
D_RegisterLoopCallbacks(&doom_loop_interface);
|
||||
|
||||
SaveGameSettings(&settings);
|
||||
D_StartNetGame(&settings, NULL);
|
||||
LoadGameSettings(&settings);
|
||||
|
||||
ES_debugf("startskill %i deathmatch: %i startmap: %i startepisode: %i\n",
|
||||
startskill, deathmatch, startmap, startepisode);
|
||||
|
||||
ES_debugf("player %i of %i (%i nodes)\n",
|
||||
consoleplayer+1, settings.num_players, settings.num_players);
|
||||
|
||||
// Show players here; the server might have specified a time limit
|
||||
|
||||
if (timelimit > 0 && deathmatch)
|
||||
{
|
||||
// Gross hack to work like Vanilla:
|
||||
|
||||
if (timelimit == 20 && M_CheckParm("-avg"))
|
||||
{
|
||||
ES_debugf("Austin Virtual Gaming: Levels will end "
|
||||
"after 20 minutes\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
ES_debugf("Levels will end after %d minute%.2s.\n", timelimit, (timelimit > 1) ? "s" : "");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __D_PLAYER__
|
||||
#define __D_PLAYER__
|
||||
|
||||
// The player data structure depends on a number
|
||||
// of other structs: items (internal inventory),
|
||||
// animation states (closely tied to the sprites
|
||||
// used to represent them, unfortunately).
|
||||
#include "d_items.h"
|
||||
#include "p_pspr.h"
|
||||
|
||||
// In addition, the player is just a special
|
||||
// case of the generic moving object/actor.
|
||||
#include "p_mobj.h"
|
||||
|
||||
// Finally, for odd reasons, the player input
|
||||
// is buffered within the player data struct,
|
||||
// as commands per game tick.
|
||||
#include "d_ticcmd.h"
|
||||
|
||||
#include "net_defs.h"
|
||||
|
||||
//
|
||||
// Player states.
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
// Playing or camping.
|
||||
PST_LIVE,
|
||||
// Dead on the ground, view follows killer.
|
||||
PST_DEAD,
|
||||
// Ready to restart/respawn???
|
||||
PST_REBORN
|
||||
|
||||
} playerstate_t;
|
||||
|
||||
//
|
||||
// Player internal flags, for cheats and debug.
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
// No clipping, walk through barriers.
|
||||
CF_NOCLIP = 1,
|
||||
// No damage, no health loss.
|
||||
CF_GODMODE = 2,
|
||||
// Not really a cheat, just a debug aid.
|
||||
CF_NOMOMENTUM = 4
|
||||
|
||||
} cheat_t;
|
||||
|
||||
//
|
||||
// Extended player object info: player_t
|
||||
//
|
||||
typedef struct player_s
|
||||
{
|
||||
mobj_t* mo;
|
||||
playerstate_t playerstate;
|
||||
ticcmd_t cmd;
|
||||
|
||||
// Determine POV,
|
||||
// including viewpoint bobbing during movement.
|
||||
// Focal origin above r.z
|
||||
fixed_t viewz;
|
||||
// Base height above floor for viewz.
|
||||
fixed_t viewheight;
|
||||
// Bob/squat speed.
|
||||
fixed_t deltaviewheight;
|
||||
// bounded/scaled total momentum.
|
||||
fixed_t bob;
|
||||
|
||||
// This is only used between levels,
|
||||
// mo->health is used during levels.
|
||||
int health;
|
||||
int armorpoints;
|
||||
// Armor type is 0-2.
|
||||
int armortype;
|
||||
|
||||
// Power ups. invinc and invis are tic counters.
|
||||
int powers[NUMPOWERS];
|
||||
boolean cards[NUMCARDS];
|
||||
boolean backpack;
|
||||
|
||||
// Frags, kills of other players.
|
||||
int frags[MAXPLAYERS];
|
||||
weapontype_t readyweapon;
|
||||
|
||||
// Is wp_nochange if not changing.
|
||||
weapontype_t pendingweapon;
|
||||
|
||||
boolean weaponowned[NUMWEAPONS];
|
||||
int ammo[NUMAMMO];
|
||||
int maxammo[NUMAMMO];
|
||||
|
||||
// True if button down last tic.
|
||||
int attackdown;
|
||||
int usedown;
|
||||
|
||||
// Bit flags, for cheats and debug.
|
||||
// See cheat_t, above.
|
||||
int cheats;
|
||||
|
||||
// Refired shots are less accurate.
|
||||
int refire;
|
||||
|
||||
// For intermission stats.
|
||||
int killcount;
|
||||
int itemcount;
|
||||
int secretcount;
|
||||
|
||||
// Hint messages.
|
||||
char* message;
|
||||
|
||||
// For screen flashing (red or bright).
|
||||
int damagecount;
|
||||
int bonuscount;
|
||||
|
||||
// Who did damage (NULL for floors/ceilings).
|
||||
mobj_t* attacker;
|
||||
|
||||
// So gun flashes light up areas.
|
||||
int extralight;
|
||||
|
||||
// Current PLAYPAL, ???
|
||||
// can be set to REDCOLORMAP for pain, etc.
|
||||
int fixedcolormap;
|
||||
|
||||
// Player skin colorshift,
|
||||
// 0-3 for which color to draw player.
|
||||
int colormap;
|
||||
|
||||
// Overlay view sprites (gun, etc).
|
||||
pspdef_t psprites[NUMPSPRITES];
|
||||
|
||||
// True if secret level has been done.
|
||||
boolean didsecret;
|
||||
|
||||
} player_t;
|
||||
|
||||
//
|
||||
// INTERMISSION
|
||||
// Structure passed e.g. to WI_Start(wb)
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
boolean in; // whether the player is in game
|
||||
|
||||
// Player stats, kills, collected items etc.
|
||||
int skills;
|
||||
int sitems;
|
||||
int ssecret;
|
||||
int stime;
|
||||
int frags[4];
|
||||
int score; // current score on entry, modified on return
|
||||
|
||||
} wbplayerstruct_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int epsd; // episode # (0-2)
|
||||
|
||||
// if true, splash the secret level
|
||||
boolean didsecret;
|
||||
|
||||
// previous and next levels, origin 0
|
||||
int last;
|
||||
int next;
|
||||
|
||||
int maxkills;
|
||||
int maxitems;
|
||||
int maxsecret;
|
||||
int maxfrags;
|
||||
|
||||
// the par time
|
||||
int partime;
|
||||
|
||||
// index of this player in game
|
||||
int pnum;
|
||||
|
||||
wbplayerstruct_t plyr[MAXPLAYERS];
|
||||
|
||||
} wbstartstruct_t;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Typedefs related to to textures etc.,
|
||||
// isolated here to make it easier separating modules.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __D_TEXTUR__
|
||||
#define __D_TEXTUR__
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
//
|
||||
// Flats?
|
||||
//
|
||||
// a pic is an unmasked block of pixels
|
||||
typedef struct
|
||||
{
|
||||
byte width;
|
||||
byte height;
|
||||
byte data;
|
||||
} pic_t;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// MapObj data. Map Objects or mobjs are actors, entities,
|
||||
// thinker, take-your-pick... anything that moves, acts, or
|
||||
// suffers state changes of more or less violent nature.
|
||||
//
|
||||
|
||||
#ifndef __D_THINK__
|
||||
#define __D_THINK__
|
||||
|
||||
//
|
||||
// Experimental stuff.
|
||||
// To compile this as "ANSI C with classes"
|
||||
// we will need to handle the various
|
||||
// action functions cleanly.
|
||||
//
|
||||
typedef void (*actionf_v)();
|
||||
typedef void (*actionf_p1)( void* );
|
||||
typedef void (*actionf_p2)( void*, void* );
|
||||
|
||||
typedef union
|
||||
{
|
||||
actionf_v acv;
|
||||
actionf_p1 acp1;
|
||||
actionf_p2 acp2;
|
||||
|
||||
} actionf_t;
|
||||
|
||||
// Historically, "think_t" is yet another
|
||||
// function pointer to a routine to handle
|
||||
// an actor.
|
||||
typedef actionf_t think_t;
|
||||
|
||||
// Doubly linked list of actors.
|
||||
typedef struct thinker_s
|
||||
{
|
||||
struct thinker_s* prev;
|
||||
struct thinker_s* next;
|
||||
think_t function;
|
||||
|
||||
} thinker_t;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 1993-2008 Raven Software
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// System specific interface stuff.
|
||||
//
|
||||
|
||||
#ifndef __D_TICCMD__
|
||||
#define __D_TICCMD__
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
// The data sampled per tick (single player)
|
||||
// and transmitted to other peers (multiplayer).
|
||||
// Mainly movements/button commands per game tick,
|
||||
// plus a checksum for internal state consistency.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
signed char forwardmove; // *2048 for move
|
||||
signed char sidemove; // *2048 for move
|
||||
short angleturn; // <<16 for angle delta
|
||||
byte chatchar;
|
||||
byte buttons;
|
||||
// villsa [STRIFE] according to the asm,
|
||||
// consistancy is a short, not a byte
|
||||
byte consistancy; // checks for net game
|
||||
|
||||
// villsa - Strife specific:
|
||||
|
||||
byte buttons2;
|
||||
int inventory;
|
||||
|
||||
// Heretic/Hexen specific:
|
||||
|
||||
byte lookfly; // look/fly up/down/centering
|
||||
byte arti; // artitype_t to use
|
||||
} ticcmd_t;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,196 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// all external data is defined here
|
||||
// most of the data is loaded into different structures at run time
|
||||
// some internal structures shared by many modules are here
|
||||
//
|
||||
|
||||
#ifndef __DOOMDATA__
|
||||
#define __DOOMDATA__
|
||||
|
||||
// The most basic types we use, portability.
|
||||
#include "doomtype.h"
|
||||
|
||||
// Some global defines, that configure the game.
|
||||
#include "doomdef.h"
|
||||
|
||||
//
|
||||
// Map level types.
|
||||
// The following data structures define the persistent format
|
||||
// used in the lumps of the WAD files.
|
||||
//
|
||||
|
||||
// Lump order in a map WAD: each map needs a couple of lumps
|
||||
// to provide a complete scene geometry description.
|
||||
enum
|
||||
{
|
||||
ML_LABEL, // A separator, name, ExMx or MAPxx
|
||||
ML_THINGS, // Monsters, items..
|
||||
ML_LINEDEFS, // LineDefs, from editing
|
||||
ML_SIDEDEFS, // SideDefs, from editing
|
||||
ML_VERTEXES, // Vertices, edited and BSP splits generated
|
||||
ML_SEGS, // LineSegs, from LineDefs split by BSP
|
||||
ML_SSECTORS, // SubSectors, list of LineSegs
|
||||
ML_NODES, // BSP nodes
|
||||
ML_SECTORS, // Sectors, from editing
|
||||
ML_REJECT, // LUT, sector-sector visibility
|
||||
ML_BLOCKMAP // LUT, motion clipping, walls/grid element
|
||||
};
|
||||
|
||||
|
||||
// A single Vertex.
|
||||
typedef struct
|
||||
{
|
||||
short x;
|
||||
short y;
|
||||
} PACKEDATTR mapvertex_t;
|
||||
|
||||
|
||||
// A SideDef, defining the visual appearance of a wall,
|
||||
// by setting textures and offsets.
|
||||
typedef struct
|
||||
{
|
||||
short textureoffset;
|
||||
short rowoffset;
|
||||
char toptexture[8];
|
||||
char bottomtexture[8];
|
||||
char midtexture[8];
|
||||
// Front sector, towards viewer.
|
||||
short sector;
|
||||
} PACKEDATTR mapsidedef_t;
|
||||
|
||||
// A LineDef, as used for editing, and as input
|
||||
// to the BSP builder.
|
||||
typedef struct
|
||||
{
|
||||
short v1;
|
||||
short v2;
|
||||
short flags;
|
||||
short special;
|
||||
short tag;
|
||||
// sidenum[1] will be -1 if one sided
|
||||
short sidenum[2];
|
||||
} PACKEDATTR maplinedef_t;
|
||||
|
||||
//
|
||||
// LineDef attributes.
|
||||
//
|
||||
|
||||
// Solid, is an obstacle.
|
||||
#define ML_BLOCKING 1
|
||||
|
||||
// Blocks monsters only.
|
||||
#define ML_BLOCKMONSTERS 2
|
||||
|
||||
// Backside will not be present at all
|
||||
// if not two sided.
|
||||
#define ML_TWOSIDED 4
|
||||
|
||||
// If a texture is pegged, the texture will have
|
||||
// the end exposed to air held constant at the
|
||||
// top or bottom of the texture (stairs or pulled
|
||||
// down things) and will move with a height change
|
||||
// of one of the neighbor sectors.
|
||||
// Unpegged textures allways have the first row of
|
||||
// the texture at the top pixel of the line for both
|
||||
// top and bottom textures (use next to windows).
|
||||
|
||||
// upper texture unpegged
|
||||
#define ML_DONTPEGTOP 8
|
||||
|
||||
// lower texture unpegged
|
||||
#define ML_DONTPEGBOTTOM 16
|
||||
|
||||
// In AutoMap: don't map as two sided: IT'S A SECRET!
|
||||
#define ML_SECRET 32
|
||||
|
||||
// Sound rendering: don't let sound cross two of these.
|
||||
#define ML_SOUNDBLOCK 64
|
||||
|
||||
// Don't draw on the automap at all.
|
||||
#define ML_DONTDRAW 128
|
||||
|
||||
// Set if already seen, thus drawn in automap.
|
||||
#define ML_MAPPED 256
|
||||
|
||||
// Sector definition, from editing.
|
||||
typedef struct
|
||||
{
|
||||
short floorheight;
|
||||
short ceilingheight;
|
||||
char floorpic[8];
|
||||
char ceilingpic[8];
|
||||
short lightlevel;
|
||||
short special;
|
||||
short tag;
|
||||
} PACKEDATTR mapsector_t;
|
||||
|
||||
// SubSector, as generated by BSP.
|
||||
typedef struct
|
||||
{
|
||||
short numsegs;
|
||||
// Index of first one, segs are stored sequentially.
|
||||
short firstseg;
|
||||
} PACKEDATTR mapsubsector_t;
|
||||
|
||||
|
||||
// LineSeg, generated by splitting LineDefs
|
||||
// using partition lines selected by BSP builder.
|
||||
typedef struct
|
||||
{
|
||||
short v1;
|
||||
short v2;
|
||||
short angle;
|
||||
short linedef;
|
||||
short side;
|
||||
short offset;
|
||||
} PACKEDATTR mapseg_t;
|
||||
|
||||
// BSP node structure.
|
||||
|
||||
// Indicate a leaf.
|
||||
#define NF_SUBSECTOR 0x8000
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Partition line from (x,y) to x+dx,y+dy)
|
||||
short x;
|
||||
short y;
|
||||
short dx;
|
||||
short dy;
|
||||
|
||||
// Bounding box for each child,
|
||||
// clip against view frustum.
|
||||
short bbox[2][4];
|
||||
|
||||
// If NF_SUBSECTOR its a subsector,
|
||||
// else it's a node of another subtree.
|
||||
unsigned short children[2];
|
||||
|
||||
} PACKEDATTR mapnode_t;
|
||||
|
||||
// Thing definition, position, orientation and type,
|
||||
// plus skill/visibility flags and attributes.
|
||||
typedef struct
|
||||
{
|
||||
short x;
|
||||
short y;
|
||||
short angle;
|
||||
short type;
|
||||
short options;
|
||||
} PACKEDATTR mapthing_t;
|
||||
|
||||
#endif // __DOOMDATA__
|
|
@ -0,0 +1,159 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Internally used data structures for virtually everything,
|
||||
// lots of other stuff.
|
||||
//
|
||||
|
||||
#ifndef __DOOMDEF__
|
||||
#define __DOOMDEF__
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "i_timer.h"
|
||||
#include "d_mode.h"
|
||||
|
||||
//
|
||||
// Global parameters/defines.
|
||||
//
|
||||
// DOOM version
|
||||
#define DOOM_VERSION 109
|
||||
|
||||
// Version code for cph's longtics hack ("v1.91")
|
||||
#define DOOM_191_VERSION 111
|
||||
|
||||
// If rangecheck is undefined,
|
||||
// most parameter validation debugging code will not be compiled
|
||||
#define RANGECHECK
|
||||
|
||||
// The maximum number of players, multiplayer/networking.
|
||||
#define MAXPLAYERS 4
|
||||
|
||||
// The current state of the game: whether we are
|
||||
// playing, gazing at the intermission screen,
|
||||
// the game final animation, or a demo.
|
||||
typedef enum
|
||||
{
|
||||
GS_LEVEL,
|
||||
GS_INTERMISSION,
|
||||
GS_FINALE,
|
||||
GS_DEMOSCREEN,
|
||||
} gamestate_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ga_nothing,
|
||||
ga_loadlevel,
|
||||
ga_newgame,
|
||||
ga_loadgame,
|
||||
ga_savegame,
|
||||
ga_playdemo,
|
||||
ga_completed,
|
||||
ga_victory,
|
||||
ga_worlddone,
|
||||
ga_screenshot
|
||||
} gameaction_t;
|
||||
|
||||
//
|
||||
// Difficulty/skill settings/filters.
|
||||
//
|
||||
|
||||
// Skill flags.
|
||||
#define MTF_EASY 1
|
||||
#define MTF_NORMAL 2
|
||||
#define MTF_HARD 4
|
||||
|
||||
// Deaf monsters/do not react to sound.
|
||||
#define MTF_AMBUSH 8
|
||||
|
||||
//
|
||||
// Key cards.
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
it_bluecard,
|
||||
it_yellowcard,
|
||||
it_redcard,
|
||||
it_blueskull,
|
||||
it_yellowskull,
|
||||
it_redskull,
|
||||
|
||||
NUMCARDS
|
||||
|
||||
} card_t;
|
||||
|
||||
// The defined weapons,
|
||||
// including a marker indicating
|
||||
// user has not changed weapon.
|
||||
typedef enum
|
||||
{
|
||||
wp_fist,
|
||||
wp_pistol,
|
||||
wp_shotgun,
|
||||
wp_chaingun,
|
||||
wp_missile,
|
||||
wp_plasma,
|
||||
wp_bfg,
|
||||
wp_chainsaw,
|
||||
wp_supershotgun,
|
||||
|
||||
NUMWEAPONS,
|
||||
|
||||
// No pending weapon change.
|
||||
wp_nochange
|
||||
|
||||
} weapontype_t;
|
||||
|
||||
// Ammunition types defined.
|
||||
typedef enum
|
||||
{
|
||||
am_clip, // Pistol / chaingun ammo.
|
||||
am_shell, // Shotgun / double barreled shotgun.
|
||||
am_cell, // Plasma rifle, BFG.
|
||||
am_misl, // Missile launcher.
|
||||
NUMAMMO,
|
||||
am_noammo // Unlimited for chainsaw / fist.
|
||||
|
||||
} ammotype_t;
|
||||
|
||||
// Power up artifacts.
|
||||
typedef enum
|
||||
{
|
||||
pw_invulnerability,
|
||||
pw_strength,
|
||||
pw_invisibility,
|
||||
pw_ironfeet,
|
||||
pw_allmap,
|
||||
pw_infrared,
|
||||
NUMPOWERS
|
||||
|
||||
} powertype_t;
|
||||
|
||||
//
|
||||
// Power up durations,
|
||||
// how many seconds till expiration,
|
||||
// assuming TICRATE is 35 ticks/second.
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
INVULNTICS = (30*TICRATE),
|
||||
INVISTICS = (60*TICRATE),
|
||||
INFRATICS = (120*TICRATE),
|
||||
IRONTICS = (60*TICRATE)
|
||||
|
||||
} powerduration_t;
|
||||
|
||||
#endif // __DOOMDEF__
|
|
@ -0,0 +1,97 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Key definitions
|
||||
//
|
||||
|
||||
#ifndef __DOOMKEYS__
|
||||
#define __DOOMKEYS__
|
||||
|
||||
//
|
||||
// DOOM keyboard definition.
|
||||
// This is the stuff configured by Setup.Exe.
|
||||
// Most key data are simple ascii (uppercased).
|
||||
//
|
||||
#define KEY_RIGHTARROW 0xae
|
||||
#define KEY_LEFTARROW 0xac
|
||||
#define KEY_UPARROW 0xad
|
||||
#define KEY_DOWNARROW 0xaf
|
||||
#define KEY_STRAFE_L 0xa0
|
||||
#define KEY_STRAFE_R 0xa1
|
||||
#define KEY_USE 0xa2
|
||||
#define KEY_FIRE 0xa3
|
||||
#define KEY_ESCAPE 27
|
||||
#define KEY_ENTER 13
|
||||
#define KEY_TAB 9
|
||||
#define KEY_F1 (0x80+0x3b)
|
||||
#define KEY_F2 (0x80+0x3c)
|
||||
#define KEY_F3 (0x80+0x3d)
|
||||
#define KEY_F4 (0x80+0x3e)
|
||||
#define KEY_F5 (0x80+0x3f)
|
||||
#define KEY_F6 (0x80+0x40)
|
||||
#define KEY_F7 (0x80+0x41)
|
||||
#define KEY_F8 (0x80+0x42)
|
||||
#define KEY_F9 (0x80+0x43)
|
||||
#define KEY_F10 (0x80+0x44)
|
||||
#define KEY_F11 (0x80+0x57)
|
||||
#define KEY_F12 (0x80+0x58)
|
||||
|
||||
#define KEY_BACKSPACE 0x7f
|
||||
#define KEY_PAUSE 0xff
|
||||
|
||||
#define KEY_EQUALS 0x3d
|
||||
#define KEY_MINUS 0x2d
|
||||
|
||||
#define KEY_RSHIFT (0x80+0x36)
|
||||
#define KEY_RCTRL (0x80+0x1d)
|
||||
#define KEY_RALT (0x80+0x38)
|
||||
|
||||
#define KEY_LALT KEY_RALT
|
||||
|
||||
// new keys:
|
||||
|
||||
#define KEY_CAPSLOCK (0x80+0x3a)
|
||||
#define KEY_NUMLOCK (0x80+0x45)
|
||||
#define KEY_SCRLCK (0x80+0x46)
|
||||
#define KEY_PRTSCR (0x80+0x59)
|
||||
|
||||
#define KEY_HOME (0x80+0x47)
|
||||
#define KEY_END (0x80+0x4f)
|
||||
#define KEY_PGUP (0x80+0x49)
|
||||
#define KEY_PGDN (0x80+0x51)
|
||||
#define KEY_INS (0x80+0x52)
|
||||
#define KEY_DEL (0x80+0x53)
|
||||
|
||||
#define KEYP_0 0
|
||||
#define KEYP_1 KEY_END
|
||||
#define KEYP_2 KEY_DOWNARROW
|
||||
#define KEYP_3 KEY_PGDN
|
||||
#define KEYP_4 KEY_LEFTARROW
|
||||
#define KEYP_5 '5'
|
||||
#define KEYP_6 KEY_RIGHTARROW
|
||||
#define KEYP_7 KEY_HOME
|
||||
#define KEYP_8 KEY_UPARROW
|
||||
#define KEYP_9 KEY_PGUP
|
||||
|
||||
#define KEYP_DIVIDE '/'
|
||||
#define KEYP_PLUS '+'
|
||||
#define KEYP_MINUS '-'
|
||||
#define KEYP_MULTIPLY '*'
|
||||
#define KEYP_PERIOD 0
|
||||
#define KEYP_EQUALS KEY_EQUALS
|
||||
#define KEYP_ENTER KEY_ENTER
|
||||
|
||||
#endif // __DOOMKEYS__
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Put all global tate variables here.
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "doomstat.h"
|
||||
|
||||
// Game Mode - identify IWAD as shareware, retail etc.
|
||||
GameMode_t gamemode = indetermined;
|
||||
GameMission_t gamemission = doom;
|
||||
GameVersion_t gameversion = exe_final2;
|
||||
char *gamedescription;
|
||||
|
||||
// Set if homebrew PWAD stuff has been added.
|
||||
boolean modifiedgame;
|
|
@ -0,0 +1,281 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// All the global variables that store the internal state.
|
||||
// Theoretically speaking, the internal state of the engine
|
||||
// should be found by looking at the variables collected
|
||||
// here, and every relevant module will have to include
|
||||
// this header file.
|
||||
// In practice, things are a bit messy.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __D_STATE__
|
||||
#define __D_STATE__
|
||||
|
||||
// We need globally shared data structures,
|
||||
// for defining the global state variables.
|
||||
#include "doomdata.h"
|
||||
#include "d_loop.h"
|
||||
|
||||
// We need the playr data structure as well.
|
||||
#include "d_player.h"
|
||||
|
||||
// Game mode/mission
|
||||
#include "d_mode.h"
|
||||
|
||||
#include "net_defs.h"
|
||||
|
||||
|
||||
|
||||
// ------------------------
|
||||
// Command line parameters.
|
||||
//
|
||||
extern boolean nomonsters; // checkparm of -nomonsters
|
||||
extern boolean respawnparm; // checkparm of -respawn
|
||||
extern boolean fastparm; // checkparm of -fast
|
||||
|
||||
extern boolean devparm; // DEBUG: launched with -devparm
|
||||
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Game Mode - identify IWAD as shareware, retail etc.
|
||||
//
|
||||
extern GameMode_t gamemode;
|
||||
extern GameMission_t gamemission;
|
||||
extern GameVersion_t gameversion;
|
||||
extern char *gamedescription;
|
||||
|
||||
// If true, we're using one of the mangled BFG edition IWADs.
|
||||
extern boolean bfgedition;
|
||||
|
||||
// Convenience macro.
|
||||
// 'gamemission' can be equal to pack_chex or pack_hacx, but these are
|
||||
// just modified versions of doom and doom2, and should be interpreted
|
||||
// as the same most of the time.
|
||||
|
||||
#define logical_gamemission \
|
||||
(gamemission == pack_chex ? doom : \
|
||||
gamemission == pack_hacx ? doom2 : gamemission)
|
||||
|
||||
// Set if homebrew PWAD stuff has been added.
|
||||
extern boolean modifiedgame;
|
||||
|
||||
|
||||
// -------------------------------------------
|
||||
// Selected skill type, map etc.
|
||||
//
|
||||
|
||||
// Defaults for menu, methinks.
|
||||
extern skill_t startskill;
|
||||
extern int startepisode;
|
||||
extern int startmap;
|
||||
|
||||
// Savegame slot to load on startup. This is the value provided to
|
||||
// the -loadgame option. If this has not been provided, this is -1.
|
||||
|
||||
extern int startloadgame;
|
||||
|
||||
extern boolean autostart;
|
||||
|
||||
// Selected by user.
|
||||
extern skill_t gameskill;
|
||||
extern int gameepisode;
|
||||
extern int gamemap;
|
||||
|
||||
// If non-zero, exit the level after this number of minutes
|
||||
extern int timelimit;
|
||||
|
||||
// Nightmare mode flag, single player.
|
||||
extern boolean respawnmonsters;
|
||||
|
||||
// Netgame? Only true if >1 player.
|
||||
extern boolean netgame;
|
||||
|
||||
// 0=Cooperative; 1=Deathmatch; 2=Altdeath
|
||||
extern int deathmatch;
|
||||
|
||||
// -------------------------
|
||||
// Internal parameters for sound rendering.
|
||||
// These have been taken from the DOS version,
|
||||
// but are not (yet) supported with Linux
|
||||
// (e.g. no sound volume adjustment with menu.
|
||||
|
||||
// From m_menu.c:
|
||||
// Sound FX volume has default, 0 - 15
|
||||
// Music volume has default, 0 - 15
|
||||
// These are multiplied by 8.
|
||||
extern int sfxVolume;
|
||||
extern int musicVolume;
|
||||
|
||||
// Current music/sfx card - index useless
|
||||
// w/o a reference LUT in a sound module.
|
||||
// Ideally, this would use indices found
|
||||
// in: /usr/include/linux/soundcard.h
|
||||
extern int snd_MusicDevice;
|
||||
extern int snd_SfxDevice;
|
||||
// Config file? Same disclaimer as above.
|
||||
extern int snd_DesiredMusicDevice;
|
||||
extern int snd_DesiredSfxDevice;
|
||||
|
||||
|
||||
// -------------------------
|
||||
// Status flags for refresh.
|
||||
//
|
||||
|
||||
// Depending on view size - no status bar?
|
||||
// Note that there is no way to disable the
|
||||
// status bar explicitely.
|
||||
extern boolean statusbaractive;
|
||||
|
||||
extern boolean automapactive; // In AutoMap mode?
|
||||
extern boolean menuactive; // Menu overlayed?
|
||||
extern boolean paused; // Game Pause?
|
||||
|
||||
|
||||
extern boolean viewactive;
|
||||
|
||||
extern boolean nodrawers;
|
||||
|
||||
|
||||
extern boolean testcontrols;
|
||||
extern int testcontrols_mousespeed;
|
||||
|
||||
|
||||
|
||||
|
||||
// This one is related to the 3-screen display mode.
|
||||
// ANG90 = left side, ANG270 = right
|
||||
extern int viewangleoffset;
|
||||
|
||||
// Player taking events, and displaying.
|
||||
extern int consoleplayer;
|
||||
extern int displayplayer;
|
||||
|
||||
|
||||
// -------------------------------------
|
||||
// Scores, rating.
|
||||
// Statistics on a given map, for intermission.
|
||||
//
|
||||
extern int totalkills;
|
||||
extern int totalitems;
|
||||
extern int totalsecret;
|
||||
|
||||
// Timer, for scores.
|
||||
extern int levelstarttic; // gametic at level start
|
||||
extern int leveltime; // tics in game play for par
|
||||
|
||||
|
||||
|
||||
// --------------------------------------
|
||||
// DEMO playback/recording related stuff.
|
||||
// No demo, there is a human player in charge?
|
||||
// Disable save/end game?
|
||||
extern boolean usergame;
|
||||
|
||||
//?
|
||||
extern boolean demoplayback;
|
||||
extern boolean demorecording;
|
||||
|
||||
// Round angleturn in ticcmds to the nearest 256. This is used when
|
||||
// recording Vanilla demos in netgames.
|
||||
|
||||
extern boolean lowres_turn;
|
||||
|
||||
// Quit after playing a demo from cmdline.
|
||||
extern boolean singledemo;
|
||||
|
||||
|
||||
|
||||
|
||||
//?
|
||||
extern gamestate_t gamestate;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------
|
||||
// Internal parameters, fixed.
|
||||
// These are set by the engine, and not changed
|
||||
// according to user inputs. Partly load from
|
||||
// WAD, partly set at startup time.
|
||||
|
||||
|
||||
|
||||
// Bookkeeping on players - state.
|
||||
extern player_t players[MAXPLAYERS];
|
||||
|
||||
// Alive? Disconnected?
|
||||
extern boolean playeringame[MAXPLAYERS];
|
||||
|
||||
|
||||
// Player spawn spots for deathmatch.
|
||||
#define MAX_DM_STARTS 10
|
||||
extern mapthing_t deathmatchstarts[MAX_DM_STARTS];
|
||||
extern mapthing_t* deathmatch_p;
|
||||
|
||||
// Player spawn spots.
|
||||
extern mapthing_t playerstarts[MAXPLAYERS];
|
||||
|
||||
// Intermission stats.
|
||||
// Parameters for world map / intermission.
|
||||
extern wbstartstruct_t wminfo;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
// Internal parameters, used for engine.
|
||||
//
|
||||
|
||||
// File handling stuff.
|
||||
extern char * savegamedir;
|
||||
extern char basedefault[1024];
|
||||
|
||||
// if true, load all graphics at level load
|
||||
extern boolean precache;
|
||||
|
||||
|
||||
// wipegamestate can be set to -1
|
||||
// to force a wipe on the next draw
|
||||
extern gamestate_t wipegamestate;
|
||||
|
||||
extern int mouseSensitivity;
|
||||
|
||||
extern int bodyqueslot;
|
||||
|
||||
|
||||
|
||||
// Needed to store the number of the dummy sky flat.
|
||||
// Used for rendering,
|
||||
// as well as tracking projectiles etc.
|
||||
extern int skyflatnum;
|
||||
|
||||
|
||||
|
||||
// Netgame stuff (buffers and pointers, i.e. indices).
|
||||
|
||||
|
||||
extern int rndindex;
|
||||
|
||||
extern ticcmd_t *netcmds;
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Simple basic typedefs, isolated here to make it easier
|
||||
// separating modules.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __DOOMTYPE__
|
||||
#define __DOOMTYPE__
|
||||
|
||||
// #define macros to provide functions missing in Windows.
|
||||
// Outside Windows, we use strings.h for str[n]casecmp.
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
//
|
||||
// The packed attribute forces structures to be packed into the minimum
|
||||
// space necessary. If this is not done, the compiler may align structure
|
||||
// fields differently to optimize memory access, inflating the overall
|
||||
// structure size. It is important to use the packed attribute on certain
|
||||
// structures where alignment is important, particularly data read/written
|
||||
// to disk.
|
||||
//
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define PACKEDATTR __attribute__((packed))
|
||||
#else
|
||||
#define PACKEDATTR
|
||||
#endif
|
||||
|
||||
typedef bool boolean;
|
||||
|
||||
typedef uint8_t byte;
|
||||
|
||||
#define DIR_SEPARATOR '/'
|
||||
#define DIR_SEPARATOR_S "/"
|
||||
#define PATH_SEPARATOR ':'
|
||||
|
||||
#define arrlen(array) (sizeof(array) / sizeof(*array))
|
||||
|
||||
#endif
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Globally defined strings.
|
||||
//
|
||||
|
||||
#include "dstrings.h"
|
||||
|
||||
char *doom1_endmsg[] =
|
||||
{
|
||||
"are you sure you want to\nquit this great game?",
|
||||
"please don't leave, there's more\ndemons to toast!",
|
||||
"let's beat it -- this is turning\ninto a bloodbath!",
|
||||
"i wouldn't leave if i were you.\ndos is much worse.",
|
||||
"you're trying to say you like dos\nbetter than me, right?",
|
||||
"don't leave yet -- there's a\ndemon around that corner!",
|
||||
"ya know, next time you come in here\ni'm gonna toast ya.",
|
||||
"go ahead and leave. see if i care.",
|
||||
};
|
||||
|
||||
char *doom2_endmsg[] =
|
||||
{
|
||||
// QuitDOOM II messages
|
||||
"are you sure you want to\nquit this great game?",
|
||||
"you want to quit?\nthen, thou hast lost an eighth!",
|
||||
"don't go now, there's a \ndimensional shambler waiting\nat the dos prompt!",
|
||||
"get outta here and go back\nto your boring programs.",
|
||||
"if i were your boss, i'd \n deathmatch ya in a minute!",
|
||||
"look, bud. you leave now\nand you forfeit your body count!",
|
||||
"just leave. when you come\nback, i'll be waiting with a bat.",
|
||||
"you're lucky i don't smack\nyou for thinking about leaving.",
|
||||
};
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// DOOM strings, by language.
|
||||
//
|
||||
|
||||
#ifndef __DSTRINGS__
|
||||
#define __DSTRINGS__
|
||||
|
||||
// All important printed strings.
|
||||
#include "d_englsh.h"
|
||||
|
||||
// Misc. other strings.
|
||||
#define SAVEGAMENAME "doomsav"
|
||||
|
||||
// QuitDOOM messages
|
||||
// 8 per each game type
|
||||
#define NUM_QUITMESSAGES 8
|
||||
|
||||
extern char *doom1_endmsg[];
|
||||
extern char *doom2_endmsg[];
|
||||
|
||||
#endif
|
|
@ -0,0 +1,200 @@
|
|||
#include "include.h"
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#include "../doomkeys.h"
|
||||
#include "../d_main.h"
|
||||
#include "../m_argv.h"
|
||||
|
||||
EsInstance *instance = 0;
|
||||
pixel_t *ES_ScreenBuffer = 0;
|
||||
|
||||
typedef struct {
|
||||
uint8_t value;
|
||||
bool pressed;
|
||||
} KeyEntry;
|
||||
#define KEY_QUEUE_SIZE 64
|
||||
|
||||
static KeyEntry KeyQueue[KEY_QUEUE_SIZE] = { 0 };
|
||||
static size_t KeyQueueHead = 0;
|
||||
static size_t KeyQueueTail = 0;
|
||||
|
||||
uint8_t ES_TranslateKey(EsScancode scancode) {
|
||||
switch (scancode) {
|
||||
case ES_SCANCODE_ENTER: return KEY_ENTER;
|
||||
case ES_SCANCODE_ESCAPE: return KEY_ESCAPE;
|
||||
case ES_SCANCODE_LEFT_ARROW: return KEY_LEFTARROW;
|
||||
case ES_SCANCODE_RIGHT_ARROW: return KEY_RIGHTARROW;
|
||||
case ES_SCANCODE_UP_ARROW: return KEY_UPARROW;
|
||||
case ES_SCANCODE_DOWN_ARROW: return KEY_DOWNARROW;
|
||||
case ES_SCANCODE_LEFT_CTRL:
|
||||
case ES_SCANCODE_RIGHT_CTRL:
|
||||
return KEY_FIRE;
|
||||
case ES_SCANCODE_SPACE: return KEY_USE;
|
||||
case ES_SCANCODE_LEFT_SHIFT:
|
||||
case ES_SCANCODE_RIGHT_SHIFT:
|
||||
return KEY_RSHIFT;
|
||||
case ES_SCANCODE_LEFT_ALT:
|
||||
case ES_SCANCODE_RIGHT_ALT:
|
||||
return KEY_LALT;
|
||||
case ES_SCANCODE_TAB:
|
||||
return KEY_TAB;
|
||||
case ES_SCANCODE_F2: return KEY_F2;
|
||||
case ES_SCANCODE_F3: return KEY_F3;
|
||||
case ES_SCANCODE_F4: return KEY_F4;
|
||||
case ES_SCANCODE_F5: return KEY_F5;
|
||||
case ES_SCANCODE_F6: return KEY_F6;
|
||||
case ES_SCANCODE_F7: return KEY_F7;
|
||||
case ES_SCANCODE_F8: return KEY_F8;
|
||||
case ES_SCANCODE_F9: return KEY_F9;
|
||||
case ES_SCANCODE_F10: return KEY_F10;
|
||||
case ES_SCANCODE_F11: return KEY_F11;
|
||||
case ES_SCANCODE_EQUALS: return KEY_EQUALS;
|
||||
case ES_SCANCODE_LEFT_BRACE:
|
||||
case ES_SCANCODE_RIGHT_BRACE:
|
||||
return KEY_MINUS;
|
||||
case ES_SCANCODE_0: return '0';
|
||||
case ES_SCANCODE_1: return '1';
|
||||
case ES_SCANCODE_2: return '2';
|
||||
case ES_SCANCODE_3: return '3';
|
||||
case ES_SCANCODE_4: return '4';
|
||||
case ES_SCANCODE_5: return '5';
|
||||
case ES_SCANCODE_6: return '6';
|
||||
case ES_SCANCODE_7: return '7';
|
||||
case ES_SCANCODE_8: return '8';
|
||||
case ES_SCANCODE_9: return '9';
|
||||
default:
|
||||
}
|
||||
|
||||
if (ES_SCANCODE_A <= scancode && scancode <= ES_SCANCODE_Z) {
|
||||
return scancode + ('a' - ES_SCANCODE_A);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t ES_GetKey(int *pressed, unsigned char *key) {
|
||||
if (KeyQueueHead == KeyQueueTail) return 0;
|
||||
|
||||
KeyEntry entry = KeyQueue[KeyQueueHead];
|
||||
KeyQueueHead = (KeyQueueHead + 1) % KEY_QUEUE_SIZE;
|
||||
|
||||
*key = entry.value;
|
||||
*pressed = entry.pressed;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t ES_GetTicksMs(void) {
|
||||
return EsTimeStampMs();
|
||||
}
|
||||
|
||||
void ES_SleepMs(uint32_t ms) {
|
||||
EsSleep(ms);
|
||||
}
|
||||
|
||||
int GameMessage(EsElement *element, EsMessage *message) {
|
||||
switch (message->type) {
|
||||
case ES_MSG_ANIMATE: {
|
||||
D_DoomTick();
|
||||
|
||||
EsElementRepaint(element, ES_NULL);
|
||||
|
||||
message->animate.complete = false;
|
||||
|
||||
return ES_HANDLED;
|
||||
}
|
||||
|
||||
case ES_MSG_PAINT: {
|
||||
EsPainter *painter = message->painter;
|
||||
|
||||
EsDrawRectangle(painter, ES_RECT_4(0, RES_X, 0, RES_Y), 0x000000FF, 0, ES_RECT_1(0));
|
||||
EsDrawBitmap(painter, ES_RECT_4(0, RES_X, 0, RES_Y), ES_ScreenBuffer, RES_X * 4, ES_DRAW_BITMAP_OPAQUE);
|
||||
|
||||
return ES_HANDLED;
|
||||
}
|
||||
|
||||
case ES_MSG_GET_WIDTH: {
|
||||
message->measure.width = RES_X;
|
||||
|
||||
return ES_HANDLED;
|
||||
}
|
||||
|
||||
case ES_MSG_GET_HEIGHT: {
|
||||
message->measure.height = RES_Y;
|
||||
|
||||
return ES_HANDLED;
|
||||
}
|
||||
|
||||
case ES_MSG_KEY_UP:
|
||||
case ES_MSG_KEY_DOWN: {
|
||||
uint8_t key = ES_TranslateKey(message->keyboard.scancode);
|
||||
if (key == 0) return ES_HANDLED;
|
||||
|
||||
KeyQueue[KeyQueueTail] = (KeyEntry) {
|
||||
.value = key,
|
||||
.pressed = message->type == ES_MSG_KEY_DOWN
|
||||
};
|
||||
|
||||
KeyQueueTail = (KeyQueueTail + 1) % KEY_QUEUE_SIZE;
|
||||
|
||||
return ES_HANDLED;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ApplicationMessage(EsMessage *message) {
|
||||
switch (message->type) {
|
||||
case ES_MSG_INSTANCE_CREATE: {
|
||||
instance = EsInstanceCreate(message, "DOOM", -1);
|
||||
EsWindowSetIcon(instance->window, ES_ICON_APPLICATIONS_GAMES);
|
||||
|
||||
EsPanel *panel = EsPanelCreate(instance->window, ES_CELL_FILL, 0);
|
||||
EsSpacerCreate(panel, ES_CELL_CENTER, 0, 0, 0);
|
||||
|
||||
EsElement *game = EsCustomElementCreate(panel, ES_ELEMENT_FOCUSABLE, 0);
|
||||
game->messageUser = GameMessage;
|
||||
|
||||
ES_Init();
|
||||
|
||||
EsElementFocus(game, ES_FLAGS_DEFAULT);
|
||||
EsElementStartAnimating(game);
|
||||
|
||||
return ES_HANDLED;
|
||||
}
|
||||
|
||||
default:
|
||||
return ES_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
static char *ES_ARGV[] = { "doom" };
|
||||
static int ES_ARGC = sizeof(ES_ARGV) / sizeof(char *);
|
||||
|
||||
void ES_Init(void) {
|
||||
myargc = ES_ARGC;
|
||||
myargv = ES_ARGV;
|
||||
|
||||
ES_ScreenBuffer = ES_malloc(RES_X * RES_Y * 4);
|
||||
|
||||
D_DoomMain();
|
||||
}
|
||||
|
||||
void ES_Loop(void) {
|
||||
while (true) ApplicationMessage(EsMessageReceive());
|
||||
}
|
||||
|
||||
void ES_Crash(const char *message) {
|
||||
ES_crashf("%s\n", message);
|
||||
|
||||
EsPanic("");
|
||||
}
|
||||
|
||||
void ES_Exit() {
|
||||
if (instance) EsInstanceClose(instance);
|
||||
|
||||
EsProcessTerminate(ES_CURRENT_PROCESS, 0);
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
#ifndef __ES_INCLUDE__
|
||||
#define __ES_INCLUDE__
|
||||
|
||||
#include <essence.h>
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
/* Logging */
|
||||
|
||||
void ES_logf(const char *label, const char *format, ...);
|
||||
|
||||
#ifdef FEATURE_CONSOLE
|
||||
#define ES_infof(format, ...) ES_logf("[Info:DOOM] ", format, ## __VA_ARGS__)
|
||||
#define ES_debugf(format, ...) ES_logf("[Debug:DOOM] ", format, ## __VA_ARGS__)
|
||||
#define ES_warnf(format, ...) ES_logf("[Warn:DOOM] ", format, ## __VA_ARGS__)
|
||||
#define ES_errorf(format, ...) ES_logf("[Error:DOOM] ", format, ## __VA_ARGS__)
|
||||
#define ES_crashf(format, ...) ES_logf("[Crash:DOOM] ", format, ## __VA_ARGS__)
|
||||
#else
|
||||
#define ES_infof(format, ...)
|
||||
#define ES_debugf(format, ...)
|
||||
#define ES_warnf(format, ...)
|
||||
#define ES_errorf(format, ...)
|
||||
#define ES_crashf(format, ...)
|
||||
#endif
|
||||
|
||||
/* Process */
|
||||
|
||||
__attribute__((noreturn))
|
||||
void ES_Crash(const char *message);
|
||||
|
||||
__attribute__((noreturn))
|
||||
void ES_Exit();
|
||||
|
||||
/* Math */
|
||||
|
||||
int ES_atoi(const char *str);
|
||||
#define ES_atoi EsCRTatoi
|
||||
|
||||
float ES_atof(const char *str);
|
||||
#define ES_atof EsCRTatof
|
||||
|
||||
int ES_abs(int n);
|
||||
#define ES_abs EsCRTabs
|
||||
|
||||
float ES_fabs(float n);
|
||||
#define ES_fabs EsCRTfabs
|
||||
|
||||
/* String */
|
||||
|
||||
int ES_strcasecmp(const char *s1, const char *s2);
|
||||
int ES_strncasecmp(const char *s1, const char *s2, size_t count);
|
||||
char ES_toupper(char c);
|
||||
|
||||
char ES_tolower(char c);
|
||||
#define ES_tolower EsCRTtolower
|
||||
|
||||
void *ES_memcpy(void *destination, const void *source, size_t num);
|
||||
#define ES_memcpy EsCRTmemcpy
|
||||
|
||||
void *ES_memset(void *ptr, int value, size_t num);
|
||||
#define ES_memset EsCRTmemset
|
||||
|
||||
const char *ES_strchr(const char *str, int character);
|
||||
#define ES_strchr EsCRTstrchr
|
||||
|
||||
size_t ES_strlen(const char *str);
|
||||
#define ES_strlen EsCRTstrlen
|
||||
|
||||
int ES_strcmp(const char *s1, const char *s2);
|
||||
#define ES_strcmp EsCRTstrcmp
|
||||
|
||||
int ES_strncmp(const char *s1, const char *s2, size_t count);
|
||||
#define ES_strncmp EsCRTstrncmp
|
||||
|
||||
int ES_strstr(const char *haystack, const char *needle);
|
||||
#define ES_strstr EsCRTstrstr
|
||||
|
||||
int ES_strcpy(char *dest, const char *src);
|
||||
#define ES_strcpy EsCRTstrcpy
|
||||
|
||||
int ES_strncpy(char *dest, const char *src, size_t n);
|
||||
#define ES_strncpy EsCRTstrncpy
|
||||
|
||||
int ES_isspace(int c);
|
||||
#define ES_isspace EsCRTisspace
|
||||
|
||||
int ES_vsnprintf(char *buffer, size_t size, const char *format, va_list arguments);
|
||||
#define ES_vsnprintf EsCRTvsnprintf
|
||||
|
||||
char *ES_strdup(const char *str);
|
||||
#define ES_strdup EsCRTstrdup
|
||||
|
||||
long ES_strtol(const char *ptr, char **endptr, int base);
|
||||
#define ES_strtol EsCRTstrtol
|
||||
|
||||
/* File */
|
||||
|
||||
typedef struct {
|
||||
EsFileInformation data;
|
||||
size_t ptr;
|
||||
} ES_File;
|
||||
|
||||
typedef enum {
|
||||
ES_BYTE_MODE = 0b1,
|
||||
ES_READ_MODE = 0b10,
|
||||
ES_WRITE_MODE = 0b100
|
||||
} ES_FileMode;
|
||||
|
||||
typedef enum {
|
||||
ES_SEEK_END,
|
||||
ES_SEEK_SET
|
||||
} ES_Seek;
|
||||
|
||||
ES_File *ES_fopen(const char *path, ES_FileMode mode);
|
||||
int ES_fvalid(ES_File *file);
|
||||
size_t ES_fread(void *buffer, size_t size, size_t count, ES_File *file);
|
||||
size_t ES_fwrite(const void *buffer, size_t size, size_t count, ES_File *file);
|
||||
int ES_fseek(ES_File *file, size_t offset, ES_Seek origin);
|
||||
size_t ES_ftell(ES_File *file);
|
||||
size_t ES_fprintf(ES_File *file, const char *format, ...);
|
||||
void ES_fclose(ES_File *file);
|
||||
|
||||
int ES_mkdir(const char *path);
|
||||
|
||||
int ES_remove(const char *path);
|
||||
int ES_rename(const char *old, const char *new);
|
||||
|
||||
/* Heap */
|
||||
|
||||
void *ES_malloc(size_t size);
|
||||
#define ES_malloc EsCRTmalloc
|
||||
|
||||
void *ES_calloc(size_t num, size_t size);
|
||||
#define ES_calloc EsCRTcalloc
|
||||
|
||||
void *ES_realloc(void *ptr, size_t size);
|
||||
#define ES_realloc EsCRTrealloc
|
||||
|
||||
void ES_free(void *ptr);
|
||||
#define ES_free EsCRTfree
|
||||
|
||||
/* Graphics */
|
||||
|
||||
#ifdef CMAP256
|
||||
typedef uint8_t pixel_t;
|
||||
#else
|
||||
typedef uint32_t pixel_t;
|
||||
#endif
|
||||
|
||||
extern pixel_t* ES_ScreenBuffer;
|
||||
|
||||
/* Game */
|
||||
|
||||
void ES_Loop(void);
|
||||
void ES_SleepMs(uint32_t ms);
|
||||
uint32_t ES_GetTicksMs(void);
|
||||
uint8_t ES_GetKey(int *pressed, unsigned char *key);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,200 @@
|
|||
#include "include.h"
|
||||
|
||||
static char ES_LOG_BUFFER[4096];
|
||||
|
||||
void ES_vlogf(const char *label, const char *format, va_list args) {
|
||||
size_t label_size = ES_strlen(label);
|
||||
ES_memcpy(ES_LOG_BUFFER, label, label_size);
|
||||
|
||||
size_t data_size = ES_vsnprintf(ES_LOG_BUFFER + label_size, sizeof(ES_LOG_BUFFER), format, args);
|
||||
|
||||
ES_LOG_BUFFER[sizeof(ES_LOG_BUFFER) - 1] = '\0';
|
||||
|
||||
EsPrintDirect(ES_LOG_BUFFER, data_size + label_size);
|
||||
}
|
||||
|
||||
void ES_logf(const char *label, const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
ES_vlogf(label, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
char ES_toupper(char c) {
|
||||
return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c;
|
||||
}
|
||||
|
||||
int ES_strcasecmp(const char *s1, const char *s2) {
|
||||
int c1, c2;
|
||||
|
||||
for (;;) {
|
||||
c1 = ES_tolower(*s1++);
|
||||
c2 = ES_tolower(*s2++);
|
||||
|
||||
if (c1 != c2) {
|
||||
return c1 - c2;
|
||||
}
|
||||
|
||||
if (c1 == '\0') break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ES_strncasecmp(const char *s1, const char *s2, register size_t n) {
|
||||
int c1, c2;
|
||||
|
||||
for (; n != 0; --n) {
|
||||
c1 = ES_tolower(*s1++);
|
||||
c2 = ES_tolower(*s2++);
|
||||
|
||||
if (c1 != c2) {
|
||||
return c1 - c2;
|
||||
}
|
||||
|
||||
if (c1 == '\0') break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ES_File *ES_fopen(const char *path, ES_FileMode mode) {
|
||||
EsFileOpenFlags flags;
|
||||
if (mode & ES_WRITE_MODE) flags = ES_FILE_WRITE;
|
||||
else flags = ES_FILE_READ;
|
||||
|
||||
if (flags & ES_FILE_READ) {
|
||||
EsNodeType nodeType;
|
||||
|
||||
if (!EsPathExists(path, ES_strlen(path), &nodeType) || nodeType != ES_NODE_FILE) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
EsFileInformation data = EsFileOpen(path, ES_strlen(path), flags);
|
||||
if (data.error != ES_SUCCESS) {
|
||||
EsHandleClose(data.handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ES_File *file = ES_malloc(sizeof(ES_File));
|
||||
if (file == NULL) {
|
||||
EsHandleClose(data.handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file->ptr = 0;
|
||||
file->data = data;
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
int ES_fvalid(ES_File *file) {
|
||||
return file->data.error == ES_SUCCESS;
|
||||
}
|
||||
|
||||
size_t ES_fread(void *buffer, size_t size, size_t count, ES_File *file) {
|
||||
size_t offset = EsFileReadSync(file->data.handle, file->ptr, size * count, buffer);
|
||||
|
||||
file->ptr += offset;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
size_t ES_fwrite(const void *buffer, size_t size, size_t count, ES_File *file) {
|
||||
size_t offset = EsFileWriteSync(file->data.handle, file->ptr, size * count, buffer);
|
||||
file->ptr += offset;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
int ES_fseek(ES_File *file, size_t offset, ES_Seek origin) {
|
||||
switch (origin) {
|
||||
case ES_SEEK_SET:
|
||||
if (offset >= file->data.size) return -1;
|
||||
file->ptr = offset;
|
||||
return 0;
|
||||
|
||||
case ES_SEEK_END:
|
||||
file->ptr = file->data.size + 1;
|
||||
return 0;
|
||||
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
size_t ES_ftell(ES_File *file) {
|
||||
return file->ptr;
|
||||
}
|
||||
|
||||
size_t ES_fprintf(ES_File *file, const char *format, ...) {
|
||||
size_t max_size = ES_strlen(format) * 4;
|
||||
void *buffer = ES_malloc(max_size);
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
ES_vsnprintf(buffer, max_size, format, args);
|
||||
va_end(args);
|
||||
|
||||
size_t size = ES_strlen(buffer);
|
||||
|
||||
size_t write_size = ES_fwrite(buffer, size, 1, file);
|
||||
|
||||
ES_free(buffer);
|
||||
|
||||
return write_size;
|
||||
}
|
||||
|
||||
void ES_fclose(ES_File *file) {
|
||||
EsHandleClose(file->data.handle);
|
||||
ES_free(file);
|
||||
}
|
||||
|
||||
int ES_remove(const char *path) {
|
||||
EsFileInformation file = EsFileOpen(path, ES_strlen(path), ES_FILE_WRITE);
|
||||
if (file.error != ES_SUCCESS) {
|
||||
EsHandleClose(file.handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
EsFileDelete(file.handle);
|
||||
EsHandleClose(file.handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ES_rename(const char *old, const char *new) {
|
||||
EsFileInformation oldFile = EsFileOpen(old, ES_strlen(old), ES_FILE_READ | ES_FILE_WRITE);
|
||||
if (oldFile.error != ES_SUCCESS) {
|
||||
EsHandleClose(oldFile.handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (EsPathCreate(new, ES_strlen(new), ES_NODE_FILE, true) != ES_SUCCESS) {
|
||||
EsHandleClose(oldFile.handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
EsFileInformation newFile = EsFileOpen(new, ES_strlen(new), ES_FILE_WRITE);
|
||||
if (newFile.error != ES_SUCCESS) {
|
||||
EsHandleClose(oldFile.handle);
|
||||
EsHandleClose(newFile.handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *buffer = ES_malloc(oldFile.size);
|
||||
EsFileReadSync(oldFile.handle, 0, oldFile.size, buffer);
|
||||
EsFileWriteSync(newFile.handle, 0, newFile.size, buffer);
|
||||
ES_free(buffer);
|
||||
|
||||
EsFileDelete(oldFile.handle);
|
||||
|
||||
EsHandleClose(oldFile.handle);
|
||||
EsHandleClose(newFile.handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ES_mkdir(const char *path) {
|
||||
return EsPathCreate(path, ES_strlen(path), ES_NODE_DIRECTORY, true) == ES_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
#include "include.h"
|
||||
|
||||
#include "../am_map.c"
|
||||
#include "../d_event.c"
|
||||
#include "../d_items.c"
|
||||
#include "../d_iwad.c"
|
||||
#include "../d_loop.c"
|
||||
#include "../d_main.c"
|
||||
#include "../d_mode.c"
|
||||
#include "../d_net.c"
|
||||
#include "../doomstat.c"
|
||||
#include "../dstrings.c"
|
||||
#include "../f_finale.c"
|
||||
#include "../f_wipe.c"
|
||||
#include "../g_game.c"
|
||||
#include "../gusconf.c"
|
||||
#include "../hu_lib.c"
|
||||
#include "../hu_stuff.c"
|
||||
#include "../i_input.c"
|
||||
#include "../i_joystick.c"
|
||||
#include "../info.c"
|
||||
#include "../i_scale.c"
|
||||
#include "../i_sound.c"
|
||||
#include "../i_system.c"
|
||||
#include "../i_timer.c"
|
||||
#include "../i_video.c"
|
||||
#include "../m_argv.c"
|
||||
#include "../m_bbox.c"
|
||||
#include "../m_cheat.c"
|
||||
#include "../m_config.c"
|
||||
#include "../m_controls.c"
|
||||
#include "../memio.c"
|
||||
#include "../m_fixed.c"
|
||||
#include "../m_menu.c"
|
||||
#include "../m_misc.c"
|
||||
#include "../m_random.c"
|
||||
#include "../mus2mid.c"
|
||||
#include "../net_client.c"
|
||||
#include "../p_ceilng.c"
|
||||
#include "../p_doors.c"
|
||||
#include "../p_enemy.c"
|
||||
#include "../p_floor.c"
|
||||
#include "../p_inter.c"
|
||||
#include "../p_lights.c"
|
||||
#include "../p_map.c"
|
||||
#include "../p_maputl.c"
|
||||
#include "../p_mobj.c"
|
||||
#include "../p_plats.c"
|
||||
#include "../p_pspr.c"
|
||||
#include "../p_saveg.c"
|
||||
#include "../p_setup.c"
|
||||
#include "../p_sight.c"
|
||||
#include "../p_spec.c"
|
||||
#include "../p_switch.c"
|
||||
#include "../p_telept.c"
|
||||
#include "../p_tick.c"
|
||||
#include "../p_user.c"
|
||||
#include "../r_bsp.c"
|
||||
#include "../r_data.c"
|
||||
#include "../r_draw.c"
|
||||
#include "../r_main.c"
|
||||
#include "../r_plane.c"
|
||||
#include "../r_segs.c"
|
||||
#include "../r_sky.c"
|
||||
#include "../r_things.c"
|
||||
#include "../sha1.c"
|
||||
#include "../sounds.c"
|
||||
#include "../s_sound.c"
|
||||
#include "../statdump.c"
|
||||
#include "../st_lib.c"
|
||||
#include "../st_stuff.c"
|
||||
#include "../tables.c"
|
||||
#include "../v_video.c"
|
||||
#include "../w_checksum.c"
|
||||
#include "../w_file.c"
|
||||
#include "../w_file_stdc.c"
|
||||
#include "../wi_stuff.c"
|
||||
#include "../w_main.c"
|
||||
#include "../w_wad.c"
|
||||
#include "../z_zone.c"
|
||||
|
||||
#include "lib.c"
|
||||
#include "game.c"
|
||||
|
||||
void _start() {
|
||||
_init();
|
||||
|
||||
ES_debugf("Started\n");
|
||||
|
||||
ES_Loop();
|
||||
}
|
|
@ -0,0 +1,705 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Game completion, final screen animation.
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
// Functions.
|
||||
#include "i_system.h"
|
||||
#include "i_swap.h"
|
||||
#include "z_zone.h"
|
||||
#include "v_video.h"
|
||||
#include "w_wad.h"
|
||||
#include "s_sound.h"
|
||||
|
||||
// Data.
|
||||
#include "d_main.h"
|
||||
#include "dstrings.h"
|
||||
#include "sounds.h"
|
||||
|
||||
#include "doomstat.h"
|
||||
#include "r_state.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
F_STAGE_TEXT,
|
||||
F_STAGE_ARTSCREEN,
|
||||
F_STAGE_CAST,
|
||||
} finalestage_t;
|
||||
|
||||
// ?
|
||||
//#include "doomstat.h"
|
||||
//#include "r_local.h"
|
||||
//#include "f_finale.h"
|
||||
|
||||
// Stage of animation:
|
||||
finalestage_t finalestage;
|
||||
|
||||
unsigned int finalecount;
|
||||
|
||||
#define TEXTSPEED 3
|
||||
#define TEXTWAIT 250
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GameMission_t mission;
|
||||
int episode, level;
|
||||
char *background;
|
||||
char *text;
|
||||
} textscreen_t;
|
||||
|
||||
static textscreen_t textscreens[] =
|
||||
{
|
||||
{ doom, 1, 8, "FLOOR4_8", E1TEXT},
|
||||
{ doom, 2, 8, "SFLR6_1", E2TEXT},
|
||||
{ doom, 3, 8, "MFLR8_4", E3TEXT},
|
||||
{ doom, 4, 8, "MFLR8_3", E4TEXT},
|
||||
|
||||
{ doom2, 1, 6, "SLIME16", C1TEXT},
|
||||
{ doom2, 1, 11, "RROCK14", C2TEXT},
|
||||
{ doom2, 1, 20, "RROCK07", C3TEXT},
|
||||
{ doom2, 1, 30, "RROCK17", C4TEXT},
|
||||
{ doom2, 1, 15, "RROCK13", C5TEXT},
|
||||
{ doom2, 1, 31, "RROCK19", C6TEXT},
|
||||
|
||||
{ pack_tnt, 1, 6, "SLIME16", T1TEXT},
|
||||
{ pack_tnt, 1, 11, "RROCK14", T2TEXT},
|
||||
{ pack_tnt, 1, 20, "RROCK07", T3TEXT},
|
||||
{ pack_tnt, 1, 30, "RROCK17", T4TEXT},
|
||||
{ pack_tnt, 1, 15, "RROCK13", T5TEXT},
|
||||
{ pack_tnt, 1, 31, "RROCK19", T6TEXT},
|
||||
|
||||
{ pack_plut, 1, 6, "SLIME16", P1TEXT},
|
||||
{ pack_plut, 1, 11, "RROCK14", P2TEXT},
|
||||
{ pack_plut, 1, 20, "RROCK07", P3TEXT},
|
||||
{ pack_plut, 1, 30, "RROCK17", P4TEXT},
|
||||
{ pack_plut, 1, 15, "RROCK13", P5TEXT},
|
||||
{ pack_plut, 1, 31, "RROCK19", P6TEXT},
|
||||
};
|
||||
|
||||
char* finaletext;
|
||||
char* finaleflat;
|
||||
|
||||
void F_StartCast (void);
|
||||
void F_CastTicker (void);
|
||||
boolean F_CastResponder (event_t *ev);
|
||||
void F_CastDrawer (void);
|
||||
|
||||
//
|
||||
// F_StartFinale
|
||||
//
|
||||
void F_StartFinale (void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
gameaction = ga_nothing;
|
||||
gamestate = GS_FINALE;
|
||||
viewactive = false;
|
||||
automapactive = false;
|
||||
|
||||
if (logical_gamemission == doom)
|
||||
{
|
||||
S_ChangeMusic(mus_victor, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
S_ChangeMusic(mus_read_m, true);
|
||||
}
|
||||
|
||||
// Find the right screen and set the text and background
|
||||
|
||||
for (i=0; i<arrlen(textscreens); ++i)
|
||||
{
|
||||
textscreen_t *screen = &textscreens[i];
|
||||
|
||||
// Hack for Chex Quest
|
||||
|
||||
if (gameversion == exe_chex && screen->mission == doom)
|
||||
{
|
||||
screen->level = 5;
|
||||
}
|
||||
|
||||
if (logical_gamemission == screen->mission
|
||||
&& (logical_gamemission != doom || gameepisode == screen->episode)
|
||||
&& gamemap == screen->level)
|
||||
{
|
||||
finaletext = screen->text;
|
||||
finaleflat = screen->background;
|
||||
}
|
||||
}
|
||||
|
||||
finalestage = F_STAGE_TEXT;
|
||||
finalecount = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
boolean F_Responder (event_t *event)
|
||||
{
|
||||
if (finalestage == F_STAGE_CAST)
|
||||
return F_CastResponder (event);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// F_Ticker
|
||||
//
|
||||
void F_Ticker (void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
// check for skipping
|
||||
if ( (gamemode == commercial)
|
||||
&& ( finalecount > 50) )
|
||||
{
|
||||
// go on to the next level
|
||||
for (i=0 ; i<MAXPLAYERS ; i++)
|
||||
if (players[i].cmd.buttons)
|
||||
break;
|
||||
|
||||
if (i < MAXPLAYERS)
|
||||
{
|
||||
if (gamemap == 30)
|
||||
F_StartCast ();
|
||||
else
|
||||
gameaction = ga_worlddone;
|
||||
}
|
||||
}
|
||||
|
||||
// advance animation
|
||||
finalecount++;
|
||||
|
||||
if (finalestage == F_STAGE_CAST)
|
||||
{
|
||||
F_CastTicker ();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( gamemode == commercial)
|
||||
return;
|
||||
|
||||
if (finalestage == F_STAGE_TEXT
|
||||
&& finalecount>ES_strlen (finaletext)*TEXTSPEED + TEXTWAIT)
|
||||
{
|
||||
finalecount = 0;
|
||||
finalestage = F_STAGE_ARTSCREEN;
|
||||
wipegamestate = -1; // force a wipe
|
||||
if (gameepisode == 3)
|
||||
S_StartMusic (mus_bunny);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// F_TextWrite
|
||||
//
|
||||
|
||||
#include "hu_stuff.h"
|
||||
extern patch_t *hu_font[HU_FONTSIZE];
|
||||
|
||||
|
||||
void F_TextWrite (void)
|
||||
{
|
||||
byte* src;
|
||||
byte* dest;
|
||||
|
||||
int x,y,w;
|
||||
signed int count;
|
||||
char* ch;
|
||||
int c;
|
||||
int cx;
|
||||
int cy;
|
||||
|
||||
// erase the entire screen to a tiled background
|
||||
src = W_CacheLumpName ( finaleflat , PU_CACHE);
|
||||
dest = I_VideoBuffer;
|
||||
|
||||
for (y=0 ; y<SCREENHEIGHT ; y++)
|
||||
{
|
||||
for (x=0 ; x<SCREENWIDTH/64 ; x++)
|
||||
{
|
||||
ES_memcpy (dest, src+((y&63)<<6), 64);
|
||||
dest += 64;
|
||||
}
|
||||
if (SCREENWIDTH&63)
|
||||
{
|
||||
ES_memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
|
||||
dest += (SCREENWIDTH&63);
|
||||
}
|
||||
}
|
||||
|
||||
V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
|
||||
|
||||
// draw some of the text onto the screen
|
||||
cx = 10;
|
||||
cy = 10;
|
||||
ch = finaletext;
|
||||
|
||||
count = ((signed int) finalecount - 10) / TEXTSPEED;
|
||||
if (count < 0)
|
||||
count = 0;
|
||||
for ( ; count ; count-- )
|
||||
{
|
||||
c = *ch++;
|
||||
if (!c)
|
||||
break;
|
||||
if (c == '\n')
|
||||
{
|
||||
cx = 10;
|
||||
cy += 11;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = ES_toupper(c) - HU_FONTSTART;
|
||||
if (c < 0 || c> HU_FONTSIZE)
|
||||
{
|
||||
cx += 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
w = SHORT (hu_font[c]->width);
|
||||
if (cx+w > SCREENWIDTH)
|
||||
break;
|
||||
V_DrawPatch(cx, cy, hu_font[c]);
|
||||
cx+=w;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Final DOOM 2 animation
|
||||
// Casting by id Software.
|
||||
// in order of appearance
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
mobjtype_t type;
|
||||
} castinfo_t;
|
||||
|
||||
castinfo_t castorder[] = {
|
||||
{CC_ZOMBIE, MT_POSSESSED},
|
||||
{CC_SHOTGUN, MT_SHOTGUY},
|
||||
{CC_HEAVY, MT_CHAINGUY},
|
||||
{CC_IMP, MT_TROOP},
|
||||
{CC_DEMON, MT_SERGEANT},
|
||||
{CC_LOST, MT_SKULL},
|
||||
{CC_CACO, MT_HEAD},
|
||||
{CC_HELL, MT_KNIGHT},
|
||||
{CC_BARON, MT_BRUISER},
|
||||
{CC_ARACH, MT_BABY},
|
||||
{CC_PAIN, MT_PAIN},
|
||||
{CC_REVEN, MT_UNDEAD},
|
||||
{CC_MANCU, MT_FATSO},
|
||||
{CC_ARCH, MT_VILE},
|
||||
{CC_SPIDER, MT_SPIDER},
|
||||
{CC_CYBER, MT_CYBORG},
|
||||
{CC_HERO, MT_PLAYER},
|
||||
|
||||
{NULL,0}
|
||||
};
|
||||
|
||||
int castnum;
|
||||
int casttics;
|
||||
state_t* caststate;
|
||||
boolean castdeath;
|
||||
int castframes;
|
||||
int castonmelee;
|
||||
boolean castattacking;
|
||||
|
||||
|
||||
//
|
||||
// F_StartCast
|
||||
//
|
||||
void F_StartCast (void)
|
||||
{
|
||||
wipegamestate = -1; // force a screen wipe
|
||||
castnum = 0;
|
||||
caststate = &states[mobjinfo[castorder[castnum].type].seestate];
|
||||
casttics = caststate->tics;
|
||||
castdeath = false;
|
||||
finalestage = F_STAGE_CAST;
|
||||
castframes = 0;
|
||||
castonmelee = 0;
|
||||
castattacking = false;
|
||||
S_ChangeMusic(mus_evil, true);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// F_CastTicker
|
||||
//
|
||||
void F_CastTicker (void)
|
||||
{
|
||||
int st;
|
||||
int sfx;
|
||||
|
||||
if (--casttics > 0)
|
||||
return; // not time to change state yet
|
||||
|
||||
if (caststate->tics == -1 || caststate->nextstate == S_NULL)
|
||||
{
|
||||
// switch from deathstate to next monster
|
||||
castnum++;
|
||||
castdeath = false;
|
||||
if (castorder[castnum].name == NULL)
|
||||
castnum = 0;
|
||||
if (mobjinfo[castorder[castnum].type].seesound)
|
||||
S_StartSound (NULL, mobjinfo[castorder[castnum].type].seesound);
|
||||
caststate = &states[mobjinfo[castorder[castnum].type].seestate];
|
||||
castframes = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// just advance to next state in animation
|
||||
if (caststate == &states[S_PLAY_ATK1])
|
||||
goto stopattack; // Oh, gross hack!
|
||||
st = caststate->nextstate;
|
||||
caststate = &states[st];
|
||||
castframes++;
|
||||
|
||||
// sound hacks....
|
||||
switch (st)
|
||||
{
|
||||
case S_PLAY_ATK1: sfx = sfx_dshtgn; break;
|
||||
case S_POSS_ATK2: sfx = sfx_pistol; break;
|
||||
case S_SPOS_ATK2: sfx = sfx_shotgn; break;
|
||||
case S_VILE_ATK2: sfx = sfx_vilatk; break;
|
||||
case S_SKEL_FIST2: sfx = sfx_skeswg; break;
|
||||
case S_SKEL_FIST4: sfx = sfx_skepch; break;
|
||||
case S_SKEL_MISS2: sfx = sfx_skeatk; break;
|
||||
case S_FATT_ATK8:
|
||||
case S_FATT_ATK5:
|
||||
case S_FATT_ATK2: sfx = sfx_firsht; break;
|
||||
case S_CPOS_ATK2:
|
||||
case S_CPOS_ATK3:
|
||||
case S_CPOS_ATK4: sfx = sfx_shotgn; break;
|
||||
case S_TROO_ATK3: sfx = sfx_claw; break;
|
||||
case S_SARG_ATK2: sfx = sfx_sgtatk; break;
|
||||
case S_BOSS_ATK2:
|
||||
case S_BOS2_ATK2:
|
||||
case S_HEAD_ATK2: sfx = sfx_firsht; break;
|
||||
case S_SKULL_ATK2: sfx = sfx_sklatk; break;
|
||||
case S_SPID_ATK2:
|
||||
case S_SPID_ATK3: sfx = sfx_shotgn; break;
|
||||
case S_BSPI_ATK2: sfx = sfx_plasma; break;
|
||||
case S_CYBER_ATK2:
|
||||
case S_CYBER_ATK4:
|
||||
case S_CYBER_ATK6: sfx = sfx_rlaunc; break;
|
||||
case S_PAIN_ATK3: sfx = sfx_sklatk; break;
|
||||
default: sfx = 0; break;
|
||||
}
|
||||
|
||||
if (sfx)
|
||||
S_StartSound (NULL, sfx);
|
||||
}
|
||||
|
||||
if (castframes == 12)
|
||||
{
|
||||
// go into attack frame
|
||||
castattacking = true;
|
||||
if (castonmelee)
|
||||
caststate=&states[mobjinfo[castorder[castnum].type].meleestate];
|
||||
else
|
||||
caststate=&states[mobjinfo[castorder[castnum].type].missilestate];
|
||||
castonmelee ^= 1;
|
||||
if (caststate == &states[S_NULL])
|
||||
{
|
||||
if (castonmelee)
|
||||
caststate=
|
||||
&states[mobjinfo[castorder[castnum].type].meleestate];
|
||||
else
|
||||
caststate=
|
||||
&states[mobjinfo[castorder[castnum].type].missilestate];
|
||||
}
|
||||
}
|
||||
|
||||
if (castattacking)
|
||||
{
|
||||
if (castframes == 24
|
||||
|| caststate == &states[mobjinfo[castorder[castnum].type].seestate] )
|
||||
{
|
||||
stopattack:
|
||||
castattacking = false;
|
||||
castframes = 0;
|
||||
caststate = &states[mobjinfo[castorder[castnum].type].seestate];
|
||||
}
|
||||
}
|
||||
|
||||
casttics = caststate->tics;
|
||||
if (casttics == -1)
|
||||
casttics = 15;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// F_CastResponder
|
||||
//
|
||||
|
||||
boolean F_CastResponder (event_t* ev)
|
||||
{
|
||||
if (ev->type != ev_keydown)
|
||||
return false;
|
||||
|
||||
if (castdeath)
|
||||
return true; // already in dying frames
|
||||
|
||||
// go into death frame
|
||||
castdeath = true;
|
||||
caststate = &states[mobjinfo[castorder[castnum].type].deathstate];
|
||||
casttics = caststate->tics;
|
||||
castframes = 0;
|
||||
castattacking = false;
|
||||
if (mobjinfo[castorder[castnum].type].deathsound)
|
||||
S_StartSound (NULL, mobjinfo[castorder[castnum].type].deathsound);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void F_CastPrint (char* text)
|
||||
{
|
||||
char* ch;
|
||||
int c;
|
||||
int cx;
|
||||
int w;
|
||||
int width;
|
||||
|
||||
// find width
|
||||
ch = text;
|
||||
width = 0;
|
||||
|
||||
while (ch)
|
||||
{
|
||||
c = *ch++;
|
||||
if (!c)
|
||||
break;
|
||||
c = ES_toupper(c) - HU_FONTSTART;
|
||||
if (c < 0 || c> HU_FONTSIZE)
|
||||
{
|
||||
width += 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
w = SHORT (hu_font[c]->width);
|
||||
width += w;
|
||||
}
|
||||
|
||||
// draw it
|
||||
cx = 160-width/2;
|
||||
ch = text;
|
||||
while (ch)
|
||||
{
|
||||
c = *ch++;
|
||||
if (!c)
|
||||
break;
|
||||
c = ES_toupper(c) - HU_FONTSTART;
|
||||
if (c < 0 || c> HU_FONTSIZE)
|
||||
{
|
||||
cx += 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
w = SHORT (hu_font[c]->width);
|
||||
V_DrawPatch(cx, 180, hu_font[c]);
|
||||
cx+=w;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// F_CastDrawer
|
||||
//
|
||||
|
||||
void F_CastDrawer (void)
|
||||
{
|
||||
spritedef_t* sprdef;
|
||||
spriteframe_t* sprframe;
|
||||
int lump;
|
||||
boolean flip;
|
||||
patch_t* patch;
|
||||
|
||||
// erase the entire screen to a background
|
||||
V_DrawPatch (0, 0, W_CacheLumpName ("BOSSBACK", PU_CACHE));
|
||||
|
||||
F_CastPrint (castorder[castnum].name);
|
||||
|
||||
// draw the current frame in the middle of the screen
|
||||
sprdef = &sprites[caststate->sprite];
|
||||
sprframe = &sprdef->spriteframes[ caststate->frame & FF_FRAMEMASK];
|
||||
lump = sprframe->lump[0];
|
||||
flip = (boolean)sprframe->flip[0];
|
||||
|
||||
patch = W_CacheLumpNum (lump+firstspritelump, PU_CACHE);
|
||||
if (flip)
|
||||
V_DrawPatchFlipped(160, 170, patch);
|
||||
else
|
||||
V_DrawPatch(160, 170, patch);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// F_DrawPatchCol
|
||||
//
|
||||
void
|
||||
F_DrawPatchCol
|
||||
( int x,
|
||||
patch_t* patch,
|
||||
int col )
|
||||
{
|
||||
column_t* column;
|
||||
byte* source;
|
||||
byte* dest;
|
||||
byte* desttop;
|
||||
int count;
|
||||
|
||||
column = (column_t *)((byte *)patch + LONG(patch->columnofs[col]));
|
||||
desttop = I_VideoBuffer + x;
|
||||
|
||||
// step through the posts in a column
|
||||
while (column->topdelta != 0xff )
|
||||
{
|
||||
source = (byte *)column + 3;
|
||||
dest = desttop + column->topdelta*SCREENWIDTH;
|
||||
count = column->length;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
*dest = *source++;
|
||||
dest += SCREENWIDTH;
|
||||
}
|
||||
column = (column_t *)( (byte *)column + column->length + 4 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// F_BunnyScroll
|
||||
//
|
||||
void F_BunnyScroll (void)
|
||||
{
|
||||
signed int scrolled;
|
||||
int x;
|
||||
patch_t* p1;
|
||||
patch_t* p2;
|
||||
char name[10];
|
||||
int stage;
|
||||
static int laststage;
|
||||
|
||||
p1 = W_CacheLumpName ("PFUB2", PU_LEVEL);
|
||||
p2 = W_CacheLumpName ("PFUB1", PU_LEVEL);
|
||||
|
||||
V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
|
||||
|
||||
scrolled = (320 - ((signed int) finalecount-230)/2);
|
||||
if (scrolled > 320)
|
||||
scrolled = 320;
|
||||
if (scrolled < 0)
|
||||
scrolled = 0;
|
||||
|
||||
for ( x=0 ; x<SCREENWIDTH ; x++)
|
||||
{
|
||||
if (x+scrolled < 320)
|
||||
F_DrawPatchCol (x, p1, x+scrolled);
|
||||
else
|
||||
F_DrawPatchCol (x, p2, x+scrolled - 320);
|
||||
}
|
||||
|
||||
if (finalecount < 1130)
|
||||
return;
|
||||
if (finalecount < 1180)
|
||||
{
|
||||
V_DrawPatch((SCREENWIDTH - 13 * 8) / 2,
|
||||
(SCREENHEIGHT - 8 * 8) / 2,
|
||||
W_CacheLumpName("END0", PU_CACHE));
|
||||
laststage = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
stage = (finalecount-1180) / 5;
|
||||
if (stage > 6)
|
||||
stage = 6;
|
||||
if (stage > laststage)
|
||||
{
|
||||
S_StartSound (NULL, sfx_pistol);
|
||||
laststage = stage;
|
||||
}
|
||||
|
||||
M_snprintf(name, 10, "END%i", stage);
|
||||
V_DrawPatch((SCREENWIDTH - 13 * 8) / 2,
|
||||
(SCREENHEIGHT - 8 * 8) / 2,
|
||||
W_CacheLumpName (name,PU_CACHE));
|
||||
}
|
||||
|
||||
static void F_ArtScreenDrawer(void)
|
||||
{
|
||||
char *lumpname;
|
||||
|
||||
if (gameepisode == 3)
|
||||
{
|
||||
F_BunnyScroll();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (gameepisode)
|
||||
{
|
||||
case 1:
|
||||
if (gamemode == retail)
|
||||
{
|
||||
lumpname = "CREDIT";
|
||||
}
|
||||
else
|
||||
{
|
||||
lumpname = "HELP2";
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
lumpname = "VICTORY2";
|
||||
break;
|
||||
case 4:
|
||||
lumpname = "ENDPIC";
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
V_DrawPatch (0, 0, W_CacheLumpName(lumpname, PU_CACHE));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// F_Drawer
|
||||
//
|
||||
void F_Drawer (void)
|
||||
{
|
||||
switch (finalestage)
|
||||
{
|
||||
case F_STAGE_CAST:
|
||||
F_CastDrawer();
|
||||
break;
|
||||
case F_STAGE_TEXT:
|
||||
F_TextWrite();
|
||||
break;
|
||||
case F_STAGE_ARTSCREEN:
|
||||
F_ArtScreenDrawer();
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __F_FINALE__
|
||||
#define __F_FINALE__
|
||||
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "d_event.h"
|
||||
//
|
||||
// FINALE
|
||||
//
|
||||
|
||||
// Called by main loop.
|
||||
boolean F_Responder (event_t* ev);
|
||||
|
||||
// Called by main loop.
|
||||
void F_Ticker (void);
|
||||
|
||||
// Called by main loop.
|
||||
void F_Drawer (void);
|
||||
|
||||
void F_StartFinale (void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,297 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Mission begin melt/wipe screen special effect.
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "z_zone.h"
|
||||
#include "i_video.h"
|
||||
#include "v_video.h"
|
||||
#include "m_random.h"
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
#include "f_wipe.h"
|
||||
|
||||
//
|
||||
// SCREEN WIPE PACKAGE
|
||||
//
|
||||
|
||||
// when zero, stop the wipe
|
||||
static boolean go = 0;
|
||||
|
||||
static byte* wipe_scr_start;
|
||||
static byte* wipe_scr_end;
|
||||
static byte* wipe_scr;
|
||||
|
||||
|
||||
void
|
||||
wipe_shittyColMajorXform
|
||||
( short* array,
|
||||
int width,
|
||||
int height )
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
short* dest;
|
||||
|
||||
dest = (short*) Z_Malloc(width*height*2, PU_STATIC, 0);
|
||||
|
||||
for(y=0;y<height;y++)
|
||||
for(x=0;x<width;x++)
|
||||
dest[x*height+y] = array[y*width+x];
|
||||
|
||||
ES_memcpy(array, dest, width*height*2);
|
||||
|
||||
Z_Free(dest);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
wipe_initColorXForm
|
||||
( int width,
|
||||
int height,
|
||||
int ticks )
|
||||
{
|
||||
ES_memcpy(wipe_scr, wipe_scr_start, width*height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
wipe_doColorXForm
|
||||
( int width,
|
||||
int height,
|
||||
int ticks )
|
||||
{
|
||||
boolean changed;
|
||||
byte* w;
|
||||
byte* e;
|
||||
int newval;
|
||||
|
||||
changed = false;
|
||||
w = wipe_scr;
|
||||
e = wipe_scr_end;
|
||||
|
||||
while (w!=wipe_scr+width*height)
|
||||
{
|
||||
if (*w != *e)
|
||||
{
|
||||
if (*w > *e)
|
||||
{
|
||||
newval = *w - ticks;
|
||||
if (newval < *e)
|
||||
*w = *e;
|
||||
else
|
||||
*w = newval;
|
||||
changed = true;
|
||||
}
|
||||
else if (*w < *e)
|
||||
{
|
||||
newval = *w + ticks;
|
||||
if (newval > *e)
|
||||
*w = *e;
|
||||
else
|
||||
*w = newval;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
w++;
|
||||
e++;
|
||||
}
|
||||
|
||||
return !changed;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
wipe_exitColorXForm
|
||||
( int width,
|
||||
int height,
|
||||
int ticks )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int* y;
|
||||
|
||||
int
|
||||
wipe_initMelt
|
||||
( int width,
|
||||
int height,
|
||||
int ticks )
|
||||
{
|
||||
int i, r;
|
||||
|
||||
// copy start screen to main screen
|
||||
ES_memcpy(wipe_scr, wipe_scr_start, width*height);
|
||||
|
||||
// makes this wipe faster (in theory)
|
||||
// to have stuff in column-major format
|
||||
wipe_shittyColMajorXform((short*)wipe_scr_start, width/2, height);
|
||||
wipe_shittyColMajorXform((short*)wipe_scr_end, width/2, height);
|
||||
|
||||
// setup initial column positions
|
||||
// (y<0 => not ready to scroll yet)
|
||||
y = (int *) Z_Malloc(width*sizeof(int), PU_STATIC, 0);
|
||||
y[0] = -(M_Random()%16);
|
||||
for (i=1;i<width;i++)
|
||||
{
|
||||
r = (M_Random()%3) - 1;
|
||||
y[i] = y[i-1] + r;
|
||||
if (y[i] > 0) y[i] = 0;
|
||||
else if (y[i] == -16) y[i] = -15;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
wipe_doMelt
|
||||
( int width,
|
||||
int height,
|
||||
int ticks)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int dy;
|
||||
int idx;
|
||||
|
||||
short* s;
|
||||
short* d;
|
||||
boolean done = true;
|
||||
|
||||
width/=2;
|
||||
|
||||
while (ticks--)
|
||||
{
|
||||
for (i=0;i<width;i++)
|
||||
{
|
||||
if (y[i]<0)
|
||||
{
|
||||
y[i]++; done = false;
|
||||
}
|
||||
else if (y[i] < height)
|
||||
{
|
||||
dy = (y[i] < 16) ? y[i]+1 : 8;
|
||||
if (y[i]+dy >= height) dy = height - y[i];
|
||||
s = &((short *)wipe_scr_end)[i*height+y[i]];
|
||||
d = &((short *)wipe_scr)[y[i]*width+i];
|
||||
idx = 0;
|
||||
for (j=dy;j;j--)
|
||||
{
|
||||
d[idx] = *(s++);
|
||||
idx += width;
|
||||
}
|
||||
y[i] += dy;
|
||||
s = &((short *)wipe_scr_start)[i*height];
|
||||
d = &((short *)wipe_scr)[y[i]*width+i];
|
||||
idx = 0;
|
||||
for (j=height-y[i];j;j--)
|
||||
{
|
||||
d[idx] = *(s++);
|
||||
idx += width;
|
||||
}
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return done;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
wipe_exitMelt
|
||||
( int width,
|
||||
int height,
|
||||
int ticks )
|
||||
{
|
||||
Z_Free(y);
|
||||
Z_Free(wipe_scr_start);
|
||||
Z_Free(wipe_scr_end);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
wipe_StartScreen
|
||||
( int x,
|
||||
int y,
|
||||
int width,
|
||||
int height )
|
||||
{
|
||||
wipe_scr_start = Z_Malloc(SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL);
|
||||
I_ReadScreen(wipe_scr_start);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
wipe_EndScreen
|
||||
( int x,
|
||||
int y,
|
||||
int width,
|
||||
int height )
|
||||
{
|
||||
wipe_scr_end = Z_Malloc(SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL);
|
||||
I_ReadScreen(wipe_scr_end);
|
||||
V_DrawBlock(x, y, width, height, wipe_scr_start); // restore start scr.
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
wipe_ScreenWipe
|
||||
( int wipeno,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int ticks )
|
||||
{
|
||||
int rc;
|
||||
static int (*wipes[])(int, int, int) =
|
||||
{
|
||||
wipe_initColorXForm,
|
||||
wipe_doColorXForm,
|
||||
wipe_exitColorXForm,
|
||||
wipe_initMelt,
|
||||
wipe_doMelt,
|
||||
wipe_exitMelt
|
||||
};
|
||||
|
||||
// initial stuff
|
||||
if (!go)
|
||||
{
|
||||
go = 1;
|
||||
// wipe_scr = (byte *) Z_Malloc(width*height, PU_STATIC, 0); // DEBUG
|
||||
wipe_scr = I_VideoBuffer;
|
||||
(*wipes[wipeno*3])(width, height, ticks);
|
||||
}
|
||||
|
||||
// do a piece of wipe-in
|
||||
V_MarkRect(0, 0, width, height);
|
||||
rc = (*wipes[wipeno*3+1])(width, height, ticks);
|
||||
// V_DrawBlock(x, y, 0, width, height, wipe_scr); // DEBUG
|
||||
|
||||
// final stuff
|
||||
if (rc)
|
||||
{
|
||||
go = 0;
|
||||
(*wipes[wipeno*3+2])(width, height, ticks);
|
||||
}
|
||||
|
||||
return !go;
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Mission start screen wipe/melt, special effects.
|
||||
//
|
||||
|
||||
#ifndef __F_WIPE_H__
|
||||
#define __F_WIPE_H__
|
||||
|
||||
//
|
||||
// SCREEN WIPE PACKAGE
|
||||
//
|
||||
|
||||
enum
|
||||
{
|
||||
// simple gradual pixel change for 8-bit only
|
||||
wipe_ColorXForm,
|
||||
|
||||
// weird screen melt
|
||||
wipe_Melt,
|
||||
|
||||
wipe_NUMWIPES
|
||||
};
|
||||
|
||||
int
|
||||
wipe_StartScreen
|
||||
( int x,
|
||||
int y,
|
||||
int width,
|
||||
int height );
|
||||
|
||||
|
||||
int
|
||||
wipe_EndScreen
|
||||
( int x,
|
||||
int y,
|
||||
int width,
|
||||
int height );
|
||||
|
||||
|
||||
int
|
||||
wipe_ScreenWipe
|
||||
( int wipeno,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int ticks );
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,79 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Duh.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __G_GAME__
|
||||
#define __G_GAME__
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "d_event.h"
|
||||
#include "d_ticcmd.h"
|
||||
|
||||
|
||||
//
|
||||
// GAME
|
||||
//
|
||||
void G_DeathMatchSpawnPlayer (int playernum);
|
||||
|
||||
void G_InitNew (skill_t skill, int episode, int map);
|
||||
|
||||
// Can be called by the startup code or M_Responder.
|
||||
// A normal game starts at map 1,
|
||||
// but a warp test can start elsewhere
|
||||
void G_DeferedInitNew (skill_t skill, int episode, int map);
|
||||
|
||||
void G_DeferedPlayDemo (char* demo);
|
||||
|
||||
// Can be called by the startup code or M_Responder,
|
||||
// calls P_SetupLevel or W_EnterWorld.
|
||||
void G_LoadGame (char* name);
|
||||
|
||||
void G_DoLoadGame (void);
|
||||
|
||||
// Called by M_Responder.
|
||||
void G_SaveGame (int slot, char* description);
|
||||
|
||||
// Only called by startup code.
|
||||
void G_RecordDemo (char* name);
|
||||
|
||||
void G_BeginRecording (void);
|
||||
|
||||
void G_PlayDemo (char* name);
|
||||
void G_TimeDemo (char* name);
|
||||
boolean G_CheckDemoStatus (void);
|
||||
|
||||
void G_ExitLevel (void);
|
||||
void G_SecretExitLevel (void);
|
||||
|
||||
void G_WorldDone (void);
|
||||
|
||||
// Read current data from inputs and build a player movement command.
|
||||
|
||||
void G_BuildTiccmd (ticcmd_t *cmd, int maketic);
|
||||
|
||||
void G_Ticker (void);
|
||||
boolean G_Responder (event_t* ev);
|
||||
|
||||
void G_ScreenShot (void);
|
||||
|
||||
void G_DrawMouseSpeedBox(void);
|
||||
int G_VanillaVersionCode(void);
|
||||
|
||||
extern int vanilla_savegame_limit;
|
||||
extern int vanilla_demo_limit;
|
||||
#endif
|
|
@ -0,0 +1,265 @@
|
|||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// GUS emulation code.
|
||||
//
|
||||
// Actually emulating a GUS is far too much work; fortunately
|
||||
// GUS "emulation" already exists in the form of Timidity, which
|
||||
// supports GUS patch files. This code therefore converts Doom's
|
||||
// DMXGUS lump into an equivalent Timidity configuration file.
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
#define MAX_INSTRUMENTS 256
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *patch_names[MAX_INSTRUMENTS];
|
||||
int mapping[MAX_INSTRUMENTS];
|
||||
} gus_config_t;
|
||||
|
||||
char *gus_patch_path = "";
|
||||
unsigned int gus_ram_kb = 1024;
|
||||
|
||||
static unsigned int MappingIndex(void)
|
||||
{
|
||||
unsigned int result = gus_ram_kb / 256;
|
||||
|
||||
if (result < 1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (result > 4)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
static int SplitLine(char *line, char **fields, unsigned int max_fields)
|
||||
{
|
||||
unsigned int num_fields;
|
||||
char *p;
|
||||
|
||||
fields[0] = line;
|
||||
num_fields = 1;
|
||||
|
||||
for (p = line; *p != '\0'; ++p)
|
||||
{
|
||||
if (*p == ',')
|
||||
{
|
||||
*p = '\0';
|
||||
|
||||
// Skip spaces following the comma.
|
||||
do
|
||||
{
|
||||
++p;
|
||||
} while (*p != '\0' && ES_isspace(*p));
|
||||
|
||||
fields[num_fields] = p;
|
||||
++num_fields;
|
||||
--p;
|
||||
|
||||
if (num_fields >= max_fields)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (*p == '#')
|
||||
{
|
||||
*p = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Strip off trailing whitespace from the end of the line.
|
||||
p = fields[num_fields - 1] + ES_strlen(fields[num_fields - 1]);
|
||||
while (p > fields[num_fields - 1] && ES_isspace(*(p - 1)))
|
||||
{
|
||||
--p;
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
return num_fields;
|
||||
}
|
||||
|
||||
static void ParseLine(gus_config_t *config, char *line)
|
||||
{
|
||||
char *fields[6];
|
||||
unsigned int num_fields;
|
||||
unsigned int instr_id, mapped_id;
|
||||
|
||||
num_fields = SplitLine(line, fields, 6);
|
||||
|
||||
if (num_fields < 6)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
instr_id = ES_atoi(fields[0]);
|
||||
mapped_id = ES_atoi(fields[MappingIndex()]);
|
||||
|
||||
ES_free(config->patch_names[instr_id]);
|
||||
config->patch_names[instr_id] = ES_strdup(fields[5]);
|
||||
config->mapping[instr_id] = mapped_id;
|
||||
}
|
||||
|
||||
static void ParseDMXConfig(char *dmxconf, gus_config_t *config)
|
||||
{
|
||||
char *p, *newline;
|
||||
unsigned int i;
|
||||
|
||||
ES_memset(config, 0, sizeof(gus_config_t));
|
||||
|
||||
for (i = 0; i < MAX_INSTRUMENTS; ++i)
|
||||
{
|
||||
config->mapping[i] = -1;
|
||||
}
|
||||
|
||||
p = dmxconf;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
newline = ES_strchr(p, '\n');
|
||||
|
||||
if (newline != NULL)
|
||||
{
|
||||
*newline = '\0';
|
||||
}
|
||||
|
||||
ParseLine(config, p);
|
||||
|
||||
if (newline == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = newline + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void FreeDMXConfig(gus_config_t *config)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < MAX_INSTRUMENTS; ++i)
|
||||
{
|
||||
ES_free(config->patch_names[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static char *ReadDMXConfig(void)
|
||||
{
|
||||
int lumpnum;
|
||||
unsigned int len;
|
||||
char *data;
|
||||
|
||||
// TODO: This should be chosen based on gamemode == commercial:
|
||||
|
||||
lumpnum = W_CheckNumForName("DMXGUS");
|
||||
|
||||
if (lumpnum < 0)
|
||||
{
|
||||
lumpnum = W_GetNumForName("DMXGUSC");
|
||||
}
|
||||
|
||||
len = W_LumpLength(lumpnum);
|
||||
data = Z_Malloc(len + 1, PU_STATIC, NULL);
|
||||
W_ReadLump(lumpnum, data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static boolean WriteTimidityConfig(char *path, gus_config_t *config)
|
||||
{
|
||||
ES_File *fstream;
|
||||
unsigned int i;
|
||||
|
||||
fstream = ES_fopen(path, ES_WRITE_MODE);
|
||||
if (fstream == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ES_fprintf(fstream, "# Autogenerated Timidity config.\n\n");
|
||||
|
||||
ES_fprintf(fstream, "dir %s\n", gus_patch_path);
|
||||
|
||||
ES_fprintf(fstream, "\nbank 0\n\n");
|
||||
|
||||
for (i = 0; i < 128; ++i)
|
||||
{
|
||||
if (config->mapping[i] >= 0 && config->mapping[i] < MAX_INSTRUMENTS
|
||||
&& config->patch_names[config->mapping[i]] != NULL)
|
||||
{
|
||||
ES_fprintf(fstream, "%i %s\n",
|
||||
i, config->patch_names[config->mapping[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
ES_fprintf(fstream, "\ndrumset 0\n\n");
|
||||
|
||||
for (i = 128 + 25; i < MAX_INSTRUMENTS; ++i)
|
||||
{
|
||||
if (config->mapping[i] >= 0 && config->mapping[i] < MAX_INSTRUMENTS
|
||||
&& config->patch_names[config->mapping[i]] != NULL)
|
||||
{
|
||||
ES_fprintf(fstream, "%i %s\n",
|
||||
i - 128, config->patch_names[config->mapping[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
ES_fprintf(fstream, "\n");
|
||||
|
||||
ES_fclose(fstream);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean GUS_WriteConfig(char *path)
|
||||
{
|
||||
boolean result;
|
||||
char *dmxconf;
|
||||
gus_config_t config;
|
||||
|
||||
if (!ES_strcmp(gus_patch_path, ""))
|
||||
{
|
||||
ES_warnf("You haven't configured gus_patch_path.\n");
|
||||
ES_warnf("gus_patch_path needs to point to the location of "
|
||||
"your GUS patch set.\n"
|
||||
"To get a copy of the \"standard\" GUS patches, "
|
||||
"download a copy of dgguspat.zip.\n");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
dmxconf = ReadDMXConfig();
|
||||
ParseDMXConfig(dmxconf, &config);
|
||||
|
||||
result = WriteTimidityConfig(path, &config);
|
||||
|
||||
FreeDMXConfig(&config);
|
||||
Z_Free(dmxconf);
|
||||
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// GUS emulation code.
|
||||
//
|
||||
|
||||
#ifndef __GUSCONF_H__
|
||||
#define __GUSCONF_H__
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
extern char *gus_patch_path;
|
||||
extern unsigned int gus_ram_kb;
|
||||
|
||||
boolean GUS_WriteConfig(char *path);
|
||||
|
||||
#endif /* #ifndef __GUSCONF_H__ */
|
|
@ -0,0 +1,345 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION: heads-up text and input code
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomkeys.h"
|
||||
|
||||
#include "v_video.h"
|
||||
#include "i_swap.h"
|
||||
|
||||
#include "hu_lib.h"
|
||||
#include "r_local.h"
|
||||
#include "r_draw.h"
|
||||
|
||||
// boolean : whether the screen is always erased
|
||||
#define noterased viewwindowx
|
||||
|
||||
extern boolean automapactive; // in AM_map.c
|
||||
|
||||
void HUlib_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void HUlib_clearTextLine(hu_textline_t* t)
|
||||
{
|
||||
t->len = 0;
|
||||
t->l[0] = 0;
|
||||
t->needsupdate = true;
|
||||
}
|
||||
|
||||
void
|
||||
HUlib_initTextLine
|
||||
( hu_textline_t* t,
|
||||
int x,
|
||||
int y,
|
||||
patch_t** f,
|
||||
int sc )
|
||||
{
|
||||
t->x = x;
|
||||
t->y = y;
|
||||
t->f = f;
|
||||
t->sc = sc;
|
||||
HUlib_clearTextLine(t);
|
||||
}
|
||||
|
||||
boolean
|
||||
HUlib_addCharToTextLine
|
||||
( hu_textline_t* t,
|
||||
char ch )
|
||||
{
|
||||
|
||||
if (t->len == HU_MAXLINELENGTH)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
t->l[t->len++] = ch;
|
||||
t->l[t->len] = 0;
|
||||
t->needsupdate = 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
boolean HUlib_delCharFromTextLine(hu_textline_t* t)
|
||||
{
|
||||
|
||||
if (!t->len) return false;
|
||||
else
|
||||
{
|
||||
t->l[--t->len] = 0;
|
||||
t->needsupdate = 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
HUlib_drawTextLine
|
||||
( hu_textline_t* l,
|
||||
boolean drawcursor )
|
||||
{
|
||||
|
||||
int i;
|
||||
int w;
|
||||
int x;
|
||||
unsigned char c;
|
||||
|
||||
// draw the new stuff
|
||||
x = l->x;
|
||||
for (i=0;i<l->len;i++)
|
||||
{
|
||||
c = ES_toupper((int)l->l[i]);
|
||||
if (c != ' '
|
||||
&& c >= l->sc
|
||||
&& c <= '_')
|
||||
{
|
||||
w = SHORT(l->f[c - l->sc]->width);
|
||||
if (x+w > SCREENWIDTH)
|
||||
break;
|
||||
V_DrawPatchDirect(x, l->y, l->f[c - l->sc]);
|
||||
x += w;
|
||||
}
|
||||
else
|
||||
{
|
||||
x += 4;
|
||||
if (x >= SCREENWIDTH)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// draw the cursor if requested
|
||||
if (drawcursor
|
||||
&& x + SHORT(l->f['_' - l->sc]->width) <= SCREENWIDTH)
|
||||
{
|
||||
V_DrawPatchDirect(x, l->y, l->f['_' - l->sc]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// sorta called by HU_Erase and just better darn get things straight
|
||||
void HUlib_eraseTextLine(hu_textline_t* l)
|
||||
{
|
||||
int lh;
|
||||
int y;
|
||||
int yoffset;
|
||||
|
||||
// Only erases when NOT in automap and the screen is reduced,
|
||||
// and the text must either need updating or refreshing
|
||||
// (because of a recent change back from the automap)
|
||||
|
||||
if (!automapactive &&
|
||||
viewwindowx && l->needsupdate)
|
||||
{
|
||||
lh = SHORT(l->f[0]->height) + 1;
|
||||
for (y=l->y,yoffset=y*SCREENWIDTH ; y<l->y+lh ; y++,yoffset+=SCREENWIDTH)
|
||||
{
|
||||
if (y < viewwindowy || y >= viewwindowy + viewheight)
|
||||
R_VideoErase(yoffset, SCREENWIDTH); // erase entire line
|
||||
else
|
||||
{
|
||||
R_VideoErase(yoffset, viewwindowx); // erase left border
|
||||
R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx);
|
||||
// erase right border
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (l->needsupdate) l->needsupdate--;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
HUlib_initSText
|
||||
( hu_stext_t* s,
|
||||
int x,
|
||||
int y,
|
||||
int h,
|
||||
patch_t** font,
|
||||
int startchar,
|
||||
boolean* on )
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
s->h = h;
|
||||
s->on = on;
|
||||
s->laston = true;
|
||||
s->cl = 0;
|
||||
for (i=0;i<h;i++)
|
||||
HUlib_initTextLine(&s->l[i],
|
||||
x, y - i*(SHORT(font[0]->height)+1),
|
||||
font, startchar);
|
||||
|
||||
}
|
||||
|
||||
void HUlib_addLineToSText(hu_stext_t* s)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
// add a clear line
|
||||
if (++s->cl == s->h)
|
||||
s->cl = 0;
|
||||
HUlib_clearTextLine(&s->l[s->cl]);
|
||||
|
||||
// everything needs updating
|
||||
for (i=0 ; i<s->h ; i++)
|
||||
s->l[i].needsupdate = 4;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
HUlib_addMessageToSText
|
||||
( hu_stext_t* s,
|
||||
char* prefix,
|
||||
char* msg )
|
||||
{
|
||||
HUlib_addLineToSText(s);
|
||||
if (prefix)
|
||||
while (*prefix)
|
||||
HUlib_addCharToTextLine(&s->l[s->cl], *(prefix++));
|
||||
|
||||
while (*msg)
|
||||
HUlib_addCharToTextLine(&s->l[s->cl], *(msg++));
|
||||
}
|
||||
|
||||
void HUlib_drawSText(hu_stext_t* s)
|
||||
{
|
||||
int i, idx;
|
||||
hu_textline_t *l;
|
||||
|
||||
if (!*s->on)
|
||||
return; // if not on, don't draw
|
||||
|
||||
// draw everything
|
||||
for (i=0 ; i<s->h ; i++)
|
||||
{
|
||||
idx = s->cl - i;
|
||||
if (idx < 0)
|
||||
idx += s->h; // handle queue of lines
|
||||
|
||||
l = &s->l[idx];
|
||||
|
||||
// need a decision made here on whether to skip the draw
|
||||
HUlib_drawTextLine(l, false); // no cursor, please
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void HUlib_eraseSText(hu_stext_t* s)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
for (i=0 ; i<s->h ; i++)
|
||||
{
|
||||
if (s->laston && !*s->on)
|
||||
s->l[i].needsupdate = 4;
|
||||
HUlib_eraseTextLine(&s->l[i]);
|
||||
}
|
||||
s->laston = *s->on;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
HUlib_initIText
|
||||
( hu_itext_t* it,
|
||||
int x,
|
||||
int y,
|
||||
patch_t** font,
|
||||
int startchar,
|
||||
boolean* on )
|
||||
{
|
||||
it->lm = 0; // default left margin is start of text
|
||||
it->on = on;
|
||||
it->laston = true;
|
||||
HUlib_initTextLine(&it->l, x, y, font, startchar);
|
||||
}
|
||||
|
||||
|
||||
// The following deletion routines adhere to the left margin restriction
|
||||
void HUlib_delCharFromIText(hu_itext_t* it)
|
||||
{
|
||||
if (it->l.len != it->lm)
|
||||
HUlib_delCharFromTextLine(&it->l);
|
||||
}
|
||||
|
||||
void HUlib_eraseLineFromIText(hu_itext_t* it)
|
||||
{
|
||||
while (it->lm != it->l.len)
|
||||
HUlib_delCharFromTextLine(&it->l);
|
||||
}
|
||||
|
||||
// Resets left margin as well
|
||||
void HUlib_resetIText(hu_itext_t* it)
|
||||
{
|
||||
it->lm = 0;
|
||||
HUlib_clearTextLine(&it->l);
|
||||
}
|
||||
|
||||
void
|
||||
HUlib_addPrefixToIText
|
||||
( hu_itext_t* it,
|
||||
char* str )
|
||||
{
|
||||
while (*str)
|
||||
HUlib_addCharToTextLine(&it->l, *(str++));
|
||||
it->lm = it->l.len;
|
||||
}
|
||||
|
||||
// wrapper function for handling general keyed input.
|
||||
// returns true if it ate the key
|
||||
boolean
|
||||
HUlib_keyInIText
|
||||
( hu_itext_t* it,
|
||||
unsigned char ch )
|
||||
{
|
||||
ch = ES_toupper(ch);
|
||||
|
||||
if (ch >= ' ' && ch <= '_')
|
||||
HUlib_addCharToTextLine(&it->l, (char) ch);
|
||||
else
|
||||
if (ch == KEY_BACKSPACE)
|
||||
HUlib_delCharFromIText(it);
|
||||
else
|
||||
if (ch != KEY_ENTER)
|
||||
return false; // did not eat key
|
||||
|
||||
return true; // ate the key
|
||||
|
||||
}
|
||||
|
||||
void HUlib_drawIText(hu_itext_t* it)
|
||||
{
|
||||
|
||||
hu_textline_t *l = &it->l;
|
||||
|
||||
if (!*it->on)
|
||||
return;
|
||||
HUlib_drawTextLine(l, true); // draw the line w/ cursor
|
||||
|
||||
}
|
||||
|
||||
void HUlib_eraseIText(hu_itext_t* it)
|
||||
{
|
||||
if (it->laston && !*it->on)
|
||||
it->l.needsupdate = 4;
|
||||
HUlib_eraseTextLine(&it->l);
|
||||
it->laston = *it->on;
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION: none
|
||||
//
|
||||
|
||||
#ifndef __HULIB__
|
||||
#define __HULIB__
|
||||
|
||||
// We are referring to patches.
|
||||
#include "r_defs.h"
|
||||
|
||||
// font stuff
|
||||
#define HU_CHARERASE KEY_BACKSPACE
|
||||
|
||||
#define HU_MAXLINES 4
|
||||
#define HU_MAXLINELENGTH 80
|
||||
|
||||
//
|
||||
// Typedefs of widgets
|
||||
//
|
||||
|
||||
// Text Line widget
|
||||
// (parent of Scrolling Text and Input Text widgets)
|
||||
typedef struct
|
||||
{
|
||||
// left-justified position of scrolling text window
|
||||
int x;
|
||||
int y;
|
||||
|
||||
patch_t** f; // font
|
||||
int sc; // start character
|
||||
char l[HU_MAXLINELENGTH+1]; // line of text
|
||||
int len; // current line length
|
||||
|
||||
// whether this line needs to be udpated
|
||||
int needsupdate;
|
||||
|
||||
} hu_textline_t;
|
||||
|
||||
|
||||
|
||||
// Scrolling Text window widget
|
||||
// (child of Text Line widget)
|
||||
typedef struct
|
||||
{
|
||||
hu_textline_t l[HU_MAXLINES]; // text lines to draw
|
||||
int h; // height in lines
|
||||
int cl; // current line number
|
||||
|
||||
// pointer to boolean stating whether to update window
|
||||
boolean* on;
|
||||
boolean laston; // last value of *->on.
|
||||
|
||||
} hu_stext_t;
|
||||
|
||||
|
||||
|
||||
// Input Text Line widget
|
||||
// (child of Text Line widget)
|
||||
typedef struct
|
||||
{
|
||||
hu_textline_t l; // text line to input on
|
||||
|
||||
// left margin past which I am not to delete characters
|
||||
int lm;
|
||||
|
||||
// pointer to boolean stating whether to update window
|
||||
boolean* on;
|
||||
boolean laston; // last value of *->on;
|
||||
|
||||
} hu_itext_t;
|
||||
|
||||
|
||||
//
|
||||
// Widget creation, access, and update routines
|
||||
//
|
||||
|
||||
// initializes heads-up widget library
|
||||
void HUlib_init(void);
|
||||
|
||||
//
|
||||
// textline code
|
||||
//
|
||||
|
||||
// clear a line of text
|
||||
void HUlib_clearTextLine(hu_textline_t *t);
|
||||
|
||||
void HUlib_initTextLine(hu_textline_t *t, int x, int y, patch_t **f, int sc);
|
||||
|
||||
// returns success
|
||||
boolean HUlib_addCharToTextLine(hu_textline_t *t, char ch);
|
||||
|
||||
// returns success
|
||||
boolean HUlib_delCharFromTextLine(hu_textline_t *t);
|
||||
|
||||
// draws tline
|
||||
void HUlib_drawTextLine(hu_textline_t *l, boolean drawcursor);
|
||||
|
||||
// erases text line
|
||||
void HUlib_eraseTextLine(hu_textline_t *l);
|
||||
|
||||
|
||||
//
|
||||
// Scrolling Text window widget routines
|
||||
//
|
||||
|
||||
// ?
|
||||
void
|
||||
HUlib_initSText
|
||||
( hu_stext_t* s,
|
||||
int x,
|
||||
int y,
|
||||
int h,
|
||||
patch_t** font,
|
||||
int startchar,
|
||||
boolean* on );
|
||||
|
||||
// add a new line
|
||||
void HUlib_addLineToSText(hu_stext_t* s);
|
||||
|
||||
// ?
|
||||
void
|
||||
HUlib_addMessageToSText
|
||||
( hu_stext_t* s,
|
||||
char* prefix,
|
||||
char* msg );
|
||||
|
||||
// draws stext
|
||||
void HUlib_drawSText(hu_stext_t* s);
|
||||
|
||||
// erases all stext lines
|
||||
void HUlib_eraseSText(hu_stext_t* s);
|
||||
|
||||
// Input Text Line widget routines
|
||||
void
|
||||
HUlib_initIText
|
||||
( hu_itext_t* it,
|
||||
int x,
|
||||
int y,
|
||||
patch_t** font,
|
||||
int startchar,
|
||||
boolean* on );
|
||||
|
||||
// enforces left margin
|
||||
void HUlib_delCharFromIText(hu_itext_t* it);
|
||||
|
||||
// enforces left margin
|
||||
void HUlib_eraseLineFromIText(hu_itext_t* it);
|
||||
|
||||
// resets line and left margin
|
||||
void HUlib_resetIText(hu_itext_t* it);
|
||||
|
||||
// left of left-margin
|
||||
void
|
||||
HUlib_addPrefixToIText
|
||||
( hu_itext_t* it,
|
||||
char* str );
|
||||
|
||||
// whether eaten
|
||||
boolean
|
||||
HUlib_keyInIText
|
||||
( hu_itext_t* it,
|
||||
unsigned char ch );
|
||||
|
||||
void HUlib_drawIText(hu_itext_t* it);
|
||||
|
||||
// erases all itext lines
|
||||
void HUlib_eraseIText(hu_itext_t* it);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,631 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION: Heads-up displays
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomkeys.h"
|
||||
|
||||
#include "z_zone.h"
|
||||
|
||||
#include "i_swap.h"
|
||||
#include "i_video.h"
|
||||
|
||||
#include "hu_stuff.h"
|
||||
#include "hu_lib.h"
|
||||
#include "m_controls.h"
|
||||
#include "m_misc.h"
|
||||
#include "w_wad.h"
|
||||
|
||||
#include "s_sound.h"
|
||||
|
||||
#include "doomstat.h"
|
||||
|
||||
// Data.
|
||||
#include "dstrings.h"
|
||||
#include "sounds.h"
|
||||
|
||||
//
|
||||
// Locally used constants, shortcuts.
|
||||
//
|
||||
#define HU_TITLE (mapnames[(gameepisode-1)*9+gamemap-1])
|
||||
#define HU_TITLE2 (mapnames_commercial[gamemap-1])
|
||||
#define HU_TITLEP (mapnames_commercial[gamemap-1 + 32])
|
||||
#define HU_TITLET (mapnames_commercial[gamemap-1 + 64])
|
||||
#define HU_TITLE_CHEX (mapnames[gamemap - 1])
|
||||
#define HU_TITLEHEIGHT 1
|
||||
#define HU_TITLEX 0
|
||||
#define HU_TITLEY (167 - SHORT(hu_font[0]->height))
|
||||
|
||||
#define HU_INPUTTOGGLE 't'
|
||||
#define HU_INPUTX HU_MSGX
|
||||
#define HU_INPUTY (HU_MSGY + HU_MSGHEIGHT*(SHORT(hu_font[0]->height) +1))
|
||||
#define HU_INPUTWIDTH 64
|
||||
#define HU_INPUTHEIGHT 1
|
||||
|
||||
|
||||
|
||||
char *chat_macros[10] =
|
||||
{
|
||||
HUSTR_CHATMACRO0,
|
||||
HUSTR_CHATMACRO1,
|
||||
HUSTR_CHATMACRO2,
|
||||
HUSTR_CHATMACRO3,
|
||||
HUSTR_CHATMACRO4,
|
||||
HUSTR_CHATMACRO5,
|
||||
HUSTR_CHATMACRO6,
|
||||
HUSTR_CHATMACRO7,
|
||||
HUSTR_CHATMACRO8,
|
||||
HUSTR_CHATMACRO9
|
||||
};
|
||||
|
||||
char* player_names[] =
|
||||
{
|
||||
HUSTR_PLRGREEN,
|
||||
HUSTR_PLRINDIGO,
|
||||
HUSTR_PLRBROWN,
|
||||
HUSTR_PLRRED
|
||||
};
|
||||
|
||||
char chat_char; // remove later.
|
||||
static player_t* plr;
|
||||
patch_t* hu_font[HU_FONTSIZE];
|
||||
static hu_textline_t w_title;
|
||||
boolean chat_on;
|
||||
static hu_itext_t w_chat;
|
||||
static boolean always_off = false;
|
||||
static char chat_dest[MAXPLAYERS];
|
||||
static hu_itext_t w_inputbuffer[MAXPLAYERS];
|
||||
|
||||
static boolean message_on;
|
||||
boolean message_dontfuckwithme;
|
||||
static boolean message_nottobefuckedwith;
|
||||
|
||||
static hu_stext_t w_message;
|
||||
static int message_counter;
|
||||
|
||||
extern int showMessages;
|
||||
|
||||
static boolean headsupactive = false;
|
||||
|
||||
//
|
||||
// Builtin map names.
|
||||
// The actual names can be found in DStrings.h.
|
||||
//
|
||||
|
||||
char* mapnames[] = // DOOM shareware/registered/retail (Ultimate) names.
|
||||
{
|
||||
|
||||
HUSTR_E1M1,
|
||||
HUSTR_E1M2,
|
||||
HUSTR_E1M3,
|
||||
HUSTR_E1M4,
|
||||
HUSTR_E1M5,
|
||||
HUSTR_E1M6,
|
||||
HUSTR_E1M7,
|
||||
HUSTR_E1M8,
|
||||
HUSTR_E1M9,
|
||||
|
||||
HUSTR_E2M1,
|
||||
HUSTR_E2M2,
|
||||
HUSTR_E2M3,
|
||||
HUSTR_E2M4,
|
||||
HUSTR_E2M5,
|
||||
HUSTR_E2M6,
|
||||
HUSTR_E2M7,
|
||||
HUSTR_E2M8,
|
||||
HUSTR_E2M9,
|
||||
|
||||
HUSTR_E3M1,
|
||||
HUSTR_E3M2,
|
||||
HUSTR_E3M3,
|
||||
HUSTR_E3M4,
|
||||
HUSTR_E3M5,
|
||||
HUSTR_E3M6,
|
||||
HUSTR_E3M7,
|
||||
HUSTR_E3M8,
|
||||
HUSTR_E3M9,
|
||||
|
||||
HUSTR_E4M1,
|
||||
HUSTR_E4M2,
|
||||
HUSTR_E4M3,
|
||||
HUSTR_E4M4,
|
||||
HUSTR_E4M5,
|
||||
HUSTR_E4M6,
|
||||
HUSTR_E4M7,
|
||||
HUSTR_E4M8,
|
||||
HUSTR_E4M9,
|
||||
|
||||
"NEWLEVEL",
|
||||
"NEWLEVEL",
|
||||
"NEWLEVEL",
|
||||
"NEWLEVEL",
|
||||
"NEWLEVEL",
|
||||
"NEWLEVEL",
|
||||
"NEWLEVEL",
|
||||
"NEWLEVEL",
|
||||
"NEWLEVEL"
|
||||
};
|
||||
|
||||
// List of names for levels in commercial IWADs
|
||||
// (doom2.wad, plutonia.wad, tnt.wad). These are stored in a
|
||||
// single large array; WADs like pl2.wad have a MAP33, and rely on
|
||||
// the layout in the Vanilla executable, where it is possible to
|
||||
// overflow the end of one array into the next.
|
||||
|
||||
char *mapnames_commercial[] =
|
||||
{
|
||||
// DOOM 2 map names.
|
||||
|
||||
HUSTR_1,
|
||||
HUSTR_2,
|
||||
HUSTR_3,
|
||||
HUSTR_4,
|
||||
HUSTR_5,
|
||||
HUSTR_6,
|
||||
HUSTR_7,
|
||||
HUSTR_8,
|
||||
HUSTR_9,
|
||||
HUSTR_10,
|
||||
HUSTR_11,
|
||||
|
||||
HUSTR_12,
|
||||
HUSTR_13,
|
||||
HUSTR_14,
|
||||
HUSTR_15,
|
||||
HUSTR_16,
|
||||
HUSTR_17,
|
||||
HUSTR_18,
|
||||
HUSTR_19,
|
||||
HUSTR_20,
|
||||
|
||||
HUSTR_21,
|
||||
HUSTR_22,
|
||||
HUSTR_23,
|
||||
HUSTR_24,
|
||||
HUSTR_25,
|
||||
HUSTR_26,
|
||||
HUSTR_27,
|
||||
HUSTR_28,
|
||||
HUSTR_29,
|
||||
HUSTR_30,
|
||||
HUSTR_31,
|
||||
HUSTR_32,
|
||||
|
||||
// Plutonia WAD map names.
|
||||
|
||||
PHUSTR_1,
|
||||
PHUSTR_2,
|
||||
PHUSTR_3,
|
||||
PHUSTR_4,
|
||||
PHUSTR_5,
|
||||
PHUSTR_6,
|
||||
PHUSTR_7,
|
||||
PHUSTR_8,
|
||||
PHUSTR_9,
|
||||
PHUSTR_10,
|
||||
PHUSTR_11,
|
||||
|
||||
PHUSTR_12,
|
||||
PHUSTR_13,
|
||||
PHUSTR_14,
|
||||
PHUSTR_15,
|
||||
PHUSTR_16,
|
||||
PHUSTR_17,
|
||||
PHUSTR_18,
|
||||
PHUSTR_19,
|
||||
PHUSTR_20,
|
||||
|
||||
PHUSTR_21,
|
||||
PHUSTR_22,
|
||||
PHUSTR_23,
|
||||
PHUSTR_24,
|
||||
PHUSTR_25,
|
||||
PHUSTR_26,
|
||||
PHUSTR_27,
|
||||
PHUSTR_28,
|
||||
PHUSTR_29,
|
||||
PHUSTR_30,
|
||||
PHUSTR_31,
|
||||
PHUSTR_32,
|
||||
|
||||
// TNT WAD map names.
|
||||
|
||||
THUSTR_1,
|
||||
THUSTR_2,
|
||||
THUSTR_3,
|
||||
THUSTR_4,
|
||||
THUSTR_5,
|
||||
THUSTR_6,
|
||||
THUSTR_7,
|
||||
THUSTR_8,
|
||||
THUSTR_9,
|
||||
THUSTR_10,
|
||||
THUSTR_11,
|
||||
|
||||
THUSTR_12,
|
||||
THUSTR_13,
|
||||
THUSTR_14,
|
||||
THUSTR_15,
|
||||
THUSTR_16,
|
||||
THUSTR_17,
|
||||
THUSTR_18,
|
||||
THUSTR_19,
|
||||
THUSTR_20,
|
||||
|
||||
THUSTR_21,
|
||||
THUSTR_22,
|
||||
THUSTR_23,
|
||||
THUSTR_24,
|
||||
THUSTR_25,
|
||||
THUSTR_26,
|
||||
THUSTR_27,
|
||||
THUSTR_28,
|
||||
THUSTR_29,
|
||||
THUSTR_30,
|
||||
THUSTR_31,
|
||||
THUSTR_32
|
||||
};
|
||||
|
||||
void HU_Init(void)
|
||||
{
|
||||
|
||||
int i;
|
||||
int j;
|
||||
char buffer[9];
|
||||
|
||||
// load the heads-up font
|
||||
j = HU_FONTSTART;
|
||||
for (i=0;i<HU_FONTSIZE;i++)
|
||||
{
|
||||
M_snprintf(buffer, 9, "STCFN%.3d", j++);
|
||||
hu_font[i] = (patch_t *) W_CacheLumpName(buffer, PU_STATIC);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void HU_Stop(void)
|
||||
{
|
||||
headsupactive = false;
|
||||
}
|
||||
|
||||
void HU_Start(void)
|
||||
{
|
||||
|
||||
int i;
|
||||
char* s;
|
||||
|
||||
if (headsupactive)
|
||||
HU_Stop();
|
||||
|
||||
plr = &players[consoleplayer];
|
||||
message_on = false;
|
||||
message_dontfuckwithme = false;
|
||||
message_nottobefuckedwith = false;
|
||||
chat_on = false;
|
||||
|
||||
// create the message widget
|
||||
HUlib_initSText(&w_message,
|
||||
HU_MSGX, HU_MSGY, HU_MSGHEIGHT,
|
||||
hu_font,
|
||||
HU_FONTSTART, &message_on);
|
||||
|
||||
// create the map title widget
|
||||
HUlib_initTextLine(&w_title,
|
||||
HU_TITLEX, HU_TITLEY,
|
||||
hu_font,
|
||||
HU_FONTSTART);
|
||||
|
||||
switch ( logical_gamemission )
|
||||
{
|
||||
case doom:
|
||||
s = HU_TITLE;
|
||||
break;
|
||||
case doom2:
|
||||
s = HU_TITLE2;
|
||||
break;
|
||||
case pack_plut:
|
||||
s = HU_TITLEP;
|
||||
break;
|
||||
case pack_tnt:
|
||||
s = HU_TITLET;
|
||||
break;
|
||||
default:
|
||||
s = "Unknown level";
|
||||
break;
|
||||
}
|
||||
|
||||
// Chex.exe always uses the episode 1 level title
|
||||
// eg. E2M1 gives the title for E1M1
|
||||
|
||||
if (gameversion == exe_chex)
|
||||
{
|
||||
s = HU_TITLE_CHEX;
|
||||
}
|
||||
|
||||
while (*s)
|
||||
HUlib_addCharToTextLine(&w_title, *(s++));
|
||||
|
||||
// create the chat widget
|
||||
HUlib_initIText(&w_chat,
|
||||
HU_INPUTX, HU_INPUTY,
|
||||
hu_font,
|
||||
HU_FONTSTART, &chat_on);
|
||||
|
||||
// create the inputbuffer widgets
|
||||
for (i=0 ; i<MAXPLAYERS ; i++)
|
||||
HUlib_initIText(&w_inputbuffer[i], 0, 0, 0, 0, &always_off);
|
||||
|
||||
headsupactive = true;
|
||||
|
||||
}
|
||||
|
||||
void HU_Drawer(void)
|
||||
{
|
||||
|
||||
HUlib_drawSText(&w_message);
|
||||
HUlib_drawIText(&w_chat);
|
||||
if (automapactive)
|
||||
HUlib_drawTextLine(&w_title, false);
|
||||
|
||||
}
|
||||
|
||||
void HU_Erase(void)
|
||||
{
|
||||
|
||||
HUlib_eraseSText(&w_message);
|
||||
HUlib_eraseIText(&w_chat);
|
||||
HUlib_eraseTextLine(&w_title);
|
||||
|
||||
}
|
||||
|
||||
void HU_Ticker(void)
|
||||
{
|
||||
|
||||
int i, rc;
|
||||
char c;
|
||||
|
||||
// tick down message counter if message is up
|
||||
if (message_counter && !--message_counter)
|
||||
{
|
||||
message_on = false;
|
||||
message_nottobefuckedwith = false;
|
||||
}
|
||||
|
||||
if (showMessages || message_dontfuckwithme)
|
||||
{
|
||||
|
||||
// display message if necessary
|
||||
if ((plr->message && !message_nottobefuckedwith)
|
||||
|| (plr->message && message_dontfuckwithme))
|
||||
{
|
||||
HUlib_addMessageToSText(&w_message, 0, plr->message);
|
||||
plr->message = 0;
|
||||
message_on = true;
|
||||
message_counter = HU_MSGTIMEOUT;
|
||||
message_nottobefuckedwith = message_dontfuckwithme;
|
||||
message_dontfuckwithme = 0;
|
||||
}
|
||||
|
||||
} // else message_on = false;
|
||||
|
||||
// check for incoming chat characters
|
||||
if (netgame)
|
||||
{
|
||||
for (i=0 ; i<MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
if (i != consoleplayer
|
||||
&& (c = players[i].cmd.chatchar))
|
||||
{
|
||||
if (c <= HU_BROADCAST)
|
||||
chat_dest[i] = c;
|
||||
else
|
||||
{
|
||||
rc = HUlib_keyInIText(&w_inputbuffer[i], c);
|
||||
if (rc && c == KEY_ENTER)
|
||||
{
|
||||
if (w_inputbuffer[i].l.len
|
||||
&& (chat_dest[i] == consoleplayer+1
|
||||
|| chat_dest[i] == HU_BROADCAST))
|
||||
{
|
||||
HUlib_addMessageToSText(&w_message,
|
||||
player_names[i],
|
||||
w_inputbuffer[i].l.l);
|
||||
|
||||
message_nottobefuckedwith = true;
|
||||
message_on = true;
|
||||
message_counter = HU_MSGTIMEOUT;
|
||||
if ( gamemode == commercial )
|
||||
S_StartSound(0, sfx_radio);
|
||||
else
|
||||
S_StartSound(0, sfx_tink);
|
||||
}
|
||||
HUlib_resetIText(&w_inputbuffer[i]);
|
||||
}
|
||||
}
|
||||
players[i].cmd.chatchar = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define QUEUESIZE 128
|
||||
|
||||
static char chatchars[QUEUESIZE];
|
||||
static int head = 0;
|
||||
static int tail = 0;
|
||||
|
||||
|
||||
void HU_queueChatChar(char c)
|
||||
{
|
||||
if (((head + 1) & (QUEUESIZE-1)) == tail)
|
||||
{
|
||||
plr->message = HUSTR_MSGU;
|
||||
}
|
||||
else
|
||||
{
|
||||
chatchars[head] = c;
|
||||
head = (head + 1) & (QUEUESIZE-1);
|
||||
}
|
||||
}
|
||||
|
||||
char HU_dequeueChatChar(void)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (head != tail)
|
||||
{
|
||||
c = chatchars[tail];
|
||||
tail = (tail + 1) & (QUEUESIZE-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
c = 0;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
boolean HU_Responder(event_t *ev)
|
||||
{
|
||||
|
||||
static char lastmessage[HU_MAXLINELENGTH+1];
|
||||
char* macromessage;
|
||||
boolean eatkey = false;
|
||||
static boolean altdown = false;
|
||||
unsigned char c;
|
||||
int i;
|
||||
int numplayers;
|
||||
|
||||
static int num_nobrainers = 0;
|
||||
|
||||
numplayers = 0;
|
||||
for (i=0 ; i<MAXPLAYERS ; i++)
|
||||
numplayers += playeringame[i];
|
||||
|
||||
if (ev->data1 == KEY_RSHIFT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (ev->data1 == KEY_RALT || ev->data1 == KEY_LALT)
|
||||
{
|
||||
altdown = ev->type == ev_keydown;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ev->type != ev_keydown)
|
||||
return false;
|
||||
|
||||
if (!chat_on)
|
||||
{
|
||||
if (ev->data1 == key_message_refresh)
|
||||
{
|
||||
message_on = true;
|
||||
message_counter = HU_MSGTIMEOUT;
|
||||
eatkey = true;
|
||||
}
|
||||
else if (netgame && ev->data2 == key_multi_msg)
|
||||
{
|
||||
eatkey = chat_on = true;
|
||||
HUlib_resetIText(&w_chat);
|
||||
HU_queueChatChar(HU_BROADCAST);
|
||||
}
|
||||
else if (netgame && numplayers > 2)
|
||||
{
|
||||
for (i=0; i<MAXPLAYERS ; i++)
|
||||
{
|
||||
if (ev->data2 == key_multi_msgplayer[i])
|
||||
{
|
||||
if (playeringame[i] && i!=consoleplayer)
|
||||
{
|
||||
eatkey = chat_on = true;
|
||||
HUlib_resetIText(&w_chat);
|
||||
HU_queueChatChar(i+1);
|
||||
break;
|
||||
}
|
||||
else if (i == consoleplayer)
|
||||
{
|
||||
num_nobrainers++;
|
||||
if (num_nobrainers < 3)
|
||||
plr->message = HUSTR_TALKTOSELF1;
|
||||
else if (num_nobrainers < 6)
|
||||
plr->message = HUSTR_TALKTOSELF2;
|
||||
else if (num_nobrainers < 9)
|
||||
plr->message = HUSTR_TALKTOSELF3;
|
||||
else if (num_nobrainers < 32)
|
||||
plr->message = HUSTR_TALKTOSELF4;
|
||||
else
|
||||
plr->message = HUSTR_TALKTOSELF5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// send a macro
|
||||
if (altdown)
|
||||
{
|
||||
c = ev->data1 - '0';
|
||||
if (c > 9)
|
||||
return false;
|
||||
macromessage = chat_macros[c];
|
||||
|
||||
// kill last message with a '\n'
|
||||
HU_queueChatChar(KEY_ENTER); // DEBUG!!!
|
||||
|
||||
// send the macro message
|
||||
while (*macromessage)
|
||||
HU_queueChatChar(*macromessage++);
|
||||
HU_queueChatChar(KEY_ENTER);
|
||||
|
||||
// leave chat mode and notify that it was sent
|
||||
chat_on = false;
|
||||
M_StringCopy(lastmessage, chat_macros[c], sizeof(lastmessage));
|
||||
plr->message = lastmessage;
|
||||
eatkey = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = ev->data2;
|
||||
|
||||
eatkey = HUlib_keyInIText(&w_chat, c);
|
||||
if (eatkey)
|
||||
{
|
||||
// static unsigned char buf[20]; // DEBUG
|
||||
HU_queueChatChar(c);
|
||||
}
|
||||
if (c == KEY_ENTER)
|
||||
{
|
||||
chat_on = false;
|
||||
if (w_chat.l.len)
|
||||
{
|
||||
M_StringCopy(lastmessage, w_chat.l.l, sizeof(lastmessage));
|
||||
plr->message = lastmessage;
|
||||
}
|
||||
}
|
||||
else if (c == KEY_ESCAPE)
|
||||
chat_on = false;
|
||||
}
|
||||
}
|
||||
|
||||
return eatkey;
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION: Head up display
|
||||
//
|
||||
|
||||
#ifndef __HU_STUFF_H__
|
||||
#define __HU_STUFF_H__
|
||||
|
||||
#include "d_event.h"
|
||||
|
||||
//
|
||||
// Globally visible constants.
|
||||
//
|
||||
#define HU_FONTSTART '!' // the first font characters
|
||||
#define HU_FONTEND '_' // the last font characters
|
||||
|
||||
// Calculate # of glyphs in font.
|
||||
#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1)
|
||||
|
||||
#define HU_BROADCAST 5
|
||||
|
||||
#define HU_MSGX 0
|
||||
#define HU_MSGY 0
|
||||
#define HU_MSGWIDTH 64 // in characters
|
||||
#define HU_MSGHEIGHT 1 // in lines
|
||||
|
||||
#define HU_MSGTIMEOUT (4*TICRATE)
|
||||
|
||||
//
|
||||
// HEADS UP TEXT
|
||||
//
|
||||
|
||||
void HU_Init(void);
|
||||
void HU_Start(void);
|
||||
|
||||
boolean HU_Responder(event_t* ev);
|
||||
|
||||
void HU_Ticker(void);
|
||||
void HU_Drawer(void);
|
||||
char HU_dequeueChatChar(void);
|
||||
void HU_Erase(void);
|
||||
|
||||
extern char *chat_macros[10];
|
||||
|
||||
#endif
|
|
@ -0,0 +1,172 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "doomkeys.h"
|
||||
#include "i_joystick.h"
|
||||
#include "i_system.h"
|
||||
#include "i_swap.h"
|
||||
#include "i_timer.h"
|
||||
#include "i_video.h"
|
||||
#include "i_scale.h"
|
||||
#include "m_argv.h"
|
||||
#include "m_config.h"
|
||||
#include "m_misc.h"
|
||||
#include "tables.h"
|
||||
#include "v_video.h"
|
||||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
int vanilla_keyboard_mapping = 1;
|
||||
|
||||
// Is the shift key currently down?
|
||||
|
||||
static int shiftdown = 0;
|
||||
|
||||
// Lookup table for mapping ASCII characters to their equivalent when
|
||||
// shift is pressed on an American layout keyboard:
|
||||
static const char shiftxform[] =
|
||||
{
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
|
||||
31, ' ', '!', '"', '#', '$', '%', '&',
|
||||
'"', // shift-'
|
||||
'(', ')', '*', '+',
|
||||
'<', // shift-,
|
||||
'_', // shift--
|
||||
'>', // shift-.
|
||||
'?', // shift-/
|
||||
')', // shift-0
|
||||
'!', // shift-1
|
||||
'@', // shift-2
|
||||
'#', // shift-3
|
||||
'$', // shift-4
|
||||
'%', // shift-5
|
||||
'^', // shift-6
|
||||
'&', // shift-7
|
||||
'*', // shift-8
|
||||
'(', // shift-9
|
||||
':',
|
||||
':', // shift-;
|
||||
'<',
|
||||
'+', // shift-=
|
||||
'>', '?', '@',
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
|
||||
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'[', // shift-[
|
||||
'!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
|
||||
']', // shift-]
|
||||
'"', '_',
|
||||
'\'', // shift-`
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
|
||||
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'{', '|', '}', '~', 127
|
||||
};
|
||||
|
||||
static unsigned char TranslateKey(unsigned char key)
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
// Get the equivalent ASCII (Unicode?) character for a keypress.
|
||||
|
||||
static unsigned char GetTypedChar(unsigned char key)
|
||||
{
|
||||
key = TranslateKey(key);
|
||||
|
||||
// Is shift held down? If so, perform a translation.
|
||||
|
||||
if (shiftdown > 0)
|
||||
{
|
||||
if (key >= 0 && key < arrlen(shiftxform))
|
||||
{
|
||||
key = shiftxform[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
key = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static void UpdateShiftStatus(int pressed, unsigned char key)
|
||||
{
|
||||
int change;
|
||||
|
||||
if (pressed) {
|
||||
change = 1;
|
||||
} else {
|
||||
change = -1;
|
||||
}
|
||||
|
||||
if (key == KEY_RSHIFT) {
|
||||
shiftdown += change;
|
||||
}
|
||||
}
|
||||
|
||||
void I_GetEvent(void)
|
||||
{
|
||||
event_t event;
|
||||
int pressed;
|
||||
unsigned char key;
|
||||
|
||||
while (ES_GetKey(&pressed, &key))
|
||||
{
|
||||
UpdateShiftStatus(pressed, key);
|
||||
// process event
|
||||
|
||||
if (pressed)
|
||||
{
|
||||
// data1 has the key pressed, data2 has the character
|
||||
// (shift-translated, etc)
|
||||
event.type = ev_keydown;
|
||||
event.data1 = TranslateKey(key);
|
||||
event.data2 = GetTypedChar(key);
|
||||
|
||||
if (event.data1 != 0)
|
||||
{
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
event.type = ev_keyup;
|
||||
event.data1 = TranslateKey(key);
|
||||
|
||||
// data2 is just initialized to zero for ev_keyup.
|
||||
// For ev_keydown it's the shifted Unicode character
|
||||
// that was typed, but if something wants to detect
|
||||
// key releases it should do so based on data1
|
||||
// (key ID), not the printable char.
|
||||
|
||||
event.data2 = 0;
|
||||
|
||||
if (event.data1 != 0)
|
||||
{
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void I_InitInput(void)
|
||||
{}
|
|
@ -0,0 +1,92 @@
|
|||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// SDL Joystick code.
|
||||
//
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "d_event.h"
|
||||
#include "i_joystick.h"
|
||||
#include "i_system.h"
|
||||
|
||||
#include "m_config.h"
|
||||
#include "m_misc.h"
|
||||
|
||||
// When an axis is within the dead zone, it is set to zero.
|
||||
// This is 5% of the full range:
|
||||
|
||||
#define DEAD_ZONE (32768 / 3)
|
||||
|
||||
// Configuration variables:
|
||||
|
||||
// Standard default.cfg Joystick enable/disable
|
||||
|
||||
static int usejoystick = 0;
|
||||
|
||||
// Joystick to use, as an SDL joystick index:
|
||||
|
||||
static int joystick_index = -1;
|
||||
|
||||
// Which joystick axis to use for horizontal movement, and whether to
|
||||
// invert the direction:
|
||||
|
||||
static int joystick_x_axis = 0;
|
||||
static int joystick_x_invert = 0;
|
||||
|
||||
// Which joystick axis to use for vertical movement, and whether to
|
||||
// invert the direction:
|
||||
|
||||
static int joystick_y_axis = 1;
|
||||
static int joystick_y_invert = 0;
|
||||
|
||||
// Which joystick axis to use for strafing?
|
||||
|
||||
static int joystick_strafe_axis = -1;
|
||||
static int joystick_strafe_invert = 0;
|
||||
|
||||
// Virtual to physical button joystick button mapping. By default this
|
||||
// is a straight mapping.
|
||||
static int joystick_physical_buttons[NUM_VIRTUAL_BUTTONS] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
|
||||
};
|
||||
|
||||
void I_ShutdownJoystick(void)
|
||||
{}
|
||||
|
||||
void I_InitJoystick(void)
|
||||
{}
|
||||
|
||||
void I_UpdateJoystick(void)
|
||||
{}
|
||||
|
||||
void I_BindJoystickVariables(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
M_BindVariable("use_joystick", &usejoystick);
|
||||
M_BindVariable("joystick_index", &joystick_index);
|
||||
M_BindVariable("joystick_x_axis", &joystick_x_axis);
|
||||
M_BindVariable("joystick_y_axis", &joystick_y_axis);
|
||||
M_BindVariable("joystick_strafe_axis", &joystick_strafe_axis);
|
||||
M_BindVariable("joystick_x_invert", &joystick_x_invert);
|
||||
M_BindVariable("joystick_y_invert", &joystick_y_invert);
|
||||
M_BindVariable("joystick_strafe_invert",&joystick_strafe_invert);
|
||||
|
||||
for (i = 0; i < NUM_VIRTUAL_BUTTONS; ++i)
|
||||
{
|
||||
char name[32];
|
||||
M_snprintf(name, sizeof(name), "joystick_physical_button%i", i);
|
||||
M_BindVariable(name, &joystick_physical_buttons[i]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// System-specific joystick interface.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __I_JOYSTICK__
|
||||
#define __I_JOYSTICK__
|
||||
|
||||
// Number of "virtual" joystick buttons defined in configuration files.
|
||||
// This needs to be at least as large as the number of different key
|
||||
// bindings supported by the higher-level game code (joyb* variables).
|
||||
#define NUM_VIRTUAL_BUTTONS 10
|
||||
|
||||
// If this bit is set in a configuration file axis value, the axis is
|
||||
// not actually a joystick axis, but instead is a "button axis". This
|
||||
// means that instead of reading an SDL joystick axis, we read the
|
||||
// state of two buttons to get the axis value. This is needed for eg.
|
||||
// the PS3 SIXAXIS controller, where the D-pad buttons register as
|
||||
// buttons, not as two axes.
|
||||
#define BUTTON_AXIS 0x10000
|
||||
|
||||
// Query whether a given axis value describes a button axis.
|
||||
#define IS_BUTTON_AXIS(axis) ((axis) >= 0 && ((axis) & BUTTON_AXIS) != 0)
|
||||
|
||||
// Get the individual buttons from a button axis value.
|
||||
#define BUTTON_AXIS_NEG(axis) ((axis) & 0xff)
|
||||
#define BUTTON_AXIS_POS(axis) (((axis) >> 8) & 0xff)
|
||||
|
||||
// Create a button axis value from two button values.
|
||||
#define CREATE_BUTTON_AXIS(neg, pos) (BUTTON_AXIS | (neg) | ((pos) << 8))
|
||||
|
||||
// If this bit is set in an axis value, the axis is not actually a
|
||||
// joystick axis, but is a "hat" axis. This means that we read (one of)
|
||||
// the hats on the joystick.
|
||||
#define HAT_AXIS 0x20000
|
||||
|
||||
#define IS_HAT_AXIS(axis) ((axis) >= 0 && ((axis) & HAT_AXIS) != 0)
|
||||
|
||||
// Get the hat number from a hat axis value.
|
||||
#define HAT_AXIS_HAT(axis) ((axis) & 0xff)
|
||||
// Which axis of the hat? (horizonal or vertical)
|
||||
#define HAT_AXIS_DIRECTION(axis) (((axis) >> 8) & 0xff)
|
||||
|
||||
#define CREATE_HAT_AXIS(hat, direction) \
|
||||
(HAT_AXIS | (hat) | ((direction) << 8))
|
||||
|
||||
#define HAT_AXIS_HORIZONTAL 1
|
||||
#define HAT_AXIS_VERTICAL 2
|
||||
|
||||
void I_InitJoystick(void);
|
||||
void I_ShutdownJoystick(void);
|
||||
void I_UpdateJoystick(void);
|
||||
|
||||
void I_BindJoystickVariables(void);
|
||||
|
||||
#endif /* #ifndef __I_JOYSTICK__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Pixel-doubling scale up functions.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __I_SCALE__
|
||||
#define __I_SCALE__
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
void I_InitScale(byte *_src_buffer, byte *_dest_buffer, int _dest_pitch);
|
||||
void I_ResetScaleTables(byte *palette);
|
||||
|
||||
// Scaled modes (direct multiples of 320x200)
|
||||
|
||||
extern screen_mode_t mode_scale_1x;
|
||||
extern screen_mode_t mode_scale_2x;
|
||||
extern screen_mode_t mode_scale_3x;
|
||||
extern screen_mode_t mode_scale_4x;
|
||||
extern screen_mode_t mode_scale_5x;
|
||||
|
||||
// Vertically stretched modes (320x200 -> multiples of 320x240)
|
||||
|
||||
extern screen_mode_t mode_stretch_1x;
|
||||
extern screen_mode_t mode_stretch_2x;
|
||||
extern screen_mode_t mode_stretch_3x;
|
||||
extern screen_mode_t mode_stretch_4x;
|
||||
extern screen_mode_t mode_stretch_5x;
|
||||
|
||||
// Horizontally squashed modes (320x200 -> multiples of 256x200)
|
||||
|
||||
extern screen_mode_t mode_squash_1x;
|
||||
extern screen_mode_t mode_squash_2x;
|
||||
extern screen_mode_t mode_squash_3x;
|
||||
extern screen_mode_t mode_squash_4x;
|
||||
extern screen_mode_t mode_squash_5x;
|
||||
|
||||
#endif /* #ifndef __I_SCALE__ */
|
|
@ -0,0 +1,397 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION: none
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "doomtype.h"
|
||||
|
||||
#include "i_sound.h"
|
||||
#include "i_video.h"
|
||||
#include "m_argv.h"
|
||||
#include "m_config.h"
|
||||
|
||||
// Sound sample rate to use for digital output (Hz)
|
||||
|
||||
int snd_samplerate = 44100;
|
||||
|
||||
// Maximum number of bytes to dedicate to allocated sound effects.
|
||||
// (Default: 64MB)
|
||||
|
||||
int snd_cachesize = 64 * 1024 * 1024;
|
||||
|
||||
// Config variable that controls the sound buffer size.
|
||||
// We default to 28ms (1000 / 35fps = 1 buffer per tic).
|
||||
|
||||
int snd_maxslicetime_ms = 28;
|
||||
|
||||
// External command to invoke to play back music.
|
||||
|
||||
char *snd_musiccmd = "";
|
||||
|
||||
// Low-level sound and music modules we are using
|
||||
|
||||
static sound_module_t *sound_module = NULL;
|
||||
static music_module_t *music_module = NULL;
|
||||
|
||||
int snd_musicdevice = SNDDEVICE_SB;
|
||||
int snd_sfxdevice = SNDDEVICE_SB;
|
||||
|
||||
// DOS-specific options: These are unused but should be maintained
|
||||
// so that the config file can be shared between chocolate
|
||||
// doom and doom.exe
|
||||
|
||||
static int snd_sbport = 0;
|
||||
static int snd_sbirq = 0;
|
||||
static int snd_sbdma = 0;
|
||||
static int snd_mport = 0;
|
||||
|
||||
// Compiled-in sound modules:
|
||||
|
||||
static sound_module_t *sound_modules[] =
|
||||
{
|
||||
#ifdef FEATURE_SOUND
|
||||
&ES_sound_module,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
// Check if a sound device is in the given list of devices
|
||||
|
||||
static boolean SndDeviceInList(snddevice_t device, snddevice_t *list,
|
||||
int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<len; ++i)
|
||||
{
|
||||
if (device == list[i])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find and initialize a sound_module_t appropriate for the setting
|
||||
// in snd_sfxdevice.
|
||||
|
||||
static void InitSfxModule(boolean use_sfx_prefix)
|
||||
{
|
||||
int i;
|
||||
|
||||
sound_module = NULL;
|
||||
|
||||
for (i=0; sound_modules[i] != NULL; ++i)
|
||||
{
|
||||
// Is the sfx device in the list of devices supported by
|
||||
// this module?
|
||||
|
||||
if (SndDeviceInList(snd_sfxdevice,
|
||||
sound_modules[i]->sound_devices,
|
||||
sound_modules[i]->num_sound_devices))
|
||||
{
|
||||
// Initialize the module
|
||||
|
||||
if (sound_modules[i]->Init(use_sfx_prefix))
|
||||
{
|
||||
sound_module = sound_modules[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize music according to snd_musicdevice.
|
||||
|
||||
static void InitMusicModule(void)
|
||||
{
|
||||
#ifdef FEATURE_SOUND
|
||||
music_module = &ES_music_module;
|
||||
#endif /* FEATURE_SOUND */
|
||||
}
|
||||
|
||||
//
|
||||
// Initializes sound stuff, including volume
|
||||
// Sets channels, SFX and music volume,
|
||||
// allocates channel buffer, sets S_sfx lookup.
|
||||
//
|
||||
|
||||
void I_InitSound(boolean use_sfx_prefix)
|
||||
{
|
||||
boolean nosound, nosfx, nomusic;
|
||||
|
||||
//!
|
||||
// @vanilla
|
||||
//
|
||||
// Disable all sound output.
|
||||
//
|
||||
|
||||
nosound = M_CheckParm("-nosound") > 0;
|
||||
|
||||
//!
|
||||
// @vanilla
|
||||
//
|
||||
// Disable sound effects.
|
||||
//
|
||||
|
||||
nosfx = M_CheckParm("-nosfx") > 0;
|
||||
|
||||
//!
|
||||
// @vanilla
|
||||
//
|
||||
// Disable music.
|
||||
//
|
||||
|
||||
nomusic = M_CheckParm("-nomusic") > 0;
|
||||
|
||||
// Initialize the sound and music subsystems.
|
||||
|
||||
if (!nosound && !screensaver_mode)
|
||||
{
|
||||
if (!nosfx)
|
||||
{
|
||||
InitSfxModule(use_sfx_prefix);
|
||||
}
|
||||
|
||||
if (!nomusic)
|
||||
{
|
||||
InitMusicModule();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void I_ShutdownSound(void)
|
||||
{
|
||||
if (sound_module != NULL)
|
||||
{
|
||||
sound_module->Shutdown();
|
||||
}
|
||||
|
||||
if (music_module != NULL)
|
||||
{
|
||||
music_module->Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
int I_GetSfxLumpNum(sfxinfo_t *sfxinfo)
|
||||
{
|
||||
if (sound_module != NULL)
|
||||
{
|
||||
return sound_module->GetSfxLumpNum(sfxinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void I_UpdateSound(void)
|
||||
{
|
||||
if (sound_module != NULL)
|
||||
{
|
||||
sound_module->Update();
|
||||
}
|
||||
|
||||
if (music_module != NULL && music_module->Poll != NULL)
|
||||
{
|
||||
music_module->Poll();
|
||||
}
|
||||
}
|
||||
|
||||
static void CheckVolumeSeparation(int *vol, int *sep)
|
||||
{
|
||||
if (*sep < 0)
|
||||
{
|
||||
*sep = 0;
|
||||
}
|
||||
else if (*sep > 254)
|
||||
{
|
||||
*sep = 254;
|
||||
}
|
||||
|
||||
if (*vol < 0)
|
||||
{
|
||||
*vol = 0;
|
||||
}
|
||||
else if (*vol > 127)
|
||||
{
|
||||
*vol = 127;
|
||||
}
|
||||
}
|
||||
|
||||
void I_UpdateSoundParams(int channel, int vol, int sep)
|
||||
{
|
||||
if (sound_module != NULL)
|
||||
{
|
||||
CheckVolumeSeparation(&vol, &sep);
|
||||
sound_module->UpdateSoundParams(channel, vol, sep);
|
||||
}
|
||||
}
|
||||
|
||||
int I_StartSound(sfxinfo_t *sfxinfo, int channel, int vol, int sep)
|
||||
{
|
||||
if (sound_module != NULL)
|
||||
{
|
||||
CheckVolumeSeparation(&vol, &sep);
|
||||
return sound_module->StartSound(sfxinfo, channel, vol, sep);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void I_StopSound(int channel)
|
||||
{
|
||||
if (sound_module != NULL)
|
||||
{
|
||||
sound_module->StopSound(channel);
|
||||
}
|
||||
}
|
||||
|
||||
boolean I_SoundIsPlaying(int channel)
|
||||
{
|
||||
if (sound_module != NULL)
|
||||
{
|
||||
return sound_module->SoundIsPlaying(channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void I_PrecacheSounds(sfxinfo_t *sounds, int num_sounds)
|
||||
{
|
||||
if (sound_module != NULL && sound_module->CacheSounds != NULL)
|
||||
{
|
||||
sound_module->CacheSounds(sounds, num_sounds);
|
||||
}
|
||||
}
|
||||
|
||||
void I_InitMusic(void)
|
||||
{
|
||||
if(music_module != NULL)
|
||||
{
|
||||
music_module->Init();
|
||||
}
|
||||
}
|
||||
|
||||
void I_ShutdownMusic(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void I_SetMusicVolume(int volume)
|
||||
{
|
||||
if (music_module != NULL)
|
||||
{
|
||||
music_module->SetMusicVolume(volume);
|
||||
}
|
||||
}
|
||||
|
||||
void I_PauseSong(void)
|
||||
{
|
||||
if (music_module != NULL)
|
||||
{
|
||||
music_module->PauseMusic();
|
||||
}
|
||||
}
|
||||
|
||||
void I_ResumeSong(void)
|
||||
{
|
||||
if (music_module != NULL)
|
||||
{
|
||||
music_module->ResumeMusic();
|
||||
}
|
||||
}
|
||||
|
||||
void *I_RegisterSong(void *data, int len)
|
||||
{
|
||||
if (music_module != NULL)
|
||||
{
|
||||
return music_module->RegisterSong(data, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void I_UnRegisterSong(void *handle)
|
||||
{
|
||||
if (music_module != NULL)
|
||||
{
|
||||
music_module->UnRegisterSong(handle);
|
||||
}
|
||||
}
|
||||
|
||||
void I_PlaySong(void *handle, boolean looping)
|
||||
{
|
||||
if (music_module != NULL)
|
||||
{
|
||||
music_module->PlaySong(handle, looping);
|
||||
}
|
||||
}
|
||||
|
||||
void I_StopSong(void)
|
||||
{
|
||||
if (music_module != NULL)
|
||||
{
|
||||
music_module->StopSong();
|
||||
}
|
||||
}
|
||||
|
||||
boolean I_MusicIsPlaying(void)
|
||||
{
|
||||
if (music_module != NULL)
|
||||
{
|
||||
return music_module->MusicIsPlaying();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void I_BindSoundVariables(void)
|
||||
{
|
||||
extern int use_libsamplerate;
|
||||
extern float libsamplerate_scale;
|
||||
|
||||
M_BindVariable("snd_musicdevice", &snd_musicdevice);
|
||||
M_BindVariable("snd_sfxdevice", &snd_sfxdevice);
|
||||
M_BindVariable("snd_sbport", &snd_sbport);
|
||||
M_BindVariable("snd_sbirq", &snd_sbirq);
|
||||
M_BindVariable("snd_sbdma", &snd_sbdma);
|
||||
M_BindVariable("snd_mport", &snd_mport);
|
||||
M_BindVariable("snd_maxslicetime_ms", &snd_maxslicetime_ms);
|
||||
M_BindVariable("snd_musiccmd", &snd_musiccmd);
|
||||
M_BindVariable("snd_samplerate", &snd_samplerate);
|
||||
M_BindVariable("snd_cachesize", &snd_cachesize);
|
||||
|
||||
#ifdef FEATURE_SOUND
|
||||
M_BindVariable("use_libsamplerate", &use_libsamplerate);
|
||||
M_BindVariable("libsamplerate_scale", &libsamplerate_scale);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// The not so system specific sound interface.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __I_SOUND__
|
||||
#define __I_SOUND__
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
//
|
||||
// SoundFX struct.
|
||||
//
|
||||
typedef struct sfxinfo_struct sfxinfo_t;
|
||||
|
||||
struct sfxinfo_struct
|
||||
{
|
||||
// tag name, used for hexen.
|
||||
char *tagname;
|
||||
|
||||
// lump name. If we are running with use_sfx_prefix=true, a
|
||||
// 'DS' (or 'DP' for PC speaker sounds) is prepended to this.
|
||||
|
||||
char name[9];
|
||||
|
||||
// Sfx priority
|
||||
int priority;
|
||||
|
||||
// referenced sound if a link
|
||||
sfxinfo_t *link;
|
||||
|
||||
// pitch if a link
|
||||
int pitch;
|
||||
|
||||
// volume if a link
|
||||
int volume;
|
||||
|
||||
// this is checked every second to see if sound
|
||||
// can be thrown out (if 0, then decrement, if -1,
|
||||
// then throw out, if > 0, then it is in use)
|
||||
int usefulness;
|
||||
|
||||
// lump number of sfx
|
||||
int lumpnum;
|
||||
|
||||
// Maximum number of channels that the sound can be played on
|
||||
// (Heretic)
|
||||
int numchannels;
|
||||
|
||||
// data used by the low level code
|
||||
void *driver_data;
|
||||
};
|
||||
|
||||
//
|
||||
// MusicInfo struct.
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
// up to 6-character name
|
||||
char *name;
|
||||
|
||||
// lump number of music
|
||||
int lumpnum;
|
||||
|
||||
// music data
|
||||
void *data;
|
||||
|
||||
// music handle once registered
|
||||
void *handle;
|
||||
|
||||
} musicinfo_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SNDDEVICE_NONE = 0,
|
||||
SNDDEVICE_PCSPEAKER = 1,
|
||||
SNDDEVICE_ADLIB = 2,
|
||||
SNDDEVICE_SB = 3,
|
||||
SNDDEVICE_PAS = 4,
|
||||
SNDDEVICE_GUS = 5,
|
||||
SNDDEVICE_WAVEBLASTER = 6,
|
||||
SNDDEVICE_SOUNDCANVAS = 7,
|
||||
SNDDEVICE_GENMIDI = 8,
|
||||
SNDDEVICE_AWE32 = 9,
|
||||
SNDDEVICE_CD = 10,
|
||||
} snddevice_t;
|
||||
|
||||
// Interface for sound modules
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// List of sound devices that this sound module is used for.
|
||||
|
||||
snddevice_t *sound_devices;
|
||||
int num_sound_devices;
|
||||
|
||||
// Initialise sound module
|
||||
// Returns true if successfully initialised
|
||||
|
||||
boolean (*Init)(boolean use_sfx_prefix);
|
||||
|
||||
// Shutdown sound module
|
||||
|
||||
void (*Shutdown)(void);
|
||||
|
||||
// Returns the lump index of the given sound.
|
||||
|
||||
int (*GetSfxLumpNum)(sfxinfo_t *sfxinfo);
|
||||
|
||||
// Called periodically to update the subsystem.
|
||||
|
||||
void (*Update)(void);
|
||||
|
||||
// Update the sound settings on the given channel.
|
||||
|
||||
void (*UpdateSoundParams)(int channel, int vol, int sep);
|
||||
|
||||
// Start a sound on a given channel. Returns the channel id
|
||||
// or -1 on failure.
|
||||
|
||||
int (*StartSound)(sfxinfo_t *sfxinfo, int channel, int vol, int sep);
|
||||
|
||||
// Stop the sound playing on the given channel.
|
||||
|
||||
void (*StopSound)(int channel);
|
||||
|
||||
// Query if a sound is playing on the given channel
|
||||
|
||||
boolean (*SoundIsPlaying)(int channel);
|
||||
|
||||
// Called on startup to precache sound effects (if necessary)
|
||||
|
||||
void (*CacheSounds)(sfxinfo_t *sounds, int num_sounds);
|
||||
|
||||
} sound_module_t;
|
||||
|
||||
void I_InitSound(boolean use_sfx_prefix);
|
||||
void I_ShutdownSound(void);
|
||||
int I_GetSfxLumpNum(sfxinfo_t *sfxinfo);
|
||||
void I_UpdateSound(void);
|
||||
void I_UpdateSoundParams(int channel, int vol, int sep);
|
||||
int I_StartSound(sfxinfo_t *sfxinfo, int channel, int vol, int sep);
|
||||
void I_StopSound(int channel);
|
||||
boolean I_SoundIsPlaying(int channel);
|
||||
void I_PrecacheSounds(sfxinfo_t *sounds, int num_sounds);
|
||||
|
||||
// Interface for music modules
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// List of sound devices that this music module is used for.
|
||||
|
||||
snddevice_t *sound_devices;
|
||||
int num_sound_devices;
|
||||
|
||||
// Initialise the music subsystem
|
||||
|
||||
boolean (*Init)(void);
|
||||
|
||||
// Shutdown the music subsystem
|
||||
|
||||
void (*Shutdown)(void);
|
||||
|
||||
// Set music volume - range 0-127
|
||||
|
||||
void (*SetMusicVolume)(int volume);
|
||||
|
||||
// Pause music
|
||||
|
||||
void (*PauseMusic)(void);
|
||||
|
||||
// Un-pause music
|
||||
|
||||
void (*ResumeMusic)(void);
|
||||
|
||||
// Register a song handle from data
|
||||
// Returns a handle that can be used to play the song
|
||||
|
||||
void *(*RegisterSong)(void *data, int len);
|
||||
|
||||
// Un-register (free) song data
|
||||
|
||||
void (*UnRegisterSong)(void *handle);
|
||||
|
||||
// Play the song
|
||||
|
||||
void (*PlaySong)(void *handle, boolean looping);
|
||||
|
||||
// Stop playing the current song.
|
||||
|
||||
void (*StopSong)(void);
|
||||
|
||||
// Query if music is playing.
|
||||
|
||||
boolean (*MusicIsPlaying)(void);
|
||||
|
||||
// Invoked periodically to poll.
|
||||
|
||||
void (*Poll)(void);
|
||||
} music_module_t;
|
||||
|
||||
void I_InitMusic(void);
|
||||
void I_ShutdownMusic(void);
|
||||
void I_SetMusicVolume(int volume);
|
||||
void I_PauseSong(void);
|
||||
void I_ResumeSong(void);
|
||||
void *I_RegisterSong(void *data, int len);
|
||||
void I_UnRegisterSong(void *handle);
|
||||
void I_PlaySong(void *handle, boolean looping);
|
||||
void I_StopSong(void);
|
||||
boolean I_MusicIsPlaying(void);
|
||||
|
||||
extern int snd_sfxdevice;
|
||||
extern int snd_musicdevice;
|
||||
extern int snd_samplerate;
|
||||
extern int snd_cachesize;
|
||||
extern int snd_maxslicetime_ms;
|
||||
extern char *snd_musiccmd;
|
||||
|
||||
void I_BindSoundVariables(void);
|
||||
|
||||
// Sound modules
|
||||
|
||||
void I_InitTimidityConfig(void);
|
||||
#ifdef FEATURE_SOUND
|
||||
extern sound_module_t ES_sound_module;
|
||||
extern music_module_t ES_music_module;
|
||||
#endif
|
||||
extern sound_module_t sound_pcsound_module;
|
||||
extern music_module_t music_opl_module;
|
||||
|
||||
// For OPL module:
|
||||
|
||||
extern int opl_io_port;
|
||||
|
||||
// For native music module:
|
||||
|
||||
extern char *timidity_cfg_path;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Endianess handling, swapping 16bit and 32bit.
|
||||
//
|
||||
|
||||
#ifndef __I_SWAP__
|
||||
#define __I_SWAP__
|
||||
|
||||
#define SHORT(x) ((signed short) (x))
|
||||
#define LONG(x) ((signed int) (x))
|
||||
|
||||
#define SYS_LITTLE_ENDIAN
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,349 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "m_argv.h"
|
||||
#include "m_config.h"
|
||||
#include "m_misc.h"
|
||||
#include "i_joystick.h"
|
||||
#include "i_sound.h"
|
||||
#include "i_timer.h"
|
||||
#include "i_video.h"
|
||||
|
||||
#include "i_system.h"
|
||||
|
||||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
#define DEFAULT_RAM 16 /* MiB */
|
||||
#define MIN_RAM 16 /* MiB */
|
||||
|
||||
|
||||
typedef struct atexit_listentry_s atexit_listentry_t;
|
||||
|
||||
struct atexit_listentry_s
|
||||
{
|
||||
atexit_func_t func;
|
||||
boolean run_on_error;
|
||||
atexit_listentry_t *next;
|
||||
};
|
||||
|
||||
static atexit_listentry_t *exit_funcs = NULL;
|
||||
|
||||
void I_AtExit(atexit_func_t func, boolean run_on_error)
|
||||
{
|
||||
atexit_listentry_t *entry;
|
||||
|
||||
entry = ES_malloc(sizeof(*entry));
|
||||
|
||||
entry->func = func;
|
||||
entry->run_on_error = run_on_error;
|
||||
entry->next = exit_funcs;
|
||||
exit_funcs = entry;
|
||||
}
|
||||
|
||||
// Tactile feedback function, probably used for the Logitech Cyberman
|
||||
|
||||
void I_Tactile(int on, int off, int total)
|
||||
{
|
||||
}
|
||||
|
||||
// Zone memory auto-allocation function that allocates the zone size
|
||||
// by trying progressively smaller zone sizes until one is found that
|
||||
// works.
|
||||
|
||||
static byte *AutoAllocMemory(int *size, int default_ram, int min_ram)
|
||||
{
|
||||
byte *zonemem;
|
||||
|
||||
// Allocate the zone memory. This loop tries progressively smaller
|
||||
// zone sizes until a size is found that can be allocated.
|
||||
// If we used the -mb command line parameter, only the parameter
|
||||
// provided is accepted.
|
||||
|
||||
zonemem = NULL;
|
||||
|
||||
while (zonemem == NULL)
|
||||
{
|
||||
// We need a reasonable minimum amount of RAM to start.
|
||||
|
||||
if (default_ram < min_ram)
|
||||
{
|
||||
I_Error("Unable to allocate %i MiB of RAM for zone", default_ram);
|
||||
}
|
||||
|
||||
// Try to allocate the zone memory.
|
||||
|
||||
*size = default_ram * 1024 * 1024;
|
||||
|
||||
zonemem = ES_malloc(*size);
|
||||
|
||||
// Failed to allocate? Reduce zone size until we reach a size
|
||||
// that is acceptable.
|
||||
|
||||
if (zonemem == NULL)
|
||||
{
|
||||
default_ram -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return zonemem;
|
||||
}
|
||||
|
||||
byte *I_ZoneBase (int *size)
|
||||
{
|
||||
byte *zonemem;
|
||||
int min_ram, default_ram;
|
||||
int p;
|
||||
|
||||
//!
|
||||
// @arg <mb>
|
||||
//
|
||||
// Specify the heap size, in MiB (default 16).
|
||||
//
|
||||
|
||||
p = M_CheckParmWithArgs("-mb", 1);
|
||||
|
||||
if (p > 0)
|
||||
{
|
||||
default_ram = ES_atoi(myargv[p+1]);
|
||||
min_ram = default_ram;
|
||||
}
|
||||
else
|
||||
{
|
||||
default_ram = DEFAULT_RAM;
|
||||
min_ram = MIN_RAM;
|
||||
}
|
||||
|
||||
zonemem = AutoAllocMemory(size, default_ram, min_ram);
|
||||
|
||||
ES_debugf("zone memory: %p, %x allocated for zone\n",
|
||||
zonemem, *size);
|
||||
|
||||
return zonemem;
|
||||
}
|
||||
|
||||
void I_PrintBanner(char *msg)
|
||||
{
|
||||
ES_infof("%s\n", msg);
|
||||
}
|
||||
|
||||
void I_PrintDivider(void)
|
||||
{
|
||||
ES_infof("===========================================================================\n");
|
||||
}
|
||||
|
||||
void I_PrintStartupBanner(char *gamedescription)
|
||||
{
|
||||
I_PrintDivider();
|
||||
I_PrintBanner(gamedescription);
|
||||
I_PrintDivider();
|
||||
|
||||
ES_infof(
|
||||
PACKAGE_NAME " is free software, covered by the GNU General Public"
|
||||
" License. There is NO warranty; not even for MERCHANTABILITY or FITNESS"
|
||||
" FOR A PARTICULAR PURPOSE. You are welcome to change and distribute"
|
||||
" copies under certain conditions. See the source for more information.\n");
|
||||
|
||||
I_PrintDivider();
|
||||
}
|
||||
|
||||
//
|
||||
// I_ConsoleStdout
|
||||
//
|
||||
// Returns true if stdout is a real console, false if it is a file
|
||||
//
|
||||
|
||||
boolean I_ConsoleStdout(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// I_Quit
|
||||
//
|
||||
|
||||
void I_Quit (void)
|
||||
{
|
||||
atexit_listentry_t *entry;
|
||||
|
||||
// Run through all exit functions
|
||||
|
||||
entry = exit_funcs;
|
||||
|
||||
while (entry != NULL)
|
||||
{
|
||||
entry->func();
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// I_Error
|
||||
//
|
||||
|
||||
static boolean already_quitting = false;
|
||||
|
||||
void I_Error (char *error, ...)
|
||||
{
|
||||
char msgbuf[512];
|
||||
va_list argptr;
|
||||
atexit_listentry_t *entry;
|
||||
boolean exit_gui_popup;
|
||||
|
||||
if (already_quitting)
|
||||
{
|
||||
ES_warnf("Recursive call to I_Error detected.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
already_quitting = true;
|
||||
}
|
||||
|
||||
// Write a copy of the message into buffer.
|
||||
va_start(argptr, error);
|
||||
ES_memset(msgbuf, 0, sizeof(msgbuf));
|
||||
M_vsnprintf(msgbuf, sizeof(msgbuf), error, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
// Shutdown. Here might be other errors.
|
||||
|
||||
entry = exit_funcs;
|
||||
|
||||
while (entry != NULL)
|
||||
{
|
||||
if (entry->run_on_error)
|
||||
{
|
||||
entry->func();
|
||||
}
|
||||
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
ES_Crash(msgbuf);
|
||||
}
|
||||
|
||||
//
|
||||
// Read Access Violation emulation.
|
||||
//
|
||||
// From PrBoom+, by entryway.
|
||||
//
|
||||
|
||||
// C:\>debug
|
||||
// -d 0:0
|
||||
//
|
||||
// DOS 6.22:
|
||||
// 0000:0000 (57 92 19 00) F4 06 70 00-(16 00)
|
||||
// DOS 7.1:
|
||||
// 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00)
|
||||
// Win98:
|
||||
// 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00)
|
||||
// DOSBox under XP:
|
||||
// 0000:0000 (00 00 00 F1) ?? ?? ?? 00-(07 00)
|
||||
|
||||
#define DOS_MEM_DUMP_SIZE 10
|
||||
|
||||
static const unsigned char mem_dump_dos622[DOS_MEM_DUMP_SIZE] = {
|
||||
0x57, 0x92, 0x19, 0x00, 0xF4, 0x06, 0x70, 0x00, 0x16, 0x00};
|
||||
static const unsigned char mem_dump_win98[DOS_MEM_DUMP_SIZE] = {
|
||||
0x9E, 0x0F, 0xC9, 0x00, 0x65, 0x04, 0x70, 0x00, 0x16, 0x00};
|
||||
static const unsigned char mem_dump_dosbox[DOS_MEM_DUMP_SIZE] = {
|
||||
0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00};
|
||||
static unsigned char mem_dump_custom[DOS_MEM_DUMP_SIZE];
|
||||
|
||||
static const unsigned char *dos_mem_dump = mem_dump_dos622;
|
||||
|
||||
boolean I_GetMemoryValue(unsigned int offset, void *value, int size)
|
||||
{
|
||||
static boolean firsttime = true;
|
||||
|
||||
if (firsttime)
|
||||
{
|
||||
int p, i, val;
|
||||
|
||||
firsttime = false;
|
||||
i = 0;
|
||||
|
||||
//!
|
||||
// @category compat
|
||||
// @arg <version>
|
||||
//
|
||||
// Specify DOS version to emulate for NULL pointer dereference
|
||||
// emulation. Supported versions are: dos622, dos71, dosbox.
|
||||
// The default is to emulate DOS 7.1 (Windows 98).
|
||||
//
|
||||
|
||||
p = M_CheckParmWithArgs("-setmem", 1);
|
||||
|
||||
if (p > 0)
|
||||
{
|
||||
if (!ES_strcasecmp(myargv[p + 1], "dos622"))
|
||||
{
|
||||
dos_mem_dump = mem_dump_dos622;
|
||||
}
|
||||
if (!ES_strcasecmp(myargv[p + 1], "dos71"))
|
||||
{
|
||||
dos_mem_dump = mem_dump_win98;
|
||||
}
|
||||
else if (!ES_strcasecmp(myargv[p + 1], "dosbox"))
|
||||
{
|
||||
dos_mem_dump = mem_dump_dosbox;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < DOS_MEM_DUMP_SIZE; ++i)
|
||||
{
|
||||
++p;
|
||||
|
||||
if (p >= myargc || myargv[p][0] == '-')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
M_StrToInt(myargv[p], &val);
|
||||
mem_dump_custom[i++] = (unsigned char) val;
|
||||
}
|
||||
|
||||
dos_mem_dump = mem_dump_custom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 1:
|
||||
*((unsigned char *) value) = dos_mem_dump[offset];
|
||||
return true;
|
||||
case 2:
|
||||
*((unsigned short *) value) = dos_mem_dump[offset]
|
||||
| (dos_mem_dump[offset + 1] << 8);
|
||||
return true;
|
||||
case 4:
|
||||
*((unsigned int *) value) = dos_mem_dump[offset]
|
||||
| (dos_mem_dump[offset + 1] << 8)
|
||||
| (dos_mem_dump[offset + 2] << 16)
|
||||
| (dos_mem_dump[offset + 3] << 24);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// System specific interface stuff.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __I_SYSTEM__
|
||||
#define __I_SYSTEM__
|
||||
|
||||
#include "d_ticcmd.h"
|
||||
#include "d_event.h"
|
||||
|
||||
|
||||
typedef void (*atexit_func_t)(void);
|
||||
|
||||
// Called by DoomMain.
|
||||
void I_Init (void);
|
||||
|
||||
// Called by startup code
|
||||
// to get the ammount of memory to malloc
|
||||
// for the zone management.
|
||||
byte* I_ZoneBase (int *size);
|
||||
|
||||
boolean I_ConsoleStdout(void);
|
||||
|
||||
|
||||
// Asynchronous interrupt functions should maintain private queues
|
||||
// that are read by the synchronous functions
|
||||
// to be converted into events.
|
||||
|
||||
// Either returns a null ticcmd,
|
||||
// or calls a loadable driver to build it.
|
||||
// This ticcmd will then be modified by the gameloop
|
||||
// for normal input.
|
||||
ticcmd_t* I_BaseTiccmd (void);
|
||||
|
||||
|
||||
// Called by M_Responder when quit is selected.
|
||||
// Clean exit, displays sell blurb.
|
||||
void I_Quit (void);
|
||||
|
||||
__attribute__((noreturn))
|
||||
void I_Error (char *error, ...);
|
||||
|
||||
void I_Tactile (int on, int off, int total);
|
||||
|
||||
boolean I_GetMemoryValue(unsigned int offset, void *value, int size);
|
||||
|
||||
// Schedule a function to be called when the program exits.
|
||||
// If run_if_error is true, the function is called if the exit
|
||||
// is due to an error (I_Error)
|
||||
|
||||
void I_AtExit(atexit_func_t func, boolean run_if_error);
|
||||
|
||||
// Add all system-specific config file variable bindings.
|
||||
|
||||
void I_BindVariables(void);
|
||||
|
||||
// Print startup banner copyright message.
|
||||
|
||||
void I_PrintStartupBanner(char *gamedescription);
|
||||
|
||||
// Print a centered text banner displaying the given string.
|
||||
|
||||
void I_PrintBanner(char *text);
|
||||
|
||||
// Print a dividing line for startup banners.
|
||||
|
||||
void I_PrintDivider(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Timer functions.
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "i_timer.h"
|
||||
#include "doomtype.h"
|
||||
|
||||
//
|
||||
// I_GetTime
|
||||
// returns time in 1/35th second tics
|
||||
//
|
||||
|
||||
static uint32_t basetime = 0;
|
||||
|
||||
int I_GetTicks(void)
|
||||
{
|
||||
return ES_GetTicksMs();
|
||||
}
|
||||
|
||||
int I_GetTime (void)
|
||||
{
|
||||
uint32_t ticks;
|
||||
|
||||
ticks = I_GetTicks();
|
||||
|
||||
if (basetime == 0)
|
||||
basetime = ticks;
|
||||
|
||||
ticks -= basetime;
|
||||
|
||||
return (ticks * TICRATE) / 1000;
|
||||
}
|
||||
|
||||
//
|
||||
// Same as I_GetTime, but returns time in milliseconds
|
||||
//
|
||||
int I_GetTimeMS(void)
|
||||
{
|
||||
uint32_t ticks;
|
||||
|
||||
ticks = I_GetTicks();
|
||||
|
||||
if (basetime == 0)
|
||||
basetime = ticks;
|
||||
|
||||
return ticks - basetime;
|
||||
}
|
||||
|
||||
// Sleep for a specified number of ms
|
||||
|
||||
void I_Sleep(int ms)
|
||||
{
|
||||
ES_SleepMs(ms);
|
||||
}
|
||||
|
||||
void I_WaitVBL(int count)
|
||||
{}
|
||||
|
||||
void I_InitTimer(void)
|
||||
{}
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// System-specific timer interface
|
||||
//
|
||||
|
||||
|
||||
#ifndef __I_TIMER__
|
||||
#define __I_TIMER__
|
||||
|
||||
#define TICRATE 35
|
||||
|
||||
// Called by D_DoomLoop,
|
||||
// returns current time in tics.
|
||||
int I_GetTime (void);
|
||||
|
||||
// returns current time in ms
|
||||
int I_GetTimeMS (void);
|
||||
|
||||
// Pause for a specified number of ms
|
||||
void I_Sleep(int ms);
|
||||
|
||||
// Initialize timer
|
||||
void I_InitTimer(void);
|
||||
|
||||
// Wait for vertical retrace or pause a bit.
|
||||
void I_WaitVBL(int count);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,397 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// DOOM graphics stuff for X11, UNIX.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "v_video.h"
|
||||
#include "m_argv.h"
|
||||
#include "d_event.h"
|
||||
#include "d_main.h"
|
||||
#include "i_video.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
#include "tables.h"
|
||||
#include "doomkeys.h"
|
||||
|
||||
struct FB_BitField
|
||||
{
|
||||
uint32_t offset; /* beginning of bitfield */
|
||||
uint32_t length; /* length of bitfield */
|
||||
};
|
||||
|
||||
struct FB_ScreenInfo
|
||||
{
|
||||
uint32_t xres; /* visible resolution */
|
||||
uint32_t yres;
|
||||
uint32_t xres_virtual; /* virtual resolution */
|
||||
uint32_t yres_virtual;
|
||||
|
||||
uint32_t bits_per_pixel; /* guess what */
|
||||
|
||||
/* >1 = FOURCC */
|
||||
struct FB_BitField red; /* bitfield in s_Fb mem if true color, */
|
||||
struct FB_BitField green; /* else only length is significant */
|
||||
struct FB_BitField blue;
|
||||
struct FB_BitField transp; /* transparency */
|
||||
};
|
||||
|
||||
static struct FB_ScreenInfo s_Fb;
|
||||
uint32_t fb_scaling = 1;
|
||||
int usemouse = 0;
|
||||
|
||||
|
||||
#ifdef CMAP256
|
||||
|
||||
boolean palette_changed;
|
||||
struct color colors[256];
|
||||
|
||||
#else // CMAP256
|
||||
|
||||
static struct color colors[256];
|
||||
|
||||
|
||||
#endif // CMAP256
|
||||
|
||||
|
||||
void I_GetEvent(void);
|
||||
|
||||
// The screen buffer; this is modified to draw things to the screen
|
||||
|
||||
byte *I_VideoBuffer = NULL;
|
||||
|
||||
// If true, game is running as a screensaver
|
||||
|
||||
boolean screensaver_mode = false;
|
||||
|
||||
// Flag indicating whether the screen is currently visible:
|
||||
// when the screen isnt visible, don't render the screen
|
||||
|
||||
boolean screenvisible;
|
||||
|
||||
// Mouse acceleration
|
||||
//
|
||||
// This emulates some of the behavior of DOS mouse drivers by increasing
|
||||
// the speed when the mouse is moved fast.
|
||||
//
|
||||
// The mouse input values are input directly to the game, but when
|
||||
// the values exceed the value of mouse_threshold, they are multiplied
|
||||
// by mouse_acceleration to increase the speed.
|
||||
|
||||
float mouse_acceleration = 2.0;
|
||||
int mouse_threshold = 10;
|
||||
|
||||
// Gamma correction level to use
|
||||
|
||||
int usegamma = 0;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
byte r;
|
||||
byte g;
|
||||
byte b;
|
||||
} col_t;
|
||||
|
||||
// Palette converted to RGB565
|
||||
|
||||
static uint16_t rgb565_palette[256];
|
||||
|
||||
void cmap_to_rgb565(uint16_t * out, uint8_t * in, size_t in_pixels)
|
||||
{
|
||||
size_t i, j;
|
||||
struct color c;
|
||||
uint16_t r, g, b;
|
||||
|
||||
for (i = 0; i < in_pixels; i++)
|
||||
{
|
||||
c = colors[*in];
|
||||
r = ((uint16_t)(c.r >> 3)) << 11;
|
||||
g = ((uint16_t)(c.g >> 2)) << 5;
|
||||
b = ((uint16_t)(c.b >> 3)) << 0;
|
||||
*out = (r | g | b);
|
||||
|
||||
in++;
|
||||
for (j = 0; j < fb_scaling; j++) {
|
||||
out++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cmap_to_fb(uint8_t * out, uint8_t * in, size_t in_pixels)
|
||||
{
|
||||
size_t i, j, k;
|
||||
struct color c;
|
||||
uint32_t pix;
|
||||
uint16_t r, g, b;
|
||||
|
||||
for (i = 0; i < in_pixels; i++)
|
||||
{
|
||||
c = colors[*in]; /* R:8 G:8 B:8 format! */
|
||||
r = (uint16_t)(c.r >> (8 - s_Fb.red.length));
|
||||
g = (uint16_t)(c.g >> (8 - s_Fb.green.length));
|
||||
b = (uint16_t)(c.b >> (8 - s_Fb.blue.length));
|
||||
pix = r << s_Fb.red.offset;
|
||||
pix |= g << s_Fb.green.offset;
|
||||
pix |= b << s_Fb.blue.offset;
|
||||
|
||||
for (k = 0; k < fb_scaling; k++) {
|
||||
for (j = 0; j < s_Fb.bits_per_pixel/8; j++) {
|
||||
*out = (pix >> (j*8));
|
||||
out++;
|
||||
}
|
||||
}
|
||||
in++;
|
||||
}
|
||||
}
|
||||
|
||||
void I_InitGraphics (void)
|
||||
{
|
||||
ES_memset(&s_Fb, 0, sizeof(struct FB_ScreenInfo));
|
||||
s_Fb.xres = RES_X;
|
||||
s_Fb.yres = RES_Y;
|
||||
s_Fb.xres_virtual = s_Fb.xres;
|
||||
s_Fb.yres_virtual = s_Fb.yres;
|
||||
|
||||
#ifdef CMAP256
|
||||
|
||||
s_Fb.bits_per_pixel = 8;
|
||||
|
||||
#else // CMAP256
|
||||
|
||||
s_Fb.bits_per_pixel = 32;
|
||||
|
||||
s_Fb.blue.length = 8;
|
||||
s_Fb.green.length = 8;
|
||||
s_Fb.red.length = 8;
|
||||
s_Fb.transp.length = 8;
|
||||
|
||||
s_Fb.blue.offset = 0;
|
||||
s_Fb.green.offset = 8;
|
||||
s_Fb.red.offset = 16;
|
||||
s_Fb.transp.offset = 24;
|
||||
|
||||
#endif // CMAP256
|
||||
|
||||
ES_debugf("I_InitGraphics: framebuffer: x_res: %d, y_res: %d, x_virtual: %d, y_virtual: %d, bpp: %d\n",
|
||||
s_Fb.xres, s_Fb.yres, s_Fb.xres_virtual, s_Fb.yres_virtual, s_Fb.bits_per_pixel);
|
||||
|
||||
ES_debugf("I_InitGraphics: framebuffer: RGBA: %d%d%d%d, red_off: %d, green_off: %d, blue_off: %d, transp_off: %d\n",
|
||||
s_Fb.red.length, s_Fb.green.length, s_Fb.blue.length, s_Fb.transp.length, s_Fb.red.offset, s_Fb.green.offset, s_Fb.blue.offset, s_Fb.transp.offset);
|
||||
|
||||
ES_debugf("I_InitGraphics: DOOM screen size: w x h: %d x %d\n", SCREENWIDTH, SCREENHEIGHT);
|
||||
|
||||
int i = M_CheckParmWithArgs("-scaling", 1);
|
||||
if (i > 0) {
|
||||
fb_scaling = (uint32_t)ES_atoi(myargv[i + 1]);
|
||||
ES_debugf("I_InitGraphics: Scaling factor: %d\n", fb_scaling);
|
||||
} else {
|
||||
fb_scaling = s_Fb.xres / SCREENWIDTH;
|
||||
if (s_Fb.yres / SCREENHEIGHT < fb_scaling)
|
||||
fb_scaling = s_Fb.yres / SCREENHEIGHT;
|
||||
ES_debugf("I_InitGraphics: Auto-scaling factor: %d\n", fb_scaling);
|
||||
}
|
||||
|
||||
|
||||
/* Allocate screen to draw to */
|
||||
I_VideoBuffer = (byte*)Z_Malloc (SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL); // For DOOM to draw on
|
||||
|
||||
screenvisible = true;
|
||||
|
||||
extern void I_InitInput(void);
|
||||
I_InitInput();
|
||||
}
|
||||
|
||||
void I_ShutdownGraphics (void)
|
||||
{
|
||||
Z_Free (I_VideoBuffer);
|
||||
}
|
||||
|
||||
void I_StartFrame (void)
|
||||
{}
|
||||
|
||||
void I_StartTic (void)
|
||||
{
|
||||
I_GetEvent();
|
||||
}
|
||||
|
||||
void I_UpdateNoBlit (void)
|
||||
{}
|
||||
|
||||
//
|
||||
// I_FinishUpdate
|
||||
//
|
||||
|
||||
void I_FinishUpdate (void)
|
||||
{
|
||||
int y;
|
||||
int x_offset, y_offset, x_offset_end;
|
||||
unsigned char *line_in, *line_out;
|
||||
|
||||
/* Offsets in case FB is bigger than DOOM */
|
||||
/* 600 = s_Fb heigt, 200 screenheight */
|
||||
/* 600 = s_Fb heigt, 200 screenheight */
|
||||
/* 2048 =s_Fb width, 320 screenwidth */
|
||||
y_offset = (((s_Fb.yres - (SCREENHEIGHT * fb_scaling)) * s_Fb.bits_per_pixel/8)) / 2;
|
||||
x_offset = (((s_Fb.xres - (SCREENWIDTH * fb_scaling)) * s_Fb.bits_per_pixel/8)) / 2; // XXX: siglent FB hack: /4 instead of /2, since it seems to handle the resolution in a funny way
|
||||
//x_offset = 0;
|
||||
x_offset_end = ((s_Fb.xres - (SCREENWIDTH * fb_scaling)) * s_Fb.bits_per_pixel/8) - x_offset;
|
||||
|
||||
/* DRAW SCREEN */
|
||||
line_in = (unsigned char *) I_VideoBuffer;
|
||||
line_out = (unsigned char *) ES_ScreenBuffer;
|
||||
|
||||
y = SCREENHEIGHT;
|
||||
|
||||
while (y--)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < fb_scaling; i++) {
|
||||
line_out += x_offset;
|
||||
#ifdef CMAP256
|
||||
if (fb_scaling == 1) {
|
||||
ES_memcpy(line_out, line_in, SCREENWIDTH); /* fb_width is bigger than Doom SCREENWIDTH... */
|
||||
} else {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < SCREENWIDTH; j++) {
|
||||
int k;
|
||||
for (k = 0; k < fb_scaling; k++) {
|
||||
line_out[j * fb_scaling + k] = line_in[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
//cmap_to_rgb565((void*)line_out, (void*)line_in, SCREENWIDTH);
|
||||
cmap_to_fb((void*)line_out, (void*)line_in, SCREENWIDTH);
|
||||
#endif
|
||||
line_out += (SCREENWIDTH * fb_scaling * (s_Fb.bits_per_pixel/8)) + x_offset_end;
|
||||
}
|
||||
line_in += SCREENWIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// I_ReadScreen
|
||||
//
|
||||
void I_ReadScreen (byte* scr)
|
||||
{
|
||||
ES_memcpy (scr, I_VideoBuffer, SCREENWIDTH * SCREENHEIGHT);
|
||||
}
|
||||
|
||||
//
|
||||
// I_SetPalette
|
||||
//
|
||||
#define GFX_RGB565(r, g, b) ((((r & 0xF8) >> 3) << 11) | (((g & 0xFC) >> 2) << 5) | ((b & 0xF8) >> 3))
|
||||
#define GFX_RGB565_R(color) ((0xF800 & color) >> 11)
|
||||
#define GFX_RGB565_G(color) ((0x07E0 & color) >> 5)
|
||||
#define GFX_RGB565_B(color) (0x001F & color)
|
||||
|
||||
void I_SetPalette (byte* palette)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* performance boost:
|
||||
* map to the right pixel format over here! */
|
||||
|
||||
for (i=0; i<256; ++i ) {
|
||||
colors[i].a = 0;
|
||||
colors[i].r = gammatable[usegamma][*palette++];
|
||||
colors[i].g = gammatable[usegamma][*palette++];
|
||||
colors[i].b = gammatable[usegamma][*palette++];
|
||||
}
|
||||
|
||||
#ifdef CMAP256
|
||||
|
||||
palette_changed = true;
|
||||
|
||||
#endif // CMAP256
|
||||
}
|
||||
|
||||
// Given an RGB value, find the closest matching palette index.
|
||||
|
||||
int I_GetPaletteIndex(int r, int g, int b)
|
||||
{
|
||||
int best, best_diff, diff;
|
||||
int i;
|
||||
col_t color;
|
||||
|
||||
ES_debugf("I_GetPaletteIndex\n");
|
||||
|
||||
best = 0;
|
||||
best_diff = INT_MAX;
|
||||
|
||||
for (i = 0; i < 256; ++i)
|
||||
{
|
||||
color.r = GFX_RGB565_R(rgb565_palette[i]);
|
||||
color.g = GFX_RGB565_G(rgb565_palette[i]);
|
||||
color.b = GFX_RGB565_B(rgb565_palette[i]);
|
||||
|
||||
diff = (r - color.r) * (r - color.r)
|
||||
+ (g - color.g) * (g - color.g)
|
||||
+ (b - color.b) * (b - color.b);
|
||||
|
||||
if (diff < best_diff)
|
||||
{
|
||||
best = i;
|
||||
best_diff = diff;
|
||||
}
|
||||
|
||||
if (diff == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
void I_BeginRead(void)
|
||||
{}
|
||||
|
||||
void I_EndRead(void)
|
||||
{}
|
||||
|
||||
void I_SetWindowTitle(char *title)
|
||||
{
|
||||
ES_debugf("I_SetWindowTitle: %s\n", title);
|
||||
}
|
||||
|
||||
void I_GraphicsCheckCommandLine(void)
|
||||
{}
|
||||
|
||||
void I_SetGrabMouseCallback(grabmouse_callback_t func)
|
||||
{}
|
||||
|
||||
void I_EnableLoadingDisk(void)
|
||||
{}
|
||||
|
||||
void I_BindVideoVariables(void)
|
||||
{}
|
||||
|
||||
void I_DisplayFPSDots(boolean dots_on)
|
||||
{}
|
||||
|
||||
void I_CheckIsScreensaver(void)
|
||||
{}
|
|
@ -0,0 +1,175 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// System specific interface stuff.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __I_VIDEO__
|
||||
#define __I_VIDEO__
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
// Screen width and height.
|
||||
|
||||
#define SCREENWIDTH 320
|
||||
#define SCREENHEIGHT 200
|
||||
|
||||
// Screen width used for "squash" scale functions
|
||||
|
||||
#define SCREENWIDTH_4_3 256
|
||||
|
||||
// Screen height used for "stretch" scale functions.
|
||||
|
||||
#define SCREENHEIGHT_4_3 240
|
||||
|
||||
#define MAX_MOUSE_BUTTONS 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Screen width and height
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
// Initialisation function to call when using this mode.
|
||||
// Called with a pointer to the Doom palette.
|
||||
//
|
||||
// If NULL, no init function is called.
|
||||
|
||||
void (*InitMode)(byte *palette);
|
||||
|
||||
// Function to call to draw the screen from the source buffer.
|
||||
// Return true if draw was successful.
|
||||
|
||||
boolean (*DrawScreen)(int x1, int y1, int x2, int y2);
|
||||
|
||||
// If true, this is a "poor quality" mode. The autoadjust
|
||||
// code should always attempt to use a different mode to this
|
||||
// mode in fullscreen.
|
||||
//
|
||||
// Some notes about what "poor quality" means in this context:
|
||||
//
|
||||
// The aspect ratio correction works by scaling up to the larger
|
||||
// screen size and then drawing pixels on the edges between the
|
||||
// "virtual" pixels so that an authentic blocky look-and-feel is
|
||||
// achieved.
|
||||
//
|
||||
// For a mode like 640x480, you can imagine the grid of the
|
||||
// "original" pixels spaced out, with extra "blurry" pixels added
|
||||
// in the space between them to fill it out. However, when you're
|
||||
// running at a resolution like 320x240, this is not the case. In
|
||||
// the small screen case, every single pixel has to be a blurry
|
||||
// interpolation of two pixels from the original image.
|
||||
//
|
||||
// If you run in 320x240 and put your face up close to the screen
|
||||
// you can see this: it's particularly visible in the small yellow
|
||||
// status bar numbers for example. Overall it still looks "okay"
|
||||
// but there's an obvious - albeit small - deterioration in
|
||||
// quality.
|
||||
//
|
||||
// Once you get to 640x480, all the original pixels are there at
|
||||
// least once and it's okay (the higher the resolution, the more
|
||||
// accurate it is). When I first wrote the code I was expecting
|
||||
// that even higher resolutions would be needed before it would
|
||||
// look acceptable, but it turned out to be okay even at 640x480.
|
||||
|
||||
boolean poor_quality;
|
||||
} screen_mode_t;
|
||||
|
||||
typedef boolean (*grabmouse_callback_t)(void);
|
||||
|
||||
// Called by D_DoomMain,
|
||||
// determines the hardware configuration
|
||||
// and sets up the video mode
|
||||
void I_InitGraphics (void);
|
||||
|
||||
void I_GraphicsCheckCommandLine(void);
|
||||
|
||||
void I_ShutdownGraphics(void);
|
||||
|
||||
// Takes full 8 bit values.
|
||||
void I_SetPalette (byte* palette);
|
||||
int I_GetPaletteIndex(int r, int g, int b);
|
||||
|
||||
void I_UpdateNoBlit (void);
|
||||
void I_FinishUpdate (void);
|
||||
|
||||
void I_ReadScreen (byte* scr);
|
||||
|
||||
void I_BeginRead (void);
|
||||
|
||||
void I_SetWindowTitle(char *title);
|
||||
|
||||
void I_CheckIsScreensaver(void);
|
||||
void I_SetGrabMouseCallback(grabmouse_callback_t func);
|
||||
|
||||
void I_DisplayFPSDots(boolean dots_on);
|
||||
void I_BindVideoVariables(void);
|
||||
|
||||
void I_InitWindowTitle(void);
|
||||
void I_InitWindowIcon(void);
|
||||
|
||||
// Called before processing any tics in a frame (just after displaying a frame).
|
||||
// Time consuming syncronous operations are performed here (joystick reading).
|
||||
|
||||
void I_StartFrame (void);
|
||||
|
||||
// Called before processing each tic in a frame.
|
||||
// Quick syncronous operations are performed here.
|
||||
|
||||
void I_StartTic (void);
|
||||
|
||||
// Enable the loading disk image displayed when reading from disk.
|
||||
|
||||
void I_EnableLoadingDisk(void);
|
||||
|
||||
void I_EndRead (void);
|
||||
|
||||
struct color {
|
||||
uint32_t b:8;
|
||||
uint32_t g:8;
|
||||
uint32_t r:8;
|
||||
uint32_t a:8;
|
||||
};
|
||||
|
||||
|
||||
extern char *video_driver;
|
||||
extern boolean screenvisible;
|
||||
|
||||
extern float mouse_acceleration;
|
||||
extern int mouse_threshold;
|
||||
extern int vanilla_keyboard_mapping;
|
||||
extern boolean screensaver_mode;
|
||||
extern int usegamma;
|
||||
extern byte *I_VideoBuffer;
|
||||
|
||||
extern int screen_width;
|
||||
extern int screen_height;
|
||||
extern int screen_bpp;
|
||||
extern int fullscreen;
|
||||
extern int aspect_ratio_correct;
|
||||
|
||||
extern int show_diskicon;
|
||||
extern int diskicon_readbytes;
|
||||
|
||||
#ifdef CMAP256
|
||||
|
||||
extern boolean palette_changed;
|
||||
extern struct color colors[256];
|
||||
|
||||
#endif // CMAP256
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,82 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "i_system.h"
|
||||
#include "m_misc.h"
|
||||
#include "m_argv.h" // haleyjd 20110212: warning fix
|
||||
|
||||
int myargc;
|
||||
char** myargv;
|
||||
|
||||
//
|
||||
// M_CheckParm
|
||||
// Checks for the given parameter
|
||||
// in the program's command line arguments.
|
||||
// Returns the argument number (1 to argc-1)
|
||||
// or 0 if not present
|
||||
//
|
||||
|
||||
int M_CheckParmWithArgs(char *check, int num_args)
|
||||
{
|
||||
for (int i = 1; i < myargc - num_args; i++)
|
||||
{
|
||||
if (!ES_strcasecmp(check, myargv[i]))
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// M_ParmExists
|
||||
//
|
||||
// Returns true if the given parameter exists in the program's command
|
||||
// line arguments, false if not.
|
||||
//
|
||||
|
||||
boolean M_ParmExists(char *check)
|
||||
{
|
||||
return M_CheckParm(check) != 0;
|
||||
}
|
||||
|
||||
int M_CheckParm(char *check)
|
||||
{
|
||||
return M_CheckParmWithArgs(check, 0);
|
||||
}
|
||||
|
||||
#define MAXARGVS 100
|
||||
|
||||
// Return the name of the executable used to start the program:
|
||||
|
||||
char *M_GetExecutableName(void)
|
||||
{
|
||||
char *sep;
|
||||
|
||||
sep = ES_strchr(myargv[0], DIR_SEPARATOR);
|
||||
|
||||
if (sep == NULL)
|
||||
{
|
||||
return myargv[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return sep + 1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Nil.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __M_ARGV__
|
||||
#define __M_ARGV__
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
//
|
||||
// MISC
|
||||
//
|
||||
extern int myargc;
|
||||
extern char** myargv;
|
||||
|
||||
// Returns the position of the given parameter
|
||||
// in the arg list (0 if not found).
|
||||
int M_CheckParm (char* check);
|
||||
|
||||
// Same as M_CheckParm, but checks that num_args arguments are available
|
||||
// following the specified argument.
|
||||
int M_CheckParmWithArgs(char *check, int num_args);
|
||||
|
||||
void M_FindResponseFile(void);
|
||||
|
||||
// Parameter has been specified?
|
||||
|
||||
boolean M_ParmExists(char *check);
|
||||
|
||||
// Get name of executable used to run this program:
|
||||
|
||||
char *M_GetExecutableName(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Main loop menu stuff.
|
||||
// Random number LUT.
|
||||
// Default Config File.
|
||||
// PCX Screenshots.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#include "m_bbox.h"
|
||||
|
||||
|
||||
|
||||
|
||||
void M_ClearBox (fixed_t *box)
|
||||
{
|
||||
box[BOXTOP] = box[BOXRIGHT] = INT_MIN;
|
||||
box[BOXBOTTOM] = box[BOXLEFT] = INT_MAX;
|
||||
}
|
||||
|
||||
void
|
||||
M_AddToBox
|
||||
( fixed_t* box,
|
||||
fixed_t x,
|
||||
fixed_t y )
|
||||
{
|
||||
if (x<box[BOXLEFT])
|
||||
box[BOXLEFT] = x;
|
||||
else if (x>box[BOXRIGHT])
|
||||
box[BOXRIGHT] = x;
|
||||
if (y<box[BOXBOTTOM])
|
||||
box[BOXBOTTOM] = y;
|
||||
else if (y>box[BOXTOP])
|
||||
box[BOXTOP] = y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Nil.
|
||||
//
|
||||
|
||||
#ifndef __M_BBOX__
|
||||
#define __M_BBOX__
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "m_fixed.h"
|
||||
|
||||
// Bounding box coordinate storage.
|
||||
enum
|
||||
{
|
||||
BOXTOP,
|
||||
BOXBOTTOM,
|
||||
BOXLEFT,
|
||||
BOXRIGHT
|
||||
}; // bbox coordinates
|
||||
|
||||
// Bounding box functions.
|
||||
void M_ClearBox (fixed_t* box);
|
||||
|
||||
void
|
||||
M_AddToBox
|
||||
( fixed_t* box,
|
||||
fixed_t x,
|
||||
fixed_t y );
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,87 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Cheat sequence checking.
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "m_cheat.h"
|
||||
|
||||
//
|
||||
// CHEAT SEQUENCE PACKAGE
|
||||
//
|
||||
|
||||
//
|
||||
// Called in st_stuff module, which handles the input.
|
||||
// Returns a 1 if the cheat was successful, 0 if failed.
|
||||
//
|
||||
int
|
||||
cht_CheckCheat
|
||||
( cheatseq_t* cht,
|
||||
char key )
|
||||
{
|
||||
// if we make a short sequence on a cheat with parameters, this
|
||||
// will not work in vanilla doom. behave the same.
|
||||
|
||||
if (cht->parameter_chars > 0 && ES_strlen(cht->sequence) < cht->sequence_len)
|
||||
return false;
|
||||
|
||||
if (cht->chars_read < ES_strlen(cht->sequence))
|
||||
{
|
||||
// still reading characters from the cheat code
|
||||
// and verifying. reset back to the beginning
|
||||
// if a key is wrong
|
||||
|
||||
if (key == cht->sequence[cht->chars_read])
|
||||
++cht->chars_read;
|
||||
else
|
||||
cht->chars_read = 0;
|
||||
|
||||
cht->param_chars_read = 0;
|
||||
}
|
||||
else if (cht->param_chars_read < cht->parameter_chars)
|
||||
{
|
||||
// we have passed the end of the cheat sequence and are
|
||||
// entering parameters now
|
||||
|
||||
cht->parameter_buf[cht->param_chars_read] = key;
|
||||
|
||||
++cht->param_chars_read;
|
||||
}
|
||||
|
||||
if (cht->chars_read >= ES_strlen(cht->sequence)
|
||||
&& cht->param_chars_read >= cht->parameter_chars)
|
||||
{
|
||||
cht->chars_read = cht->param_chars_read = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// cheat not matched yet
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
cht_GetParam
|
||||
( cheatseq_t* cht,
|
||||
char* buffer )
|
||||
{
|
||||
ES_memcpy(buffer, cht->parameter_buf, cht->parameter_chars);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Cheat code checking.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __M_CHEAT__
|
||||
#define __M_CHEAT__
|
||||
|
||||
//
|
||||
// CHEAT SEQUENCE PACKAGE
|
||||
//
|
||||
|
||||
// declaring a cheat
|
||||
|
||||
#define CHEAT(value, parameters) \
|
||||
{ value, sizeof(value) - 1, parameters, 0, 0, "" }
|
||||
|
||||
#define MAX_CHEAT_LEN 25
|
||||
#define MAX_CHEAT_PARAMS 5
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// settings for this cheat
|
||||
|
||||
char sequence[MAX_CHEAT_LEN];
|
||||
size_t sequence_len;
|
||||
int parameter_chars;
|
||||
|
||||
// state used during the game
|
||||
|
||||
size_t chars_read;
|
||||
int param_chars_read;
|
||||
char parameter_buf[MAX_CHEAT_PARAMS];
|
||||
} cheatseq_t;
|
||||
|
||||
int
|
||||
cht_CheckCheat
|
||||
( cheatseq_t* cht,
|
||||
char key );
|
||||
|
||||
|
||||
void
|
||||
cht_GetParam
|
||||
( cheatseq_t* cht,
|
||||
char* buffer );
|
||||
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Configuration file interface.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __M_CONFIG__
|
||||
#define __M_CONFIG__
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
void M_LoadDefaults(void);
|
||||
void M_SaveDefaults(void);
|
||||
void M_SaveDefaultsAlternate(char *main, char *extra);
|
||||
void M_SetConfigDir(char *dir);
|
||||
void M_BindVariable(char *name, void *variable);
|
||||
boolean M_SetVariable(char *name, char *value);
|
||||
int M_GetIntVariable(char *name);
|
||||
const char *M_GetStrVariable(char *name);
|
||||
float M_GetFloatVariable(char *name);
|
||||
void M_SetConfigFilenames(char *main_config, char *extra_config);
|
||||
char *M_GetSaveGameDir(char *iwadname);
|
||||
|
||||
extern char *configdir;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,398 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 1993-2008 Raven Software
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "doomkeys.h"
|
||||
|
||||
#include "m_config.h"
|
||||
#include "m_misc.h"
|
||||
|
||||
//
|
||||
// Keyboard controls
|
||||
//
|
||||
|
||||
int key_right = KEY_RIGHTARROW;
|
||||
int key_left = KEY_LEFTARROW;
|
||||
int key_up = KEY_UPARROW;
|
||||
int key_down = KEY_DOWNARROW;
|
||||
int key_strafeleft = KEY_STRAFE_L;
|
||||
int key_straferight = KEY_STRAFE_R;
|
||||
int key_fire = KEY_FIRE;
|
||||
int key_use = KEY_USE;
|
||||
int key_strafe = KEY_RALT;
|
||||
int key_speed = KEY_RSHIFT;
|
||||
|
||||
//
|
||||
// Heretic keyboard controls
|
||||
//
|
||||
|
||||
int key_flyup = KEY_PGUP;
|
||||
int key_flydown = KEY_INS;
|
||||
int key_flycenter = KEY_HOME;
|
||||
|
||||
int key_lookup = KEY_PGDN;
|
||||
int key_lookdown = KEY_DEL;
|
||||
int key_lookcenter = KEY_END;
|
||||
|
||||
int key_invleft = '[';
|
||||
int key_invright = ']';
|
||||
int key_useartifact = KEY_ENTER;
|
||||
|
||||
//
|
||||
// Hexen key controls
|
||||
//
|
||||
|
||||
int key_jump = '/';
|
||||
|
||||
int key_arti_all = KEY_BACKSPACE;
|
||||
int key_arti_health = '\\';
|
||||
int key_arti_poisonbag = '0';
|
||||
int key_arti_blastradius = '9';
|
||||
int key_arti_teleport = '8';
|
||||
int key_arti_teleportother = '7';
|
||||
int key_arti_egg = '6';
|
||||
int key_arti_invulnerability = '5';
|
||||
|
||||
//
|
||||
// Strife key controls
|
||||
//
|
||||
// haleyjd 09/01/10
|
||||
//
|
||||
|
||||
// Note: Strife also uses key_invleft, key_invright, key_jump, key_lookup, and
|
||||
// key_lookdown, but with different default values.
|
||||
|
||||
int key_usehealth = 'h';
|
||||
int key_invquery = 'q';
|
||||
int key_mission = 'w';
|
||||
int key_invpop = 'z';
|
||||
int key_invkey = 'k';
|
||||
int key_invhome = KEY_HOME;
|
||||
int key_invend = KEY_END;
|
||||
int key_invuse = KEY_ENTER;
|
||||
int key_invdrop = KEY_BACKSPACE;
|
||||
|
||||
|
||||
//
|
||||
// Mouse controls
|
||||
//
|
||||
|
||||
int mousebfire = 0;
|
||||
int mousebstrafe = 1;
|
||||
int mousebforward = 2;
|
||||
|
||||
int mousebjump = -1;
|
||||
|
||||
int mousebstrafeleft = -1;
|
||||
int mousebstraferight = -1;
|
||||
int mousebbackward = -1;
|
||||
int mousebuse = -1;
|
||||
|
||||
int mousebprevweapon = -1;
|
||||
int mousebnextweapon = -1;
|
||||
|
||||
|
||||
int key_message_refresh = KEY_ENTER;
|
||||
int key_pause = KEY_PAUSE;
|
||||
int key_demo_quit = 'q';
|
||||
int key_spy = KEY_F12;
|
||||
|
||||
// Multiplayer chat keys:
|
||||
|
||||
int key_multi_msg = 't';
|
||||
int key_multi_msgplayer[8];
|
||||
|
||||
// Weapon selection keys:
|
||||
|
||||
int key_weapon1 = '1';
|
||||
int key_weapon2 = '2';
|
||||
int key_weapon3 = '3';
|
||||
int key_weapon4 = '4';
|
||||
int key_weapon5 = '5';
|
||||
int key_weapon6 = '6';
|
||||
int key_weapon7 = '7';
|
||||
int key_weapon8 = '8';
|
||||
int key_prevweapon = 0;
|
||||
int key_nextweapon = 0;
|
||||
|
||||
// Map control keys:
|
||||
|
||||
int key_map_north = KEY_UPARROW;
|
||||
int key_map_south = KEY_DOWNARROW;
|
||||
int key_map_east = KEY_RIGHTARROW;
|
||||
int key_map_west = KEY_LEFTARROW;
|
||||
int key_map_zoomin = '=';
|
||||
int key_map_zoomout = '-';
|
||||
int key_map_toggle = KEY_TAB;
|
||||
int key_map_maxzoom = '0';
|
||||
int key_map_follow = 'f';
|
||||
int key_map_grid = 'g';
|
||||
int key_map_mark = 'm';
|
||||
int key_map_clearmark = 'c';
|
||||
|
||||
// menu keys:
|
||||
|
||||
int key_menu_activate = KEY_ESCAPE;
|
||||
int key_menu_up = KEY_UPARROW;
|
||||
int key_menu_down = KEY_DOWNARROW;
|
||||
int key_menu_left = KEY_LEFTARROW;
|
||||
int key_menu_right = KEY_RIGHTARROW;
|
||||
int key_menu_back = KEY_BACKSPACE;
|
||||
int key_menu_forward = KEY_ENTER;
|
||||
int key_menu_confirm = 'y';
|
||||
int key_menu_abort = 'n';
|
||||
|
||||
int key_menu_help = KEY_F1;
|
||||
int key_menu_save = KEY_F2;
|
||||
int key_menu_load = KEY_F3;
|
||||
int key_menu_volume = KEY_F4;
|
||||
int key_menu_detail = KEY_F5;
|
||||
int key_menu_qsave = KEY_F6;
|
||||
int key_menu_endgame = KEY_F7;
|
||||
int key_menu_messages = KEY_F8;
|
||||
int key_menu_qload = KEY_F9;
|
||||
int key_menu_quit = KEY_F10;
|
||||
int key_menu_gamma = KEY_F11;
|
||||
|
||||
int key_menu_incscreen = KEY_EQUALS;
|
||||
int key_menu_decscreen = KEY_MINUS;
|
||||
int key_menu_screenshot = 0;
|
||||
|
||||
//
|
||||
// Joystick controls
|
||||
//
|
||||
|
||||
int joybfire = 0;
|
||||
int joybstrafe = 1;
|
||||
int joybuse = 3;
|
||||
int joybspeed = 2;
|
||||
|
||||
int joybstrafeleft = -1;
|
||||
int joybstraferight = -1;
|
||||
|
||||
int joybjump = -1;
|
||||
|
||||
int joybprevweapon = -1;
|
||||
int joybnextweapon = -1;
|
||||
|
||||
int joybmenu = -1;
|
||||
|
||||
// Control whether if a mouse button is double clicked, it acts like
|
||||
// "use" has been pressed
|
||||
|
||||
int dclick_use = 1;
|
||||
|
||||
//
|
||||
// Bind all of the common controls used by Doom and all other games.
|
||||
//
|
||||
|
||||
void M_BindBaseControls(void)
|
||||
{
|
||||
M_BindVariable("key_right", &key_right);
|
||||
M_BindVariable("key_left", &key_left);
|
||||
M_BindVariable("key_up", &key_up);
|
||||
M_BindVariable("key_down", &key_down);
|
||||
M_BindVariable("key_strafeleft", &key_strafeleft);
|
||||
M_BindVariable("key_straferight", &key_straferight);
|
||||
M_BindVariable("key_fire", &key_fire);
|
||||
M_BindVariable("key_use", &key_use);
|
||||
M_BindVariable("key_strafe", &key_strafe);
|
||||
M_BindVariable("key_speed", &key_speed);
|
||||
|
||||
M_BindVariable("mouseb_fire", &mousebfire);
|
||||
M_BindVariable("mouseb_strafe", &mousebstrafe);
|
||||
M_BindVariable("mouseb_forward", &mousebforward);
|
||||
|
||||
M_BindVariable("joyb_fire", &joybfire);
|
||||
M_BindVariable("joyb_strafe", &joybstrafe);
|
||||
M_BindVariable("joyb_use", &joybuse);
|
||||
M_BindVariable("joyb_speed", &joybspeed);
|
||||
|
||||
M_BindVariable("joyb_menu_activate", &joybmenu);
|
||||
|
||||
// Extra controls that are not in the Vanilla versions:
|
||||
|
||||
M_BindVariable("joyb_strafeleft", &joybstrafeleft);
|
||||
M_BindVariable("joyb_straferight", &joybstraferight);
|
||||
M_BindVariable("mouseb_strafeleft", &mousebstrafeleft);
|
||||
M_BindVariable("mouseb_straferight", &mousebstraferight);
|
||||
M_BindVariable("mouseb_use", &mousebuse);
|
||||
M_BindVariable("mouseb_backward", &mousebbackward);
|
||||
M_BindVariable("dclick_use", &dclick_use);
|
||||
M_BindVariable("key_pause", &key_pause);
|
||||
M_BindVariable("key_message_refresh", &key_message_refresh);
|
||||
}
|
||||
|
||||
void M_BindHereticControls(void)
|
||||
{
|
||||
M_BindVariable("key_flyup", &key_flyup);
|
||||
M_BindVariable("key_flydown", &key_flydown);
|
||||
M_BindVariable("key_flycenter", &key_flycenter);
|
||||
|
||||
M_BindVariable("key_lookup", &key_lookup);
|
||||
M_BindVariable("key_lookdown", &key_lookdown);
|
||||
M_BindVariable("key_lookcenter", &key_lookcenter);
|
||||
|
||||
M_BindVariable("key_invleft", &key_invleft);
|
||||
M_BindVariable("key_invright", &key_invright);
|
||||
M_BindVariable("key_useartifact", &key_useartifact);
|
||||
}
|
||||
|
||||
void M_BindHexenControls(void)
|
||||
{
|
||||
M_BindVariable("key_jump", &key_jump);
|
||||
M_BindVariable("mouseb_jump", &mousebjump);
|
||||
M_BindVariable("joyb_jump", &joybjump);
|
||||
|
||||
M_BindVariable("key_arti_all", &key_arti_all);
|
||||
M_BindVariable("key_arti_health", &key_arti_health);
|
||||
M_BindVariable("key_arti_poisonbag", &key_arti_poisonbag);
|
||||
M_BindVariable("key_arti_blastradius", &key_arti_blastradius);
|
||||
M_BindVariable("key_arti_teleport", &key_arti_teleport);
|
||||
M_BindVariable("key_arti_teleportother", &key_arti_teleportother);
|
||||
M_BindVariable("key_arti_egg", &key_arti_egg);
|
||||
M_BindVariable("key_arti_invulnerability", &key_arti_invulnerability);
|
||||
}
|
||||
|
||||
void M_BindStrifeControls(void)
|
||||
{
|
||||
// These are shared with all games, but have different defaults:
|
||||
key_message_refresh = '/';
|
||||
|
||||
// These keys are shared with Heretic/Hexen but have different defaults:
|
||||
key_jump = 'a';
|
||||
key_lookup = KEY_PGUP;
|
||||
key_lookdown = KEY_PGDN;
|
||||
key_invleft = KEY_INS;
|
||||
key_invright = KEY_DEL;
|
||||
|
||||
M_BindVariable("key_jump", &key_jump);
|
||||
M_BindVariable("key_lookUp", &key_lookup);
|
||||
M_BindVariable("key_lookDown", &key_lookdown);
|
||||
M_BindVariable("key_invLeft", &key_invleft);
|
||||
M_BindVariable("key_invRight", &key_invright);
|
||||
|
||||
// Custom Strife-only Keys:
|
||||
M_BindVariable("key_useHealth", &key_usehealth);
|
||||
M_BindVariable("key_invquery", &key_invquery);
|
||||
M_BindVariable("key_mission", &key_mission);
|
||||
M_BindVariable("key_invPop", &key_invpop);
|
||||
M_BindVariable("key_invKey", &key_invkey);
|
||||
M_BindVariable("key_invHome", &key_invhome);
|
||||
M_BindVariable("key_invEnd", &key_invend);
|
||||
M_BindVariable("key_invUse", &key_invuse);
|
||||
M_BindVariable("key_invDrop", &key_invdrop);
|
||||
|
||||
// Strife also supports jump on mouse and joystick, and in the exact same
|
||||
// manner as Hexen!
|
||||
M_BindVariable("mouseb_jump", &mousebjump);
|
||||
M_BindVariable("joyb_jump", &joybjump);
|
||||
}
|
||||
|
||||
void M_BindWeaponControls(void)
|
||||
{
|
||||
M_BindVariable("key_weapon1", &key_weapon1);
|
||||
M_BindVariable("key_weapon2", &key_weapon2);
|
||||
M_BindVariable("key_weapon3", &key_weapon3);
|
||||
M_BindVariable("key_weapon4", &key_weapon4);
|
||||
M_BindVariable("key_weapon5", &key_weapon5);
|
||||
M_BindVariable("key_weapon6", &key_weapon6);
|
||||
M_BindVariable("key_weapon7", &key_weapon7);
|
||||
M_BindVariable("key_weapon8", &key_weapon8);
|
||||
|
||||
M_BindVariable("key_prevweapon", &key_prevweapon);
|
||||
M_BindVariable("key_nextweapon", &key_nextweapon);
|
||||
|
||||
M_BindVariable("joyb_prevweapon", &joybprevweapon);
|
||||
M_BindVariable("joyb_nextweapon", &joybnextweapon);
|
||||
|
||||
M_BindVariable("mouseb_prevweapon", &mousebprevweapon);
|
||||
M_BindVariable("mouseb_nextweapon", &mousebnextweapon);
|
||||
}
|
||||
|
||||
void M_BindMapControls(void)
|
||||
{
|
||||
M_BindVariable("key_map_north", &key_map_north);
|
||||
M_BindVariable("key_map_south", &key_map_south);
|
||||
M_BindVariable("key_map_east", &key_map_east);
|
||||
M_BindVariable("key_map_west", &key_map_west);
|
||||
M_BindVariable("key_map_zoomin", &key_map_zoomin);
|
||||
M_BindVariable("key_map_zoomout", &key_map_zoomout);
|
||||
M_BindVariable("key_map_toggle", &key_map_toggle);
|
||||
M_BindVariable("key_map_maxzoom", &key_map_maxzoom);
|
||||
M_BindVariable("key_map_follow", &key_map_follow);
|
||||
M_BindVariable("key_map_grid", &key_map_grid);
|
||||
M_BindVariable("key_map_mark", &key_map_mark);
|
||||
M_BindVariable("key_map_clearmark", &key_map_clearmark);
|
||||
}
|
||||
|
||||
void M_BindMenuControls(void)
|
||||
{
|
||||
M_BindVariable("key_menu_activate", &key_menu_activate);
|
||||
M_BindVariable("key_menu_up", &key_menu_up);
|
||||
M_BindVariable("key_menu_down", &key_menu_down);
|
||||
M_BindVariable("key_menu_left", &key_menu_left);
|
||||
M_BindVariable("key_menu_right", &key_menu_right);
|
||||
M_BindVariable("key_menu_back", &key_menu_back);
|
||||
M_BindVariable("key_menu_forward", &key_menu_forward);
|
||||
M_BindVariable("key_menu_confirm", &key_menu_confirm);
|
||||
M_BindVariable("key_menu_abort", &key_menu_abort);
|
||||
|
||||
M_BindVariable("key_menu_help", &key_menu_help);
|
||||
M_BindVariable("key_menu_save", &key_menu_save);
|
||||
M_BindVariable("key_menu_load", &key_menu_load);
|
||||
M_BindVariable("key_menu_volume", &key_menu_volume);
|
||||
M_BindVariable("key_menu_detail", &key_menu_detail);
|
||||
M_BindVariable("key_menu_qsave", &key_menu_qsave);
|
||||
M_BindVariable("key_menu_endgame", &key_menu_endgame);
|
||||
M_BindVariable("key_menu_messages", &key_menu_messages);
|
||||
M_BindVariable("key_menu_qload", &key_menu_qload);
|
||||
M_BindVariable("key_menu_quit", &key_menu_quit);
|
||||
M_BindVariable("key_menu_gamma", &key_menu_gamma);
|
||||
|
||||
M_BindVariable("key_menu_incscreen", &key_menu_incscreen);
|
||||
M_BindVariable("key_menu_decscreen", &key_menu_decscreen);
|
||||
M_BindVariable("key_menu_screenshot",&key_menu_screenshot);
|
||||
M_BindVariable("key_demo_quit", &key_demo_quit);
|
||||
M_BindVariable("key_spy", &key_spy);
|
||||
}
|
||||
|
||||
void M_BindChatControls(unsigned int num_players)
|
||||
{
|
||||
char name[32]; // haleyjd: 20 not large enough - Thank you, come again!
|
||||
unsigned int i; // haleyjd: signedness conflict
|
||||
|
||||
M_BindVariable("key_multi_msg", &key_multi_msg);
|
||||
|
||||
for (i=0; i<num_players; ++i)
|
||||
{
|
||||
M_snprintf(name, sizeof(name), "key_multi_msgplayer%i", i + 1);
|
||||
M_BindVariable(name, &key_multi_msgplayer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Apply custom patches to the default values depending on the
|
||||
// platform we are running on.
|
||||
//
|
||||
|
||||
void M_ApplyPlatformDefaults(void)
|
||||
{
|
||||
// no-op. Add your platform-specific patches here.
|
||||
}
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 1993-2008 Raven Software
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef __M_CONTROLS_H__
|
||||
#define __M_CONTROLS_H__
|
||||
|
||||
extern int key_right;
|
||||
extern int key_left;
|
||||
|
||||
extern int key_up;
|
||||
extern int key_down;
|
||||
extern int key_strafeleft;
|
||||
extern int key_straferight;
|
||||
extern int key_fire;
|
||||
extern int key_use;
|
||||
extern int key_strafe;
|
||||
extern int key_speed;
|
||||
|
||||
extern int key_jump;
|
||||
|
||||
extern int key_flyup;
|
||||
extern int key_flydown;
|
||||
extern int key_flycenter;
|
||||
extern int key_lookup;
|
||||
extern int key_lookdown;
|
||||
extern int key_lookcenter;
|
||||
extern int key_invleft;
|
||||
extern int key_invright;
|
||||
extern int key_useartifact;
|
||||
|
||||
// villsa [STRIFE] strife keys
|
||||
extern int key_usehealth;
|
||||
extern int key_invquery;
|
||||
extern int key_mission;
|
||||
extern int key_invpop;
|
||||
extern int key_invkey;
|
||||
extern int key_invhome;
|
||||
extern int key_invend;
|
||||
extern int key_invuse;
|
||||
extern int key_invdrop;
|
||||
|
||||
extern int key_message_refresh;
|
||||
extern int key_pause;
|
||||
|
||||
extern int key_multi_msg;
|
||||
extern int key_multi_msgplayer[8];
|
||||
|
||||
extern int key_weapon1;
|
||||
extern int key_weapon2;
|
||||
extern int key_weapon3;
|
||||
extern int key_weapon4;
|
||||
extern int key_weapon5;
|
||||
extern int key_weapon6;
|
||||
extern int key_weapon7;
|
||||
extern int key_weapon8;
|
||||
|
||||
extern int key_arti_all;
|
||||
extern int key_arti_health;
|
||||
extern int key_arti_poisonbag;
|
||||
extern int key_arti_blastradius;
|
||||
extern int key_arti_teleport;
|
||||
extern int key_arti_teleportother;
|
||||
extern int key_arti_egg;
|
||||
extern int key_arti_invulnerability;
|
||||
|
||||
extern int key_demo_quit;
|
||||
extern int key_spy;
|
||||
extern int key_prevweapon;
|
||||
extern int key_nextweapon;
|
||||
|
||||
extern int key_map_north;
|
||||
extern int key_map_south;
|
||||
extern int key_map_east;
|
||||
extern int key_map_west;
|
||||
extern int key_map_zoomin;
|
||||
extern int key_map_zoomout;
|
||||
extern int key_map_toggle;
|
||||
extern int key_map_maxzoom;
|
||||
extern int key_map_follow;
|
||||
extern int key_map_grid;
|
||||
extern int key_map_mark;
|
||||
extern int key_map_clearmark;
|
||||
|
||||
// menu keys:
|
||||
|
||||
extern int key_menu_activate;
|
||||
extern int key_menu_up;
|
||||
extern int key_menu_down;
|
||||
extern int key_menu_left;
|
||||
extern int key_menu_right;
|
||||
extern int key_menu_back;
|
||||
extern int key_menu_forward;
|
||||
extern int key_menu_confirm;
|
||||
extern int key_menu_abort;
|
||||
|
||||
extern int key_menu_help;
|
||||
extern int key_menu_save;
|
||||
extern int key_menu_load;
|
||||
extern int key_menu_volume;
|
||||
extern int key_menu_detail;
|
||||
extern int key_menu_qsave;
|
||||
extern int key_menu_endgame;
|
||||
extern int key_menu_messages;
|
||||
extern int key_menu_qload;
|
||||
extern int key_menu_quit;
|
||||
extern int key_menu_gamma;
|
||||
|
||||
extern int key_menu_incscreen;
|
||||
extern int key_menu_decscreen;
|
||||
extern int key_menu_screenshot;
|
||||
|
||||
extern int mousebfire;
|
||||
extern int mousebstrafe;
|
||||
extern int mousebforward;
|
||||
|
||||
extern int mousebjump;
|
||||
|
||||
extern int mousebstrafeleft;
|
||||
extern int mousebstraferight;
|
||||
extern int mousebbackward;
|
||||
extern int mousebuse;
|
||||
|
||||
extern int mousebprevweapon;
|
||||
extern int mousebnextweapon;
|
||||
|
||||
extern int joybfire;
|
||||
extern int joybstrafe;
|
||||
extern int joybuse;
|
||||
extern int joybspeed;
|
||||
|
||||
extern int joybjump;
|
||||
|
||||
extern int joybstrafeleft;
|
||||
extern int joybstraferight;
|
||||
|
||||
extern int joybprevweapon;
|
||||
extern int joybnextweapon;
|
||||
|
||||
extern int joybmenu;
|
||||
|
||||
extern int dclick_use;
|
||||
|
||||
void M_BindBaseControls(void);
|
||||
void M_BindHereticControls(void);
|
||||
void M_BindHexenControls(void);
|
||||
void M_BindStrifeControls(void);
|
||||
void M_BindWeaponControls(void);
|
||||
void M_BindMapControls(void);
|
||||
void M_BindMenuControls(void);
|
||||
void M_BindChatControls(unsigned int num_players);
|
||||
|
||||
void M_ApplyPlatformDefaults(void);
|
||||
|
||||
#endif /* #ifndef __M_CONTROLS_H__ */
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Fixed point implementation.
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "i_system.h"
|
||||
|
||||
#include "m_fixed.h"
|
||||
|
||||
// Fixme. __USE_C_FIXED__ or something.
|
||||
|
||||
fixed_t
|
||||
FixedMul
|
||||
( fixed_t a,
|
||||
fixed_t b )
|
||||
{
|
||||
return ((int64_t) a * (int64_t) b) >> FRACBITS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// FixedDiv, C version.
|
||||
//
|
||||
|
||||
fixed_t FixedDiv(fixed_t a, fixed_t b)
|
||||
{
|
||||
if ((ES_abs(a) >> 14) >= ES_abs(b))
|
||||
{
|
||||
return (a^b) < 0 ? INT_MIN : INT_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t result;
|
||||
|
||||
result = ((int64_t) a << 16) / b;
|
||||
|
||||
return (fixed_t) result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Fixed point arithemtics, implementation.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __M_FIXED__
|
||||
#define __M_FIXED__
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Fixed point, 32bit as 16.16.
|
||||
//
|
||||
#define FRACBITS 16
|
||||
#define FRACUNIT (1<<FRACBITS)
|
||||
|
||||
typedef int fixed_t;
|
||||
|
||||
fixed_t FixedMul (fixed_t a, fixed_t b);
|
||||
fixed_t FixedDiv (fixed_t a, fixed_t b);
|
||||
|
||||
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Menu widget stuff, episode selection and such.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __M_MENU__
|
||||
#define __M_MENU__
|
||||
|
||||
|
||||
|
||||
#include "d_event.h"
|
||||
|
||||
//
|
||||
// MENUS
|
||||
//
|
||||
// Called by main loop,
|
||||
// saves config file and calls I_Quit when user exits.
|
||||
// Even when the menu is not displayed,
|
||||
// this can resize the view and change game parameters.
|
||||
// Does all the real work of the menu interaction.
|
||||
boolean M_Responder (event_t *ev);
|
||||
|
||||
|
||||
// Called by main loop,
|
||||
// only used for menu (skull cursor) animation.
|
||||
void M_Ticker (void);
|
||||
|
||||
// Called by main loop,
|
||||
// draws the menus directly into the screen buffer.
|
||||
void M_Drawer (void);
|
||||
|
||||
// Called by D_DoomMain,
|
||||
// loads the config file.
|
||||
void M_Init (void);
|
||||
|
||||
// Called by intro code to force menu up upon a keypress,
|
||||
// does nothing if menu is already up.
|
||||
void M_StartControlPanel (void);
|
||||
|
||||
|
||||
|
||||
extern int detailLevel;
|
||||
extern int screenblocks;
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,470 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 1993-2008 Raven Software
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Miscellaneous.
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
#include "i_swap.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
#include "m_misc.h"
|
||||
#include "v_video.h"
|
||||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
//
|
||||
// Create a directory
|
||||
//
|
||||
|
||||
void M_MakeDirectory(char *path)
|
||||
{
|
||||
ES_mkdir(path);
|
||||
}
|
||||
|
||||
// Check if a file exists
|
||||
|
||||
boolean M_FileExists(char *filename)
|
||||
{
|
||||
ES_File *fstream;
|
||||
|
||||
fstream = ES_fopen(filename, ES_READ_MODE);
|
||||
if (fstream != NULL)
|
||||
{
|
||||
ES_fclose(fstream);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Determine the length of an open file.
|
||||
//
|
||||
|
||||
long M_FileLength(ES_File *handle)
|
||||
{
|
||||
long savedpos;
|
||||
long length;
|
||||
|
||||
// save the current position in the file
|
||||
savedpos = ES_ftell(handle);
|
||||
|
||||
// jump to the end and find the length
|
||||
ES_fseek(handle, 0, ES_SEEK_END);
|
||||
length = ES_ftell(handle);
|
||||
|
||||
// go back to the old location
|
||||
ES_fseek(handle, savedpos, ES_SEEK_SET);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
//
|
||||
// M_WriteFile
|
||||
//
|
||||
|
||||
boolean M_WriteFile(char *name, void *source, int length)
|
||||
{
|
||||
ES_File *handle;
|
||||
int count;
|
||||
|
||||
handle = ES_fopen(name, ES_WRITE_MODE | ES_BYTE_MODE);
|
||||
if (handle == NULL) return false;
|
||||
|
||||
count = ES_fwrite(source, length, 1, handle);
|
||||
ES_fclose(handle);
|
||||
|
||||
if (count < length)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// M_ReadFile
|
||||
//
|
||||
|
||||
int M_ReadFile(char *name, byte **buffer)
|
||||
{
|
||||
ES_File *handle;
|
||||
int count, length;
|
||||
byte *buf;
|
||||
|
||||
handle = ES_fopen(name, ES_READ_MODE | ES_BYTE_MODE);
|
||||
if (handle == NULL) I_Error ("Couldn't read file %s", name);
|
||||
|
||||
// find the size of the file by seeking to the end and
|
||||
// reading the current position
|
||||
|
||||
length = M_FileLength(handle);
|
||||
|
||||
buf = Z_Malloc (length, PU_STATIC, NULL);
|
||||
count = ES_fread(buf, length, 1, handle);
|
||||
ES_fclose (handle);
|
||||
|
||||
if (count < length)
|
||||
I_Error ("Couldn't read file %s", name);
|
||||
|
||||
*buffer = buf;
|
||||
return length;
|
||||
}
|
||||
|
||||
// Returns the path to a temporary file of the given name, stored
|
||||
// inside the system temporary directory.
|
||||
//
|
||||
// The returned value must be freed with Z_Free after use.
|
||||
|
||||
char *M_TempFile(char *s)
|
||||
{
|
||||
return M_StringJoin(TMP_DIR, DIR_SEPARATOR_S, s, NULL);
|
||||
}
|
||||
|
||||
boolean M_StrToInt(const char *str, int *result)
|
||||
{
|
||||
char *next = 0;
|
||||
|
||||
if (str[1] == '0' && (str[2] == 'x' || str[2] == 'X')) {
|
||||
*result = (int)ES_strtol(str+3, &next, 16);
|
||||
} else if (str[1] == '0') {
|
||||
*result = (int)ES_strtol(str+3, &next, 8);
|
||||
} else {
|
||||
*result = (int)ES_strtol(str+3, &next, 10);
|
||||
}
|
||||
|
||||
return next != 0 && next != str;
|
||||
}
|
||||
|
||||
void M_ExtractFileBase(char *path, char *dest)
|
||||
{
|
||||
char *src;
|
||||
char *filename;
|
||||
int length;
|
||||
|
||||
src = path + ES_strlen(path) - 1;
|
||||
|
||||
// back up until a \ or the start
|
||||
while (src != path && *(src - 1) != DIR_SEPARATOR)
|
||||
{
|
||||
src--;
|
||||
}
|
||||
|
||||
filename = src;
|
||||
|
||||
// Copy up to eight characters
|
||||
// Note: Vanilla Doom exits with an error if a filename is specified
|
||||
// with a base of more than eight characters. To remove the 8.3
|
||||
// filename limit, instead we simply truncate the name.
|
||||
|
||||
length = 0;
|
||||
ES_memset(dest, 0, 8);
|
||||
|
||||
while (*src != '\0' && *src != '.')
|
||||
{
|
||||
if (length >= 8)
|
||||
{
|
||||
ES_warnf("Truncated '%s' lump name to '%.8s'.\n",
|
||||
filename, dest);
|
||||
break;
|
||||
}
|
||||
|
||||
dest[length++] = ES_toupper((int)*src++);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC M_ForceUppercase
|
||||
//
|
||||
// Change string to uppercase.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void M_ForceUppercase(char *text)
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = text; *p != '\0'; ++p)
|
||||
{
|
||||
*p = ES_toupper(*p);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// M_StrCaseStr
|
||||
//
|
||||
// Case-insensitive version of strstr()
|
||||
//
|
||||
|
||||
char *M_StrCaseStr(char *haystack, char *needle)
|
||||
{
|
||||
unsigned int haystack_len;
|
||||
unsigned int needle_len;
|
||||
unsigned int len;
|
||||
unsigned int i;
|
||||
|
||||
haystack_len = ES_strlen(haystack);
|
||||
needle_len = ES_strlen(needle);
|
||||
|
||||
if (haystack_len < needle_len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = haystack_len - needle_len;
|
||||
|
||||
for (i = 0; i <= len; ++i)
|
||||
{
|
||||
if (!ES_strncasecmp(haystack + i, needle, needle_len))
|
||||
{
|
||||
return haystack + i;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Safe version of strdup() that checks the string was successfully
|
||||
// allocated.
|
||||
//
|
||||
|
||||
char *M_StringDuplicate(const char *orig)
|
||||
{
|
||||
char *result;
|
||||
|
||||
result = ES_strdup(orig);
|
||||
|
||||
if (result == NULL)
|
||||
{
|
||||
I_Error("Failed to duplicate string (length %i)\n",
|
||||
ES_strlen(orig));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// String replace function.
|
||||
//
|
||||
|
||||
char *M_StringReplace(const char *haystack, const char *needle,
|
||||
const char *replacement)
|
||||
{
|
||||
char *result, *dst;
|
||||
const char *p;
|
||||
size_t needle_len = ES_strlen(needle);
|
||||
size_t result_len, dst_len;
|
||||
|
||||
// Iterate through occurrences of 'needle' and calculate the size of
|
||||
// the new string.
|
||||
result_len = ES_strlen(haystack) + 1;
|
||||
p = haystack;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
p = ES_strstr(p, needle);
|
||||
if (p == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
p += needle_len;
|
||||
result_len += ES_strlen(replacement) - needle_len;
|
||||
}
|
||||
|
||||
// Construct new string.
|
||||
|
||||
result = ES_malloc(result_len);
|
||||
if (result == NULL)
|
||||
{
|
||||
I_Error("M_StringReplace: Failed to allocate new string");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dst = result; dst_len = result_len;
|
||||
p = haystack;
|
||||
|
||||
while (*p != '\0')
|
||||
{
|
||||
if (!ES_strncmp(p, needle, needle_len))
|
||||
{
|
||||
M_StringCopy(dst, replacement, dst_len);
|
||||
p += needle_len;
|
||||
dst += ES_strlen(replacement);
|
||||
dst_len -= ES_strlen(replacement);
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst = *p;
|
||||
++dst; --dst_len;
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
*dst = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Safe string copy function that works like OpenBSD's strlcpy().
|
||||
// Returns true if the string was not truncated.
|
||||
|
||||
boolean M_StringCopy(char *dest, const char *src, size_t dest_size)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (dest_size >= 1)
|
||||
{
|
||||
dest[dest_size - 1] = '\0';
|
||||
ES_strncpy(dest, src, dest_size - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
len = ES_strlen(dest);
|
||||
return src[len] == '\0';
|
||||
}
|
||||
|
||||
// Safe string concat function that works like OpenBSD's strlcat().
|
||||
// Returns true if string not truncated.
|
||||
|
||||
boolean M_StringConcat(char *dest, const char *src, size_t dest_size)
|
||||
{
|
||||
size_t offset;
|
||||
|
||||
offset = ES_strlen(dest);
|
||||
if (offset > dest_size)
|
||||
{
|
||||
offset = dest_size;
|
||||
}
|
||||
|
||||
return M_StringCopy(dest + offset, src, dest_size - offset);
|
||||
}
|
||||
|
||||
// Returns true if 's' begins with the specified prefix.
|
||||
|
||||
boolean M_StringStartsWith(const char *s, const char *prefix)
|
||||
{
|
||||
return ES_strlen(s) > ES_strlen(prefix)
|
||||
&& ES_strncmp(s, prefix, ES_strlen(prefix)) == 0;
|
||||
}
|
||||
|
||||
// Returns true if 's' ends with the specified suffix.
|
||||
|
||||
boolean M_StringEndsWith(const char *s, const char *suffix)
|
||||
{
|
||||
return ES_strlen(s) >= ES_strlen(suffix)
|
||||
&& ES_strcmp(s + ES_strlen(s) - ES_strlen(suffix), suffix) == 0;
|
||||
}
|
||||
|
||||
// Return a newly-malloced string with all the strings given as arguments
|
||||
// concatenated together.
|
||||
|
||||
char *M_StringJoin(const char *s, ...)
|
||||
{
|
||||
char *result;
|
||||
const char *v;
|
||||
va_list args;
|
||||
size_t result_len;
|
||||
|
||||
result_len = ES_strlen(s) + 1;
|
||||
|
||||
va_start(args, s);
|
||||
for (;;)
|
||||
{
|
||||
v = va_arg(args, const char *);
|
||||
if (v == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
result_len += ES_strlen(v);
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
result = ES_malloc(result_len);
|
||||
|
||||
if (result == NULL)
|
||||
{
|
||||
I_Error("M_StringJoin: Failed to allocate new string.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
M_StringCopy(result, s, result_len);
|
||||
|
||||
va_start(args, s);
|
||||
for (;;)
|
||||
{
|
||||
v = va_arg(args, const char *);
|
||||
if (v == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
M_StringConcat(result, v, result_len);
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Safe, portable vsnprintf().
|
||||
int M_vsnprintf(char *buf, size_t buf_len, const char *s, va_list args)
|
||||
{
|
||||
size_t result;
|
||||
|
||||
if (buf_len < 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Windows (and other OSes?) has a vsnprintf() that doesn't always
|
||||
// append a trailing \0. So we must do it, and write into a buffer
|
||||
// that is one byte shorter; otherwise this function is unsafe.
|
||||
result = ES_vsnprintf(buf, buf_len, s, args);
|
||||
|
||||
// If truncated, change the final char in the buffer to a \0.
|
||||
// A negative result indicates a truncated buffer on Windows.
|
||||
if (result < 0 || result >= buf_len)
|
||||
{
|
||||
buf[buf_len - 1] = '\0';
|
||||
result = buf_len - 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Safe, portable snprintf().
|
||||
int M_snprintf(char *buf, size_t buf_len, const char *s, ...)
|
||||
{
|
||||
va_list args;
|
||||
int result;
|
||||
va_start(args, s);
|
||||
result = M_vsnprintf(buf, buf_len, s, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Miscellaneous.
|
||||
//
|
||||
|
||||
|
||||
#ifndef __M_MISC__
|
||||
#define __M_MISC__
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
boolean M_WriteFile(char *name, void *source, int length);
|
||||
int M_ReadFile(char *name, byte **buffer);
|
||||
void M_MakeDirectory(char *dir);
|
||||
char *M_TempFile(char *s);
|
||||
boolean M_FileExists(char *file);
|
||||
long M_FileLength(ES_File *handle);
|
||||
boolean M_StrToInt(const char *str, int *result);
|
||||
void M_ExtractFileBase(char *path, char *dest);
|
||||
void M_ForceUppercase(char *text);
|
||||
char *M_StrCaseStr(char *haystack, char *needle);
|
||||
char *M_StringDuplicate(const char *orig);
|
||||
boolean M_StringCopy(char *dest, const char *src, size_t dest_size);
|
||||
boolean M_StringConcat(char *dest, const char *src, size_t dest_size);
|
||||
char *M_StringReplace(const char *haystack, const char *needle,
|
||||
const char *replacement);
|
||||
char *M_StringJoin(const char *s, ...);
|
||||
boolean M_StringStartsWith(const char *s, const char *prefix);
|
||||
boolean M_StringEndsWith(const char *s, const char *suffix);
|
||||
int M_vsnprintf(char *buf, size_t buf_len, const char *s, va_list args);
|
||||
int M_snprintf(char *buf, size_t buf_len, const char *s, ...);
|
||||
char *M_OEMToUTF8(const char *ansi);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Random number LUT.
|
||||
//
|
||||
|
||||
//
|
||||
// M_Random
|
||||
// Returns a 0-255 number
|
||||
//
|
||||
|
||||
static const unsigned char rndtable[256] = {
|
||||
0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66 ,
|
||||
74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36 ,
|
||||
95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188 ,
|
||||
52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224 ,
|
||||
149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242 ,
|
||||
145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0 ,
|
||||
175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235 ,
|
||||
25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113 ,
|
||||
94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75 ,
|
||||
136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196 ,
|
||||
135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113 ,
|
||||
80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241 ,
|
||||
24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224 ,
|
||||
145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95 ,
|
||||
28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226 ,
|
||||
71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36 ,
|
||||
17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106 ,
|
||||
197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136 ,
|
||||
120, 163, 236, 249
|
||||
};
|
||||
|
||||
int rndindex = 0;
|
||||
int prndindex = 0;
|
||||
|
||||
// Which one is deterministic?
|
||||
int P_Random (void)
|
||||
{
|
||||
prndindex = (prndindex+1)&0xff;
|
||||
return rndtable[prndindex];
|
||||
}
|
||||
|
||||
int M_Random (void)
|
||||
{
|
||||
rndindex = (rndindex+1)&0xff;
|
||||
return rndtable[rndindex];
|
||||
}
|
||||
|
||||
void M_ClearRandom (void)
|
||||
{
|
||||
rndindex = prndindex = 0;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
#ifndef __M_RANDOM__
|
||||
#define __M_RANDOM__
|
||||
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
|
||||
|
||||
// Returns a number from 0 to 255,
|
||||
// from a lookup table.
|
||||
int M_Random (void);
|
||||
|
||||
// As M_Random, but used only by the play simulation.
|
||||
int P_Random (void);
|
||||
|
||||
// Fix randoms for demos.
|
||||
void M_ClearRandom (void);
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,195 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// Emulates the IO functions in C stdio.h reading and writing to
|
||||
// memory.
|
||||
//
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "memio.h"
|
||||
|
||||
#include "z_zone.h"
|
||||
|
||||
typedef enum {
|
||||
MODE_READ,
|
||||
MODE_WRITE,
|
||||
} memfile_mode_t;
|
||||
|
||||
struct _MEMFILE {
|
||||
unsigned char *buf;
|
||||
size_t buflen;
|
||||
size_t alloced;
|
||||
unsigned int position;
|
||||
memfile_mode_t mode;
|
||||
};
|
||||
|
||||
// Open a memory area for reading
|
||||
|
||||
MEMFILE *mem_fopen_read(void *buf, size_t buflen)
|
||||
{
|
||||
MEMFILE *file;
|
||||
|
||||
file = Z_Malloc(sizeof(MEMFILE), PU_STATIC, 0);
|
||||
|
||||
file->buf = (unsigned char *) buf;
|
||||
file->buflen = buflen;
|
||||
file->position = 0;
|
||||
file->mode = MODE_READ;
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
// Read bytes
|
||||
|
||||
size_t mem_fread(void *buf, size_t size, size_t nmemb, MEMFILE *stream)
|
||||
{
|
||||
size_t items;
|
||||
|
||||
if (stream->mode != MODE_READ)
|
||||
{
|
||||
ES_debugf("not a read stream\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Trying to read more bytes than we have left?
|
||||
|
||||
items = nmemb;
|
||||
|
||||
if (items * size > stream->buflen - stream->position)
|
||||
{
|
||||
items = (stream->buflen - stream->position) / size;
|
||||
}
|
||||
|
||||
// Copy bytes to buffer
|
||||
|
||||
ES_memcpy(buf, stream->buf + stream->position, items * size);
|
||||
|
||||
// Update position
|
||||
|
||||
stream->position += items * size;
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
// Open a memory area for writing
|
||||
|
||||
MEMFILE *mem_fopen_write(void)
|
||||
{
|
||||
MEMFILE *file;
|
||||
|
||||
file = Z_Malloc(sizeof(MEMFILE), PU_STATIC, 0);
|
||||
|
||||
file->alloced = 1024;
|
||||
file->buf = Z_Malloc(file->alloced, PU_STATIC, 0);
|
||||
file->buflen = 0;
|
||||
file->position = 0;
|
||||
file->mode = MODE_WRITE;
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
// Write bytes to stream
|
||||
|
||||
size_t mem_fwrite(const void *ptr, size_t size, size_t nmemb, MEMFILE *stream)
|
||||
{
|
||||
size_t bytes;
|
||||
|
||||
if (stream->mode != MODE_WRITE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// More bytes than can fit in the buffer?
|
||||
// If so, reallocate bigger.
|
||||
|
||||
bytes = size * nmemb;
|
||||
|
||||
while (bytes > stream->alloced - stream->position)
|
||||
{
|
||||
unsigned char *newbuf;
|
||||
|
||||
newbuf = Z_Malloc(stream->alloced * 2, PU_STATIC, 0);
|
||||
ES_memcpy(newbuf, stream->buf, stream->alloced);
|
||||
Z_Free(stream->buf);
|
||||
stream->buf = newbuf;
|
||||
stream->alloced *= 2;
|
||||
}
|
||||
|
||||
// Copy into buffer
|
||||
|
||||
ES_memcpy(stream->buf + stream->position, ptr, bytes);
|
||||
stream->position += bytes;
|
||||
|
||||
if (stream->position > stream->buflen)
|
||||
stream->buflen = stream->position;
|
||||
|
||||
return nmemb;
|
||||
}
|
||||
|
||||
void mem_get_buf(MEMFILE *stream, void **buf, size_t *buflen)
|
||||
{
|
||||
*buf = stream->buf;
|
||||
*buflen = stream->buflen;
|
||||
}
|
||||
|
||||
void mem_fclose(MEMFILE *stream)
|
||||
{
|
||||
if (stream->mode == MODE_WRITE)
|
||||
{
|
||||
Z_Free(stream->buf);
|
||||
}
|
||||
|
||||
Z_Free(stream);
|
||||
}
|
||||
|
||||
long mem_ftell(MEMFILE *stream)
|
||||
{
|
||||
return stream->position;
|
||||
}
|
||||
|
||||
int mem_fseek(MEMFILE *stream, signed long position, mem_rel_t whence)
|
||||
{
|
||||
unsigned int newpos;
|
||||
|
||||
switch (whence)
|
||||
{
|
||||
case MEM_SEEK_SET:
|
||||
newpos = (int) position;
|
||||
break;
|
||||
|
||||
case MEM_SEEK_CUR:
|
||||
newpos = (int) (stream->position + position);
|
||||
break;
|
||||
|
||||
case MEM_SEEK_END:
|
||||
newpos = (int) (stream->buflen + position);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (newpos < stream->buflen)
|
||||
{
|
||||
stream->position = newpos;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ES_debugf("Error seeking to %i\n", newpos);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#ifndef MEMIO_H
|
||||
#define MEMIO_H
|
||||
|
||||
typedef struct _MEMFILE MEMFILE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MEM_SEEK_SET,
|
||||
MEM_SEEK_CUR,
|
||||
MEM_SEEK_END,
|
||||
} mem_rel_t;
|
||||
|
||||
MEMFILE *mem_fopen_read(void *buf, size_t buflen);
|
||||
size_t mem_fread(void *buf, size_t size, size_t nmemb, MEMFILE *stream);
|
||||
MEMFILE *mem_fopen_write(void);
|
||||
size_t mem_fwrite(const void *ptr, size_t size, size_t nmemb, MEMFILE *stream);
|
||||
void mem_get_buf(MEMFILE *stream, void **buf, size_t *buflen);
|
||||
void mem_fclose(MEMFILE *stream);
|
||||
long mem_ftell(MEMFILE *stream);
|
||||
int mem_fseek(MEMFILE *stream, signed long offset, mem_rel_t whence);
|
||||
|
||||
#endif /* #ifndef MEMIO_H */
|
||||
|
|
@ -0,0 +1,693 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
// Copyright(C) 2006 Ben Ryves 2006
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// mus2mid.c - Ben Ryves 2006 - http://benryves.com - benryves@benryves.com
|
||||
// Use to convert a MUS file into a single track, type 0 MIDI file.
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "i_swap.h"
|
||||
|
||||
#include "memio.h"
|
||||
#include "mus2mid.h"
|
||||
|
||||
#define NUM_CHANNELS 16
|
||||
|
||||
#define MIDI_PERCUSSION_CHAN 9
|
||||
#define MUS_PERCUSSION_CHAN 15
|
||||
|
||||
// MUS event codes
|
||||
typedef enum
|
||||
{
|
||||
mus_releasekey = 0x00,
|
||||
mus_presskey = 0x10,
|
||||
mus_pitchwheel = 0x20,
|
||||
mus_systemevent = 0x30,
|
||||
mus_changecontroller = 0x40,
|
||||
mus_scoreend = 0x60
|
||||
} musevent;
|
||||
|
||||
// MIDI event codes
|
||||
typedef enum
|
||||
{
|
||||
midi_releasekey = 0x80,
|
||||
midi_presskey = 0x90,
|
||||
midi_aftertouchkey = 0xA0,
|
||||
midi_changecontroller = 0xB0,
|
||||
midi_changepatch = 0xC0,
|
||||
midi_aftertouchchannel = 0xD0,
|
||||
midi_pitchwheel = 0xE0
|
||||
} midievent;
|
||||
|
||||
// Structure to hold MUS file header
|
||||
typedef struct
|
||||
{
|
||||
byte id[4];
|
||||
unsigned short scorelength;
|
||||
unsigned short scorestart;
|
||||
unsigned short primarychannels;
|
||||
unsigned short secondarychannels;
|
||||
unsigned short instrumentcount;
|
||||
} musheader;
|
||||
|
||||
// Standard MIDI type 0 header + track header
|
||||
static const byte midiheader[] =
|
||||
{
|
||||
'M', 'T', 'h', 'd', // Main header
|
||||
0x00, 0x00, 0x00, 0x06, // Header size
|
||||
0x00, 0x00, // MIDI type (0)
|
||||
0x00, 0x01, // Number of tracks
|
||||
0x00, 0x46, // Resolution
|
||||
'M', 'T', 'r', 'k', // Start of track
|
||||
0x00, 0x00, 0x00, 0x00 // Placeholder for track length
|
||||
};
|
||||
|
||||
// Cached channel velocities
|
||||
static byte channelvelocities[] =
|
||||
{
|
||||
127, 127, 127, 127, 127, 127, 127, 127,
|
||||
127, 127, 127, 127, 127, 127, 127, 127
|
||||
};
|
||||
|
||||
// Timestamps between sequences of MUS events
|
||||
|
||||
static unsigned int queuedtime = 0;
|
||||
|
||||
// Counter for the length of the track
|
||||
|
||||
static unsigned int tracksize;
|
||||
|
||||
static const byte controller_map[] =
|
||||
{
|
||||
0x00, 0x20, 0x01, 0x07, 0x0A, 0x0B, 0x5B, 0x5D,
|
||||
0x40, 0x43, 0x78, 0x7B, 0x7E, 0x7F, 0x79
|
||||
};
|
||||
|
||||
static int channel_map[NUM_CHANNELS];
|
||||
|
||||
// Write timestamp to a MIDI file.
|
||||
|
||||
static boolean WriteTime(unsigned int time, MEMFILE *midioutput)
|
||||
{
|
||||
unsigned int buffer = time & 0x7F;
|
||||
byte writeval;
|
||||
|
||||
while ((time >>= 7) != 0)
|
||||
{
|
||||
buffer <<= 8;
|
||||
buffer |= ((time & 0x7F) | 0x80);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
writeval = (byte)(buffer & 0xFF);
|
||||
|
||||
if (mem_fwrite(&writeval, 1, 1, midioutput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
++tracksize;
|
||||
|
||||
if ((buffer & 0x80) != 0)
|
||||
{
|
||||
buffer >>= 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
queuedtime = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Write the end of track marker
|
||||
static boolean WriteEndTrack(MEMFILE *midioutput)
|
||||
{
|
||||
byte endtrack[] = {0xFF, 0x2F, 0x00};
|
||||
|
||||
if (WriteTime(queuedtime, midioutput))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mem_fwrite(endtrack, 1, 3, midioutput) != 3)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
tracksize += 3;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write a key press event
|
||||
static boolean WritePressKey(byte channel, byte key,
|
||||
byte velocity, MEMFILE *midioutput)
|
||||
{
|
||||
byte working = midi_presskey | channel;
|
||||
|
||||
if (WriteTime(queuedtime, midioutput))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mem_fwrite(&working, 1, 1, midioutput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
working = key & 0x7F;
|
||||
|
||||
if (mem_fwrite(&working, 1, 1, midioutput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
working = velocity & 0x7F;
|
||||
|
||||
if (mem_fwrite(&working, 1, 1, midioutput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
tracksize += 3;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write a key release event
|
||||
static boolean WriteReleaseKey(byte channel, byte key,
|
||||
MEMFILE *midioutput)
|
||||
{
|
||||
byte working = midi_releasekey | channel;
|
||||
|
||||
if (WriteTime(queuedtime, midioutput))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mem_fwrite(&working, 1, 1, midioutput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
working = key & 0x7F;
|
||||
|
||||
if (mem_fwrite(&working, 1, 1, midioutput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
working = 0;
|
||||
|
||||
if (mem_fwrite(&working, 1, 1, midioutput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
tracksize += 3;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write a pitch wheel/bend event
|
||||
static boolean WritePitchWheel(byte channel, short wheel,
|
||||
MEMFILE *midioutput)
|
||||
{
|
||||
byte working = midi_pitchwheel | channel;
|
||||
|
||||
if (WriteTime(queuedtime, midioutput))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mem_fwrite(&working, 1, 1, midioutput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
working = wheel & 0x7F;
|
||||
|
||||
if (mem_fwrite(&working, 1, 1, midioutput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
working = (wheel >> 7) & 0x7F;
|
||||
|
||||
if (mem_fwrite(&working, 1, 1, midioutput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
tracksize += 3;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write a patch change event
|
||||
static boolean WriteChangePatch(byte channel, byte patch,
|
||||
MEMFILE *midioutput)
|
||||
{
|
||||
byte working = midi_changepatch | channel;
|
||||
|
||||
if (WriteTime(queuedtime, midioutput))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mem_fwrite(&working, 1, 1, midioutput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
working = patch & 0x7F;
|
||||
|
||||
if (mem_fwrite(&working, 1, 1, midioutput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
tracksize += 2;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write a valued controller change event
|
||||
|
||||
static boolean WriteChangeController_Valued(byte channel,
|
||||
byte control,
|
||||
byte value,
|
||||
MEMFILE *midioutput)
|
||||
{
|
||||
byte working = midi_changecontroller | channel;
|
||||
|
||||
if (WriteTime(queuedtime, midioutput))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mem_fwrite(&working, 1, 1, midioutput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
working = control & 0x7F;
|
||||
|
||||
if (mem_fwrite(&working, 1, 1, midioutput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Quirk in vanilla DOOM? MUS controller values should be
|
||||
// 7-bit, not 8-bit.
|
||||
|
||||
working = value;// & 0x7F;
|
||||
|
||||
// Fix on said quirk to stop MIDI players from complaining that
|
||||
// the value is out of range:
|
||||
|
||||
if (working & 0x80)
|
||||
{
|
||||
working = 0x7F;
|
||||
}
|
||||
|
||||
if (mem_fwrite(&working, 1, 1, midioutput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
tracksize += 3;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write a valueless controller change event
|
||||
static boolean WriteChangeController_Valueless(byte channel,
|
||||
byte control,
|
||||
MEMFILE *midioutput)
|
||||
{
|
||||
return WriteChangeController_Valued(channel, control, 0,
|
||||
midioutput);
|
||||
}
|
||||
|
||||
// Allocate a free MIDI channel.
|
||||
|
||||
static int AllocateMIDIChannel(void)
|
||||
{
|
||||
int result;
|
||||
int max;
|
||||
int i;
|
||||
|
||||
// Find the current highest-allocated channel.
|
||||
|
||||
max = -1;
|
||||
|
||||
for (i=0; i<NUM_CHANNELS; ++i)
|
||||
{
|
||||
if (channel_map[i] > max)
|
||||
{
|
||||
max = channel_map[i];
|
||||
}
|
||||
}
|
||||
|
||||
// max is now equal to the highest-allocated MIDI channel. We can
|
||||
// now allocate the next available channel. This also works if
|
||||
// no channels are currently allocated (max=-1)
|
||||
|
||||
result = max + 1;
|
||||
|
||||
// Don't allocate the MIDI percussion channel!
|
||||
|
||||
if (result == MIDI_PERCUSSION_CHAN)
|
||||
{
|
||||
++result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Given a MUS channel number, get the MIDI channel number to use
|
||||
// in the outputted file.
|
||||
|
||||
static int GetMIDIChannel(int mus_channel, MEMFILE *midioutput)
|
||||
{
|
||||
// Find the MIDI channel to use for this MUS channel.
|
||||
// MUS channel 15 is the percusssion channel.
|
||||
|
||||
if (mus_channel == MUS_PERCUSSION_CHAN)
|
||||
{
|
||||
return MIDI_PERCUSSION_CHAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If a MIDI channel hasn't been allocated for this MUS channel
|
||||
// yet, allocate the next free MIDI channel.
|
||||
|
||||
if (channel_map[mus_channel] == -1)
|
||||
{
|
||||
channel_map[mus_channel] = AllocateMIDIChannel();
|
||||
|
||||
// First time using the channel, send an "all notes off"
|
||||
// event. This fixes "The D_DDTBLU disease" described here:
|
||||
// https://www.doomworld.com/vb/source-ports/66802-the
|
||||
WriteChangeController_Valueless(channel_map[mus_channel], 0x7b,
|
||||
midioutput);
|
||||
}
|
||||
|
||||
return channel_map[mus_channel];
|
||||
}
|
||||
}
|
||||
|
||||
static boolean ReadMusHeader(MEMFILE *file, musheader *header)
|
||||
{
|
||||
boolean result;
|
||||
|
||||
result = mem_fread(&header->id, sizeof(byte), 4, file) == 4
|
||||
&& mem_fread(&header->scorelength, sizeof(short), 1, file) == 1
|
||||
&& mem_fread(&header->scorestart, sizeof(short), 1, file) == 1
|
||||
&& mem_fread(&header->primarychannels, sizeof(short), 1, file) == 1
|
||||
&& mem_fread(&header->secondarychannels, sizeof(short), 1, file) == 1
|
||||
&& mem_fread(&header->instrumentcount, sizeof(short), 1, file) == 1;
|
||||
|
||||
if (result)
|
||||
{
|
||||
header->scorelength = SHORT(header->scorelength);
|
||||
header->scorestart = SHORT(header->scorestart);
|
||||
header->primarychannels = SHORT(header->primarychannels);
|
||||
header->secondarychannels = SHORT(header->secondarychannels);
|
||||
header->instrumentcount = SHORT(header->instrumentcount);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Read a MUS file from a stream (musinput) and output a MIDI file to
|
||||
// a stream (midioutput).
|
||||
//
|
||||
// Returns 0 on success or 1 on failure.
|
||||
|
||||
boolean mus2mid(MEMFILE *musinput, MEMFILE *midioutput)
|
||||
{
|
||||
// Header for the MUS file
|
||||
musheader musfileheader;
|
||||
|
||||
// Descriptor for the current MUS event
|
||||
byte eventdescriptor;
|
||||
int channel; // Channel number
|
||||
musevent event;
|
||||
|
||||
|
||||
// Bunch of vars read from MUS lump
|
||||
byte key;
|
||||
byte controllernumber;
|
||||
byte controllervalue;
|
||||
|
||||
// Buffer used for MIDI track size record
|
||||
byte tracksizebuffer[4];
|
||||
|
||||
// Flag for when the score end marker is hit.
|
||||
int hitscoreend = 0;
|
||||
|
||||
// Temp working byte
|
||||
byte working;
|
||||
// Used in building up time delays
|
||||
unsigned int timedelay;
|
||||
|
||||
// Initialise channel map to mark all channels as unused.
|
||||
|
||||
for (channel=0; channel<NUM_CHANNELS; ++channel)
|
||||
{
|
||||
channel_map[channel] = -1;
|
||||
}
|
||||
|
||||
// Grab the header
|
||||
|
||||
if (!ReadMusHeader(musinput, &musfileheader))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// [crispy] enable MUS format header check
|
||||
#define CHECK_MUS_HEADER
|
||||
#ifdef CHECK_MUS_HEADER
|
||||
// Check MUS header
|
||||
if (musfileheader.id[0] != 'M'
|
||||
|| musfileheader.id[1] != 'U'
|
||||
|| musfileheader.id[2] != 'S'
|
||||
|| musfileheader.id[3] != 0x1A)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Seek to where the data is held
|
||||
if (mem_fseek(musinput, (long)musfileheader.scorestart,
|
||||
MEM_SEEK_SET) != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// So, we can assume the MUS file is faintly legit. Let's start
|
||||
// writing MIDI data...
|
||||
|
||||
mem_fwrite(midiheader, 1, sizeof(midiheader), midioutput);
|
||||
tracksize = 0;
|
||||
|
||||
// Now, process the MUS file:
|
||||
while (!hitscoreend)
|
||||
{
|
||||
// Handle a block of events:
|
||||
|
||||
while (!hitscoreend)
|
||||
{
|
||||
// Fetch channel number and event code:
|
||||
|
||||
if (mem_fread(&eventdescriptor, 1, 1, musinput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
channel = GetMIDIChannel(eventdescriptor & 0x0F, midioutput);
|
||||
event = eventdescriptor & 0x70;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case mus_releasekey:
|
||||
if (mem_fread(&key, 1, 1, musinput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (WriteReleaseKey(channel, key, midioutput))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case mus_presskey:
|
||||
if (mem_fread(&key, 1, 1, musinput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key & 0x80)
|
||||
{
|
||||
if (mem_fread(&channelvelocities[channel], 1, 1, musinput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
channelvelocities[channel] &= 0x7F;
|
||||
}
|
||||
|
||||
if (WritePressKey(channel, key,
|
||||
channelvelocities[channel], midioutput))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case mus_pitchwheel:
|
||||
if (mem_fread(&key, 1, 1, musinput) != 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (WritePitchWheel(channel, (short)(key * 64), midioutput))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case mus_systemevent:
|
||||
if (mem_fread(&controllernumber, 1, 1, musinput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (controllernumber < 10 || controllernumber > 14)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (WriteChangeController_Valueless(channel,
|
||||
controller_map[controllernumber],
|
||||
midioutput))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case mus_changecontroller:
|
||||
if (mem_fread(&controllernumber, 1, 1, musinput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mem_fread(&controllervalue, 1, 1, musinput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (controllernumber == 0)
|
||||
{
|
||||
if (WriteChangePatch(channel, controllervalue,
|
||||
midioutput))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (controllernumber < 1 || controllernumber > 9)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (WriteChangeController_Valued(channel,
|
||||
controller_map[controllernumber],
|
||||
controllervalue,
|
||||
midioutput))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case mus_scoreend:
|
||||
hitscoreend = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (eventdescriptor & 0x80)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Now we need to read the time code:
|
||||
if (!hitscoreend)
|
||||
{
|
||||
timedelay = 0;
|
||||
for (;;)
|
||||
{
|
||||
if (mem_fread(&working, 1, 1, musinput) != 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
timedelay = timedelay * 128 + (working & 0x7F);
|
||||
if ((working & 0x80) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
queuedtime += timedelay;
|
||||
}
|
||||
}
|
||||
|
||||
// End of track
|
||||
if (WriteEndTrack(midioutput))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write the track size into the stream
|
||||
if (mem_fseek(midioutput, 18, MEM_SEEK_SET))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
tracksizebuffer[0] = (tracksize >> 24) & 0xff;
|
||||
tracksizebuffer[1] = (tracksize >> 16) & 0xff;
|
||||
tracksizebuffer[2] = (tracksize >> 8) & 0xff;
|
||||
tracksizebuffer[3] = tracksize & 0xff;
|
||||
|
||||
if (mem_fwrite(tracksizebuffer, 1, 4, midioutput) != 4)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef MUS2MID_H
|
||||
#define MUS2MID_H
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "memio.h"
|
||||
|
||||
boolean mus2mid(MEMFILE *musinput, MEMFILE *midioutput);
|
||||
|
||||
#endif /* #ifndef MUS2MID_H */
|
|
@ -0,0 +1,4 @@
|
|||
#include "net_client.h"
|
||||
|
||||
boolean net_client_connected = false;
|
||||
boolean drone = false;
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// Network client code
|
||||
//
|
||||
|
||||
#ifndef NET_CLIENT_H
|
||||
#define NET_CLIENT_H
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "d_ticcmd.h"
|
||||
#include "sha1.h"
|
||||
#include "net_defs.h"
|
||||
|
||||
boolean NET_CL_Connect(net_addr_t *addr, net_connect_data_t *data);
|
||||
void NET_CL_Disconnect(void);
|
||||
void NET_CL_Run(void);
|
||||
void NET_CL_Init(void);
|
||||
void NET_CL_LaunchGame(void);
|
||||
void NET_CL_StartGame(net_gamesettings_t *settings);
|
||||
void NET_CL_SendTiccmd(ticcmd_t *ticcmd, int maketic);
|
||||
boolean NET_CL_GetSettings(net_gamesettings_t *_settings);
|
||||
void NET_Init(void);
|
||||
|
||||
void NET_BindVariables(void);
|
||||
|
||||
extern boolean net_client_connected;
|
||||
extern boolean net_client_received_wait_data;
|
||||
extern net_waitdata_t net_client_wait_data;
|
||||
extern boolean net_waiting_for_launch;
|
||||
extern char *net_player_name;
|
||||
|
||||
extern sha1_digest_t net_server_wad_sha1sum;
|
||||
extern unsigned int net_server_is_freedoom;
|
||||
extern sha1_digest_t net_local_wad_sha1sum;
|
||||
extern unsigned int net_local_is_freedoom;
|
||||
|
||||
extern boolean drone;
|
||||
|
||||
#endif /* #ifndef NET_CLIENT_H */
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//
|
||||
// Dedicated server code.
|
||||
//
|
||||
|
||||
#ifndef NET_DEDICATED_H
|
||||
#define NET_DEDICATED_H
|
||||
|
||||
void NET_DedicatedServer(void);
|
||||
|
||||
#endif /* #ifndef NET_DEDICATED_H */
|
||||
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Definitions for use in networking code.
|
||||
//
|
||||
|
||||
#ifndef NET_DEFS_H
|
||||
#define NET_DEFS_H
|
||||
|
||||
#include "essence/include.h"
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "d_ticcmd.h"
|
||||
#include "sha1.h"
|
||||
|
||||
// Absolute maximum number of "nodes" in the game. This is different to
|
||||
// NET_MAXPLAYERS, as there may be observers that are not participating
|
||||
// (eg. left/right monitors)
|
||||
|
||||
#define MAXNETNODES 16
|
||||
|
||||
// The maximum number of players, multiplayer/networking.
|
||||
// This is the maximum supported by the networking code; individual games
|
||||
// have their own values for MAXPLAYERS that can be smaller.
|
||||
|
||||
#define NET_MAXPLAYERS 8
|
||||
|
||||
// Maximum length of a player's name.
|
||||
|
||||
#define MAXPLAYERNAME 30
|
||||
|
||||
// Networking and tick handling related.
|
||||
|
||||
#define BACKUPTICS 128
|
||||
|
||||
typedef struct _net_module_s net_module_t;
|
||||
typedef struct _net_packet_s net_packet_t;
|
||||
typedef struct _net_addr_s net_addr_t;
|
||||
typedef struct _net_context_s net_context_t;
|
||||
|
||||
struct _net_packet_s
|
||||
{
|
||||
byte *data;
|
||||
size_t len;
|
||||
size_t alloced;
|
||||
unsigned int pos;
|
||||
};
|
||||
|
||||
struct _net_module_s
|
||||
{
|
||||
// Initialize this module for use as a client
|
||||
|
||||
boolean (*InitClient)(void);
|
||||
|
||||
// Initialize this module for use as a server
|
||||
|
||||
boolean (*InitServer)(void);
|
||||
|
||||
// Send a packet
|
||||
|
||||
void (*SendPacket)(net_addr_t *addr, net_packet_t *packet);
|
||||
|
||||
// Check for new packets to receive
|
||||
//
|
||||
// Returns true if packet received
|
||||
|
||||
boolean (*RecvPacket)(net_addr_t **addr, net_packet_t **packet);
|
||||
|
||||
// Converts an address to a string
|
||||
|
||||
void (*AddrToString)(net_addr_t *addr, char *buffer, int buffer_len);
|
||||
|
||||
// Free back an address when no longer in use
|
||||
|
||||
void (*FreeAddress)(net_addr_t *addr);
|
||||
|
||||
// Try to resolve a name to an address
|
||||
|
||||
net_addr_t *(*ResolveAddress)(char *addr);
|
||||
};
|
||||
|
||||
// net_addr_t
|
||||
|
||||
struct _net_addr_s
|
||||
{
|
||||
net_module_t *module;
|
||||
void *handle;
|
||||
};
|
||||
|
||||
// magic number sent when connecting to check this is a valid client
|
||||
|
||||
#define NET_MAGIC_NUMBER 3436803284U
|
||||
|
||||
// header field value indicating that the packet is a reliable packet
|
||||
|
||||
#define NET_RELIABLE_PACKET (1 << 15)
|
||||
|
||||
// packet types
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NET_PACKET_TYPE_SYN,
|
||||
NET_PACKET_TYPE_ACK,
|
||||
NET_PACKET_TYPE_REJECTED,
|
||||
NET_PACKET_TYPE_KEEPALIVE,
|
||||
NET_PACKET_TYPE_WAITING_DATA,
|
||||
NET_PACKET_TYPE_GAMESTART,
|
||||
NET_PACKET_TYPE_GAMEDATA,
|
||||
NET_PACKET_TYPE_GAMEDATA_ACK,
|
||||
NET_PACKET_TYPE_DISCONNECT,
|
||||
NET_PACKET_TYPE_DISCONNECT_ACK,
|
||||
NET_PACKET_TYPE_RELIABLE_ACK,
|
||||
NET_PACKET_TYPE_GAMEDATA_RESEND,
|
||||
NET_PACKET_TYPE_CONSOLE_MESSAGE,
|
||||
NET_PACKET_TYPE_QUERY,
|
||||
NET_PACKET_TYPE_QUERY_RESPONSE,
|
||||
NET_PACKET_TYPE_LAUNCH,
|
||||
} net_packet_type_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NET_MASTER_PACKET_TYPE_ADD,
|
||||
NET_MASTER_PACKET_TYPE_ADD_RESPONSE,
|
||||
NET_MASTER_PACKET_TYPE_QUERY,
|
||||
NET_MASTER_PACKET_TYPE_QUERY_RESPONSE,
|
||||
NET_MASTER_PACKET_TYPE_GET_METADATA,
|
||||
NET_MASTER_PACKET_TYPE_GET_METADATA_RESPONSE,
|
||||
NET_MASTER_PACKET_TYPE_SIGN_START,
|
||||
NET_MASTER_PACKET_TYPE_SIGN_START_RESPONSE,
|
||||
NET_MASTER_PACKET_TYPE_SIGN_END,
|
||||
NET_MASTER_PACKET_TYPE_SIGN_END_RESPONSE,
|
||||
} net_master_packet_type_t;
|
||||
|
||||
// Settings specified when the client connects to the server.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int gamemode;
|
||||
int gamemission;
|
||||
int lowres_turn;
|
||||
int drone;
|
||||
int max_players;
|
||||
int is_freedoom;
|
||||
sha1_digest_t wad_sha1sum;
|
||||
int player_class;
|
||||
} net_connect_data_t;
|
||||
|
||||
// Game settings sent by client to server when initiating game start,
|
||||
// and received from the server by clients when the game starts.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int ticdup;
|
||||
int extratics;
|
||||
int deathmatch;
|
||||
int episode;
|
||||
int nomonsters;
|
||||
int fast_monsters;
|
||||
int respawn_monsters;
|
||||
int map;
|
||||
int skill;
|
||||
int gameversion;
|
||||
int lowres_turn;
|
||||
int new_sync;
|
||||
int timelimit;
|
||||
int loadgame;
|
||||
int random; // [Strife only]
|
||||
|
||||
// These fields are only used by the server when sending a game
|
||||
// start message:
|
||||
|
||||
int num_players;
|
||||
int consoleplayer;
|
||||
|
||||
// Hexen player classes:
|
||||
|
||||
int player_classes[NET_MAXPLAYERS];
|
||||
|
||||
} net_gamesettings_t;
|
||||
|
||||
#define NET_TICDIFF_FORWARD (1 << 0)
|
||||
#define NET_TICDIFF_SIDE (1 << 1)
|
||||
#define NET_TICDIFF_TURN (1 << 2)
|
||||
#define NET_TICDIFF_BUTTONS (1 << 3)
|
||||
#define NET_TICDIFF_CONSISTANCY (1 << 4)
|
||||
#define NET_TICDIFF_CHATCHAR (1 << 5)
|
||||
#define NET_TICDIFF_RAVEN (1 << 6)
|
||||
#define NET_TICDIFF_STRIFE (1 << 7)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int diff;
|
||||
ticcmd_t cmd;
|
||||
} net_ticdiff_t;
|
||||
|
||||
// Complete set of ticcmds from all players
|
||||
|
||||
typedef struct
|
||||
{
|
||||
signed int latency;
|
||||
unsigned int seq;
|
||||
boolean playeringame[NET_MAXPLAYERS];
|
||||
net_ticdiff_t cmds[NET_MAXPLAYERS];
|
||||
} net_full_ticcmd_t;
|
||||
|
||||
// Data sent in response to server queries
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *version;
|
||||
int server_state;
|
||||
int num_players;
|
||||
int max_players;
|
||||
int gamemode;
|
||||
int gamemission;
|
||||
char *description;
|
||||
} net_querydata_t;
|
||||
|
||||
// Data sent by the server while waiting for the game to start.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int num_players;
|
||||
int num_drones;
|
||||
int ready_players;
|
||||
int max_players;
|
||||
int is_controller;
|
||||
int consoleplayer;
|
||||
char player_names[NET_MAXPLAYERS][MAXPLAYERNAME];
|
||||
char player_addrs[NET_MAXPLAYERS][MAXPLAYERNAME];
|
||||
sha1_digest_t wad_sha1sum;
|
||||
int is_freedoom;
|
||||
} net_waitdata_t;
|
||||
|
||||
#endif /* #ifndef NET_DEFS_H */
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// Graphical stuff related to the networking code:
|
||||
//
|
||||
// * The client waiting screen when we are waiting for the server to
|
||||
// start the game.
|
||||
//
|
||||
|
||||
|
||||
#ifndef NET_GUI_H
|
||||
#define NET_GUI_H
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
extern void NET_WaitForLaunch(void);
|
||||
|
||||
#endif /* #ifndef NET_GUI_H */
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Network packet manipulation (net_packet_t)
|
||||
//
|
||||
|
||||
#ifndef NET_IO_H
|
||||
#define NET_IO_H
|
||||
|
||||
#include "net_defs.h"
|
||||
|
||||
extern net_addr_t net_broadcast_addr;
|
||||
|
||||
net_context_t *NET_NewContext(void);
|
||||
void NET_AddModule(net_context_t *context, net_module_t *module);
|
||||
void NET_SendPacket(net_addr_t *addr, net_packet_t *packet);
|
||||
void NET_SendBroadcast(net_context_t *context, net_packet_t *packet);
|
||||
boolean NET_RecvPacket(net_context_t *context, net_addr_t **addr,
|
||||
net_packet_t **packet);
|
||||
char *NET_AddrToString(net_addr_t *addr);
|
||||
void NET_FreeAddress(net_addr_t *addr);
|
||||
net_addr_t *NET_ResolveAddress(net_context_t *context, char *address);
|
||||
|
||||
#endif /* #ifndef NET_IO_H */
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Loopback network module for server compiled into the client
|
||||
//
|
||||
|
||||
#ifndef NET_LOOP_H
|
||||
#define NET_LOOP_H
|
||||
|
||||
#include "net_defs.h"
|
||||
|
||||
extern net_module_t net_loop_client_module;
|
||||
extern net_module_t net_loop_server_module;
|
||||
|
||||
#endif /* #ifndef NET_LOOP_H */
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Definitions for use in networking code.
|
||||
//
|
||||
|
||||
#ifndef NET_PACKET_H
|
||||
#define NET_PACKET_H
|
||||
|
||||
#include "net_defs.h"
|
||||
|
||||
net_packet_t *NET_NewPacket(int initial_size);
|
||||
net_packet_t *NET_PacketDup(net_packet_t *packet);
|
||||
void NET_FreePacket(net_packet_t *packet);
|
||||
|
||||
boolean NET_ReadInt8(net_packet_t *packet, unsigned int *data);
|
||||
boolean NET_ReadInt16(net_packet_t *packet, unsigned int *data);
|
||||
boolean NET_ReadInt32(net_packet_t *packet, unsigned int *data);
|
||||
|
||||
boolean NET_ReadSInt8(net_packet_t *packet, signed int *data);
|
||||
boolean NET_ReadSInt16(net_packet_t *packet, signed int *data);
|
||||
boolean NET_ReadSInt32(net_packet_t *packet, signed int *data);
|
||||
|
||||
char *NET_ReadString(net_packet_t *packet);
|
||||
|
||||
void NET_WriteInt8(net_packet_t *packet, unsigned int i);
|
||||
void NET_WriteInt16(net_packet_t *packet, unsigned int i);
|
||||
void NET_WriteInt32(net_packet_t *packet, unsigned int i);
|
||||
|
||||
void NET_WriteString(net_packet_t *packet, char *string);
|
||||
|
||||
#endif /* #ifndef NET_PACKET_H */
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Querying servers to find their current status.
|
||||
//
|
||||
|
||||
#ifndef NET_QUERY_H
|
||||
#define NET_QUERY_H
|
||||
|
||||
#include "net_defs.h"
|
||||
|
||||
typedef void (*net_query_callback_t)(net_addr_t *addr,
|
||||
net_querydata_t *querydata,
|
||||
unsigned int ping_time,
|
||||
void *user_data);
|
||||
|
||||
extern int NET_StartLANQuery(void);
|
||||
extern int NET_StartMasterQuery(void);
|
||||
|
||||
extern void NET_LANQuery(void);
|
||||
extern void NET_MasterQuery(void);
|
||||
extern void NET_QueryAddress(char *addr);
|
||||
extern net_addr_t *NET_FindLANServer(void);
|
||||
|
||||
extern int NET_Query_Poll(net_query_callback_t callback, void *user_data);
|
||||
|
||||
extern net_addr_t *NET_Query_ResolveMaster(net_context_t *context);
|
||||
extern void NET_Query_AddToMaster(net_addr_t *master_addr);
|
||||
extern boolean NET_Query_CheckAddedToMaster(boolean *result);
|
||||
extern void NET_Query_MasterResponse(net_packet_t *packet);
|
||||
|
||||
#endif /* #ifndef NET_QUERY_H */
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// Network server code
|
||||
//
|
||||
|
||||
#ifndef NET_SERVER_H
|
||||
#define NET_SERVER_H
|
||||
|
||||
// initialize server and wait for connections
|
||||
|
||||
void NET_SV_Init(void);
|
||||
|
||||
// run server: check for new packets received etc.
|
||||
|
||||
void NET_SV_Run(void);
|
||||
|
||||
// Shut down the server
|
||||
// Blocks until all clients disconnect, or until a 5 second timeout
|
||||
|
||||
void NET_SV_Shutdown(void);
|
||||
|
||||
// Add a network module to the context used by the server
|
||||
|
||||
void NET_SV_AddModule(net_module_t *module);
|
||||
|
||||
// Register server with master server.
|
||||
|
||||
void NET_SV_RegisterWithMaster(void);
|
||||
|
||||
#endif /* #ifndef NET_SERVER_H */
|
||||
|
|
@ -0,0 +1,328 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION: Ceiling aninmation (lowering, crushing, raising)
|
||||
//
|
||||
|
||||
|
||||
|
||||
#include "z_zone.h"
|
||||
#include "doomdef.h"
|
||||
#include "p_local.h"
|
||||
|
||||
#include "s_sound.h"
|
||||
|
||||
// State.
|
||||
#include "doomstat.h"
|
||||
#include "r_state.h"
|
||||
|
||||
// Data.
|
||||
#include "sounds.h"
|
||||
|
||||
//
|
||||
// CEILINGS
|
||||
//
|
||||
|
||||
|
||||
ceiling_t* activeceilings[MAXCEILINGS];
|
||||
|
||||
|
||||
//
|
||||
// T_MoveCeiling
|
||||
//
|
||||
|
||||
void T_MoveCeiling (ceiling_t* ceiling)
|
||||
{
|
||||
result_e res;
|
||||
|
||||
switch(ceiling->direction)
|
||||
{
|
||||
case 0:
|
||||
// IN STASIS
|
||||
break;
|
||||
case 1:
|
||||
// UP
|
||||
res = T_MovePlane(ceiling->sector,
|
||||
ceiling->speed,
|
||||
ceiling->topheight,
|
||||
false,1,ceiling->direction);
|
||||
|
||||
if (!(leveltime&7))
|
||||
{
|
||||
switch(ceiling->type)
|
||||
{
|
||||
case silentCrushAndRaise:
|
||||
break;
|
||||
default:
|
||||
S_StartSound(&ceiling->sector->soundorg, sfx_stnmov);
|
||||
// ?
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (res == pastdest)
|
||||
{
|
||||
switch(ceiling->type)
|
||||
{
|
||||
case raiseToHighest:
|
||||
P_RemoveActiveCeiling(ceiling);
|
||||
break;
|
||||
|
||||
case silentCrushAndRaise:
|
||||
S_StartSound(&ceiling->sector->soundorg, sfx_pstop);
|
||||
// fall through
|
||||
case fastCrushAndRaise:
|
||||
case crushAndRaise:
|
||||
ceiling->direction = -1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case -1:
|
||||
// DOWN
|
||||
res = T_MovePlane(ceiling->sector,
|
||||
ceiling->speed,
|
||||
ceiling->bottomheight,
|
||||
ceiling->crush,1,ceiling->direction);
|
||||
|
||||
if (!(leveltime&7))
|
||||
{
|
||||
switch(ceiling->type)
|
||||
{
|
||||
case silentCrushAndRaise: break;
|
||||
default:
|
||||
S_StartSound(&ceiling->sector->soundorg, sfx_stnmov);
|
||||
}
|
||||
}
|
||||
|
||||
if (res == pastdest)
|
||||
{
|
||||
switch(ceiling->type)
|
||||
{
|
||||
case silentCrushAndRaise:
|
||||
S_StartSound(&ceiling->sector->soundorg, sfx_pstop);
|
||||
// fall through
|
||||
case crushAndRaise:
|
||||
ceiling->speed = CEILSPEED;
|
||||
// fall through
|
||||
case fastCrushAndRaise:
|
||||
ceiling->direction = 1;
|
||||
break;
|
||||
|
||||
case lowerAndCrush:
|
||||
case lowerToFloor:
|
||||
P_RemoveActiveCeiling(ceiling);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // ( res != pastdest )
|
||||
{
|
||||
if (res == crushed)
|
||||
{
|
||||
switch(ceiling->type)
|
||||
{
|
||||
case silentCrushAndRaise:
|
||||
case crushAndRaise:
|
||||
case lowerAndCrush:
|
||||
ceiling->speed = CEILSPEED / 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// EV_DoCeiling
|
||||
// Move a ceiling up/down and all around!
|
||||
//
|
||||
int
|
||||
EV_DoCeiling
|
||||
( line_t* line,
|
||||
ceiling_e type )
|
||||
{
|
||||
int secnum;
|
||||
int rtn;
|
||||
sector_t* sec;
|
||||
ceiling_t* ceiling;
|
||||
|
||||
secnum = -1;
|
||||
rtn = 0;
|
||||
|
||||
// Reactivate in-stasis ceilings...for certain types.
|
||||
switch(type)
|
||||
{
|
||||
case fastCrushAndRaise:
|
||||
case silentCrushAndRaise:
|
||||
case crushAndRaise:
|
||||
P_ActivateInStasisCeiling(line);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
if (sec->specialdata)
|
||||
continue;
|
||||
|
||||
// new door thinker
|
||||
rtn = 1;
|
||||
ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0);
|
||||
P_AddThinker (&ceiling->thinker);
|
||||
sec->specialdata = ceiling;
|
||||
ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
|
||||
ceiling->sector = sec;
|
||||
ceiling->crush = false;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case fastCrushAndRaise:
|
||||
ceiling->crush = true;
|
||||
ceiling->topheight = sec->ceilingheight;
|
||||
ceiling->bottomheight = sec->floorheight + (8*FRACUNIT);
|
||||
ceiling->direction = -1;
|
||||
ceiling->speed = CEILSPEED * 2;
|
||||
break;
|
||||
|
||||
case silentCrushAndRaise:
|
||||
case crushAndRaise:
|
||||
ceiling->crush = true;
|
||||
ceiling->topheight = sec->ceilingheight;
|
||||
// fall through
|
||||
case lowerAndCrush:
|
||||
case lowerToFloor:
|
||||
ceiling->bottomheight = sec->floorheight;
|
||||
if (type != lowerToFloor)
|
||||
ceiling->bottomheight += 8*FRACUNIT;
|
||||
ceiling->direction = -1;
|
||||
ceiling->speed = CEILSPEED;
|
||||
break;
|
||||
|
||||
case raiseToHighest:
|
||||
ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
|
||||
ceiling->direction = 1;
|
||||
ceiling->speed = CEILSPEED;
|
||||
break;
|
||||
}
|
||||
|
||||
ceiling->tag = sec->tag;
|
||||
ceiling->type = type;
|
||||
P_AddActiveCeiling(ceiling);
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Add an active ceiling
|
||||
//
|
||||
void P_AddActiveCeiling(ceiling_t* c)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXCEILINGS;i++)
|
||||
{
|
||||
if (activeceilings[i] == NULL)
|
||||
{
|
||||
activeceilings[i] = c;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Remove a ceiling's thinker
|
||||
//
|
||||
void P_RemoveActiveCeiling(ceiling_t* c)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0;i < MAXCEILINGS;i++)
|
||||
{
|
||||
if (activeceilings[i] == c)
|
||||
{
|
||||
activeceilings[i]->sector->specialdata = NULL;
|
||||
P_RemoveThinker (&activeceilings[i]->thinker);
|
||||
activeceilings[i] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Restart a ceiling that's in-stasis
|
||||
//
|
||||
void P_ActivateInStasisCeiling(line_t* line)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0;i < MAXCEILINGS;i++)
|
||||
{
|
||||
if (activeceilings[i]
|
||||
&& (activeceilings[i]->tag == line->tag)
|
||||
&& (activeceilings[i]->direction == 0))
|
||||
{
|
||||
activeceilings[i]->direction = activeceilings[i]->olddirection;
|
||||
activeceilings[i]->thinker.function.acp1
|
||||
= (actionf_p1)T_MoveCeiling;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// EV_CeilingCrushStop
|
||||
// Stop a ceiling from crushing!
|
||||
//
|
||||
int EV_CeilingCrushStop(line_t *line)
|
||||
{
|
||||
int i;
|
||||
int rtn;
|
||||
|
||||
rtn = 0;
|
||||
for (i = 0;i < MAXCEILINGS;i++)
|
||||
{
|
||||
if (activeceilings[i]
|
||||
&& (activeceilings[i]->tag == line->tag)
|
||||
&& (activeceilings[i]->direction != 0))
|
||||
{
|
||||
activeceilings[i]->olddirection = activeceilings[i]->direction;
|
||||
activeceilings[i]->thinker.function.acv = (actionf_v)NULL;
|
||||
activeceilings[i]->direction = 0; // in-stasis
|
||||
rtn = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return rtn;
|
||||
}
|
|
@ -0,0 +1,546 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION: Door animation code (opening/closing)
|
||||
//
|
||||
|
||||
#include "z_zone.h"
|
||||
#include "doomdef.h"
|
||||
#include "p_local.h"
|
||||
|
||||
#include "s_sound.h"
|
||||
|
||||
|
||||
// State.
|
||||
#include "doomstat.h"
|
||||
#include "r_state.h"
|
||||
|
||||
// Data.
|
||||
#include "dstrings.h"
|
||||
#include "sounds.h"
|
||||
|
||||
//
|
||||
// VERTICAL DOORS
|
||||
//
|
||||
|
||||
//
|
||||
// T_VerticalDoor
|
||||
//
|
||||
void T_VerticalDoor (vldoor_t* door)
|
||||
{
|
||||
result_e res;
|
||||
|
||||
switch(door->direction)
|
||||
{
|
||||
case 0:
|
||||
// WAITING
|
||||
if (!--door->topcountdown)
|
||||
{
|
||||
switch(door->type)
|
||||
{
|
||||
case vld_blazeRaise:
|
||||
door->direction = -1; // time to go back down
|
||||
S_StartSound(&door->sector->soundorg, sfx_bdcls);
|
||||
break;
|
||||
|
||||
case vld_normal:
|
||||
door->direction = -1; // time to go back down
|
||||
S_StartSound(&door->sector->soundorg, sfx_dorcls);
|
||||
break;
|
||||
|
||||
case vld_close30ThenOpen:
|
||||
door->direction = 1;
|
||||
S_StartSound(&door->sector->soundorg, sfx_doropn);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// INITIAL WAIT
|
||||
if (!--door->topcountdown)
|
||||
{
|
||||
switch(door->type)
|
||||
{
|
||||
case vld_raiseIn5Mins:
|
||||
door->direction = 1;
|
||||
door->type = vld_normal;
|
||||
S_StartSound(&door->sector->soundorg, sfx_doropn);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case -1:
|
||||
// DOWN
|
||||
res = T_MovePlane(door->sector,
|
||||
door->speed,
|
||||
door->sector->floorheight,
|
||||
false,1,door->direction);
|
||||
if (res == pastdest)
|
||||
{
|
||||
switch(door->type)
|
||||
{
|
||||
case vld_blazeRaise:
|
||||
case vld_blazeClose:
|
||||
door->sector->specialdata = NULL;
|
||||
P_RemoveThinker (&door->thinker); // unlink and free
|
||||
S_StartSound(&door->sector->soundorg, sfx_bdcls);
|
||||
break;
|
||||
|
||||
case vld_normal:
|
||||
case vld_close:
|
||||
door->sector->specialdata = NULL;
|
||||
P_RemoveThinker (&door->thinker); // unlink and free
|
||||
break;
|
||||
|
||||
case vld_close30ThenOpen:
|
||||
door->direction = 0;
|
||||
door->topcountdown = TICRATE*30;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (res == crushed)
|
||||
{
|
||||
switch(door->type)
|
||||
{
|
||||
case vld_blazeClose:
|
||||
case vld_close: // DO NOT GO BACK UP!
|
||||
break;
|
||||
|
||||
default:
|
||||
door->direction = 1;
|
||||
S_StartSound(&door->sector->soundorg, sfx_doropn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// UP
|
||||
res = T_MovePlane(door->sector,
|
||||
door->speed,
|
||||
door->topheight,
|
||||
false,1,door->direction);
|
||||
|
||||
if (res == pastdest)
|
||||
{
|
||||
switch(door->type)
|
||||
{
|
||||
case vld_blazeRaise:
|
||||
case vld_normal:
|
||||
door->direction = 0; // wait at top
|
||||
door->topcountdown = door->topwait;
|
||||
break;
|
||||
|
||||
case vld_close30ThenOpen:
|
||||
case vld_blazeOpen:
|
||||
case vld_open:
|
||||
door->sector->specialdata = NULL;
|
||||
P_RemoveThinker (&door->thinker); // unlink and free
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// EV_DoLockedDoor
|
||||
// Move a locked door up/down
|
||||
//
|
||||
|
||||
int
|
||||
EV_DoLockedDoor
|
||||
( line_t* line,
|
||||
vldoor_e type,
|
||||
mobj_t* thing )
|
||||
{
|
||||
player_t* p;
|
||||
|
||||
p = thing->player;
|
||||
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
switch(line->special)
|
||||
{
|
||||
case 99: // Blue Lock
|
||||
case 133:
|
||||
if ( !p )
|
||||
return 0;
|
||||
if (!p->cards[it_bluecard] && !p->cards[it_blueskull])
|
||||
{
|
||||
p->message = PD_BLUEO;
|
||||
S_StartSound(NULL,sfx_oof);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 134: // Red Lock
|
||||
case 135:
|
||||
if ( !p )
|
||||
return 0;
|
||||
if (!p->cards[it_redcard] && !p->cards[it_redskull])
|
||||
{
|
||||
p->message = PD_REDO;
|
||||
S_StartSound(NULL,sfx_oof);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 136: // Yellow Lock
|
||||
case 137:
|
||||
if ( !p )
|
||||
return 0;
|
||||
if (!p->cards[it_yellowcard] &&
|
||||
!p->cards[it_yellowskull])
|
||||
{
|
||||
p->message = PD_YELLOWO;
|
||||
S_StartSound(NULL,sfx_oof);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return EV_DoDoor(line,type);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
EV_DoDoor
|
||||
( line_t* line,
|
||||
vldoor_e type )
|
||||
{
|
||||
int secnum,rtn;
|
||||
sector_t* sec;
|
||||
vldoor_t* door;
|
||||
|
||||
secnum = -1;
|
||||
rtn = 0;
|
||||
|
||||
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
if (sec->specialdata)
|
||||
continue;
|
||||
|
||||
|
||||
// new door thinker
|
||||
rtn = 1;
|
||||
door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
|
||||
P_AddThinker (&door->thinker);
|
||||
sec->specialdata = door;
|
||||
|
||||
door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor;
|
||||
door->sector = sec;
|
||||
door->type = type;
|
||||
door->topwait = VDOORWAIT;
|
||||
door->speed = VDOORSPEED;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case vld_blazeClose:
|
||||
door->topheight = P_FindLowestCeilingSurrounding(sec);
|
||||
door->topheight -= 4*FRACUNIT;
|
||||
door->direction = -1;
|
||||
door->speed = VDOORSPEED * 4;
|
||||
S_StartSound(&door->sector->soundorg, sfx_bdcls);
|
||||
break;
|
||||
|
||||
case vld_close:
|
||||
door->topheight = P_FindLowestCeilingSurrounding(sec);
|
||||
door->topheight -= 4*FRACUNIT;
|
||||
door->direction = -1;
|
||||
S_StartSound(&door->sector->soundorg, sfx_dorcls);
|
||||
break;
|
||||
|
||||
case vld_close30ThenOpen:
|
||||
door->topheight = sec->ceilingheight;
|
||||
door->direction = -1;
|
||||
S_StartSound(&door->sector->soundorg, sfx_dorcls);
|
||||
break;
|
||||
|
||||
case vld_blazeRaise:
|
||||
case vld_blazeOpen:
|
||||
door->direction = 1;
|
||||
door->topheight = P_FindLowestCeilingSurrounding(sec);
|
||||
door->topheight -= 4*FRACUNIT;
|
||||
door->speed = VDOORSPEED * 4;
|
||||
if (door->topheight != sec->ceilingheight)
|
||||
S_StartSound(&door->sector->soundorg, sfx_bdopn);
|
||||
break;
|
||||
|
||||
case vld_normal:
|
||||
case vld_open:
|
||||
door->direction = 1;
|
||||
door->topheight = P_FindLowestCeilingSurrounding(sec);
|
||||
door->topheight -= 4*FRACUNIT;
|
||||
if (door->topheight != sec->ceilingheight)
|
||||
S_StartSound(&door->sector->soundorg, sfx_doropn);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// EV_VerticalDoor : open a door manually, no tag value
|
||||
//
|
||||
void
|
||||
EV_VerticalDoor
|
||||
( line_t* line,
|
||||
mobj_t* thing )
|
||||
{
|
||||
player_t* player;
|
||||
sector_t* sec;
|
||||
vldoor_t* door;
|
||||
int side;
|
||||
|
||||
side = 0; // only front sides can be used
|
||||
|
||||
// Check for locks
|
||||
player = thing->player;
|
||||
|
||||
switch(line->special)
|
||||
{
|
||||
case 26: // Blue Lock
|
||||
case 32:
|
||||
if ( !player )
|
||||
return;
|
||||
|
||||
if (!player->cards[it_bluecard] && !player->cards[it_blueskull])
|
||||
{
|
||||
player->message = PD_BLUEK;
|
||||
S_StartSound(NULL,sfx_oof);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 27: // Yellow Lock
|
||||
case 34:
|
||||
if ( !player )
|
||||
return;
|
||||
|
||||
if (!player->cards[it_yellowcard] &&
|
||||
!player->cards[it_yellowskull])
|
||||
{
|
||||
player->message = PD_YELLOWK;
|
||||
S_StartSound(NULL,sfx_oof);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 28: // Red Lock
|
||||
case 33:
|
||||
if ( !player )
|
||||
return;
|
||||
|
||||
if (!player->cards[it_redcard] && !player->cards[it_redskull])
|
||||
{
|
||||
player->message = PD_REDK;
|
||||
S_StartSound(NULL,sfx_oof);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// if the sector has an active thinker, use it
|
||||
sec = sides[ line->sidenum[side^1]] .sector;
|
||||
|
||||
if (sec->specialdata)
|
||||
{
|
||||
door = sec->specialdata;
|
||||
switch(line->special)
|
||||
{
|
||||
case 1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s
|
||||
case 26:
|
||||
case 27:
|
||||
case 28:
|
||||
case 117:
|
||||
if (door->direction == -1)
|
||||
door->direction = 1; // go back up
|
||||
else
|
||||
{
|
||||
if (!thing->player)
|
||||
return; // JDC: bad guys never close doors
|
||||
|
||||
// When is a door not a door?
|
||||
// In Vanilla, door->direction is set, even though
|
||||
// "specialdata" might not actually point at a door.
|
||||
|
||||
if (door->thinker.function.acp1 == (actionf_p1) T_VerticalDoor)
|
||||
{
|
||||
door->direction = -1; // start going down immediately
|
||||
}
|
||||
else if (door->thinker.function.acp1 == (actionf_p1) T_PlatRaise)
|
||||
{
|
||||
// Erm, this is a plat, not a door.
|
||||
// This notably causes a problem in ep1-0500.lmp where
|
||||
// a plat and a door are cross-referenced; the door
|
||||
// doesn't open on 64-bit.
|
||||
// The direction field in vldoor_t corresponds to the wait
|
||||
// field in plat_t. Let's set that to -1 instead.
|
||||
|
||||
plat_t *plat;
|
||||
|
||||
plat = (plat_t *) door;
|
||||
plat->wait = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This isn't a door OR a plat. Now we're in trouble.
|
||||
ES_debugf("EV_VerticalDoor: Tried to close "
|
||||
"something that wasn't a door.\n");
|
||||
|
||||
// Try closing it anyway. At least it will work on 32-bit
|
||||
// machines.
|
||||
|
||||
door->direction = -1;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// for proper sound
|
||||
switch(line->special)
|
||||
{
|
||||
case 117: // BLAZING DOOR RAISE
|
||||
case 118: // BLAZING DOOR OPEN
|
||||
S_StartSound(&sec->soundorg,sfx_bdopn);
|
||||
break;
|
||||
|
||||
case 1: // NORMAL DOOR SOUND
|
||||
case 31:
|
||||
S_StartSound(&sec->soundorg,sfx_doropn);
|
||||
break;
|
||||
|
||||
default: // LOCKED DOOR SOUND
|
||||
S_StartSound(&sec->soundorg,sfx_doropn);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// new door thinker
|
||||
door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
|
||||
P_AddThinker (&door->thinker);
|
||||
sec->specialdata = door;
|
||||
door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor;
|
||||
door->sector = sec;
|
||||
door->direction = 1;
|
||||
door->speed = VDOORSPEED;
|
||||
door->topwait = VDOORWAIT;
|
||||
|
||||
switch(line->special)
|
||||
{
|
||||
case 1:
|
||||
case 26:
|
||||
case 27:
|
||||
case 28:
|
||||
door->type = vld_normal;
|
||||
break;
|
||||
|
||||
case 31:
|
||||
case 32:
|
||||
case 33:
|
||||
case 34:
|
||||
door->type = vld_open;
|
||||
line->special = 0;
|
||||
break;
|
||||
|
||||
case 117: // blazing door raise
|
||||
door->type = vld_blazeRaise;
|
||||
door->speed = VDOORSPEED*4;
|
||||
break;
|
||||
case 118: // blazing door open
|
||||
door->type = vld_blazeOpen;
|
||||
line->special = 0;
|
||||
door->speed = VDOORSPEED*4;
|
||||
break;
|
||||
}
|
||||
|
||||
// find the top and bottom of the movement range
|
||||
door->topheight = P_FindLowestCeilingSurrounding(sec);
|
||||
door->topheight -= 4*FRACUNIT;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Spawn a door that closes after 30 seconds
|
||||
//
|
||||
void P_SpawnDoorCloseIn30 (sector_t* sec)
|
||||
{
|
||||
vldoor_t* door;
|
||||
|
||||
door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
|
||||
|
||||
P_AddThinker (&door->thinker);
|
||||
|
||||
sec->specialdata = door;
|
||||
sec->special = 0;
|
||||
|
||||
door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
|
||||
door->sector = sec;
|
||||
door->direction = 0;
|
||||
door->type = vld_normal;
|
||||
door->speed = VDOORSPEED;
|
||||
door->topcountdown = 30 * TICRATE;
|
||||
}
|
||||
|
||||
//
|
||||
// Spawn a door that opens after 5 minutes
|
||||
//
|
||||
void
|
||||
P_SpawnDoorRaiseIn5Mins
|
||||
( sector_t* sec,
|
||||
int secnum )
|
||||
{
|
||||
vldoor_t* door;
|
||||
|
||||
door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
|
||||
|
||||
P_AddThinker (&door->thinker);
|
||||
|
||||
sec->specialdata = door;
|
||||
sec->special = 0;
|
||||
|
||||
door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
|
||||
door->sector = sec;
|
||||
door->direction = 2;
|
||||
door->type = vld_raiseIn5Mins;
|
||||
door->speed = VDOORSPEED;
|
||||
door->topheight = P_FindLowestCeilingSurrounding(sec);
|
||||
door->topheight -= 4*FRACUNIT;
|
||||
door->topwait = VDOORWAIT;
|
||||
door->topcountdown = 5 * 60 * TICRATE;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,547 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Floor animation: raising stairs.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#include "z_zone.h"
|
||||
#include "doomdef.h"
|
||||
#include "p_local.h"
|
||||
|
||||
#include "s_sound.h"
|
||||
|
||||
// State.
|
||||
#include "doomstat.h"
|
||||
#include "r_state.h"
|
||||
// Data.
|
||||
#include "sounds.h"
|
||||
|
||||
|
||||
//
|
||||
// FLOORS
|
||||
//
|
||||
|
||||
//
|
||||
// Move a plane (floor or ceiling) and check for crushing
|
||||
//
|
||||
result_e
|
||||
T_MovePlane
|
||||
( sector_t* sector,
|
||||
fixed_t speed,
|
||||
fixed_t dest,
|
||||
boolean crush,
|
||||
int floorOrCeiling,
|
||||
int direction )
|
||||
{
|
||||
boolean flag;
|
||||
fixed_t lastpos;
|
||||
|
||||
switch(floorOrCeiling)
|
||||
{
|
||||
case 0:
|
||||
// FLOOR
|
||||
switch(direction)
|
||||
{
|
||||
case -1:
|
||||
// DOWN
|
||||
if (sector->floorheight - speed < dest)
|
||||
{
|
||||
lastpos = sector->floorheight;
|
||||
sector->floorheight = dest;
|
||||
flag = P_ChangeSector(sector,crush);
|
||||
if (flag == true)
|
||||
{
|
||||
sector->floorheight =lastpos;
|
||||
P_ChangeSector(sector,crush);
|
||||
//return crushed;
|
||||
}
|
||||
return pastdest;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastpos = sector->floorheight;
|
||||
sector->floorheight -= speed;
|
||||
flag = P_ChangeSector(sector,crush);
|
||||
if (flag == true)
|
||||
{
|
||||
sector->floorheight = lastpos;
|
||||
P_ChangeSector(sector,crush);
|
||||
return crushed;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// UP
|
||||
if (sector->floorheight + speed > dest)
|
||||
{
|
||||
lastpos = sector->floorheight;
|
||||
sector->floorheight = dest;
|
||||
flag = P_ChangeSector(sector,crush);
|
||||
if (flag == true)
|
||||
{
|
||||
sector->floorheight = lastpos;
|
||||
P_ChangeSector(sector,crush);
|
||||
//return crushed;
|
||||
}
|
||||
return pastdest;
|
||||
}
|
||||
else
|
||||
{
|
||||
// COULD GET CRUSHED
|
||||
lastpos = sector->floorheight;
|
||||
sector->floorheight += speed;
|
||||
flag = P_ChangeSector(sector,crush);
|
||||
if (flag == true)
|
||||
{
|
||||
if (crush == true)
|
||||
return crushed;
|
||||
sector->floorheight = lastpos;
|
||||
P_ChangeSector(sector,crush);
|
||||
return crushed;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// CEILING
|
||||
switch(direction)
|
||||
{
|
||||
case -1:
|
||||
// DOWN
|
||||
if (sector->ceilingheight - speed < dest)
|
||||
{
|
||||
lastpos = sector->ceilingheight;
|
||||
sector->ceilingheight = dest;
|
||||
flag = P_ChangeSector(sector,crush);
|
||||
|
||||
if (flag == true)
|
||||
{
|
||||
sector->ceilingheight = lastpos;
|
||||
P_ChangeSector(sector,crush);
|
||||
//return crushed;
|
||||
}
|
||||
return pastdest;
|
||||
}
|
||||
else
|
||||
{
|
||||
// COULD GET CRUSHED
|
||||
lastpos = sector->ceilingheight;
|
||||
sector->ceilingheight -= speed;
|
||||
flag = P_ChangeSector(sector,crush);
|
||||
|
||||
if (flag == true)
|
||||
{
|
||||
if (crush == true)
|
||||
return crushed;
|
||||
sector->ceilingheight = lastpos;
|
||||
P_ChangeSector(sector,crush);
|
||||
return crushed;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// UP
|
||||
if (sector->ceilingheight + speed > dest)
|
||||
{
|
||||
lastpos = sector->ceilingheight;
|
||||
sector->ceilingheight = dest;
|
||||
flag = P_ChangeSector(sector,crush);
|
||||
if (flag == true)
|
||||
{
|
||||
sector->ceilingheight = lastpos;
|
||||
P_ChangeSector(sector,crush);
|
||||
//return crushed;
|
||||
}
|
||||
return pastdest;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastpos = sector->ceilingheight;
|
||||
sector->ceilingheight += speed;
|
||||
flag = P_ChangeSector(sector,crush);
|
||||
// UNUSED
|
||||
#if 0
|
||||
if (flag == true)
|
||||
{
|
||||
sector->ceilingheight = lastpos;
|
||||
P_ChangeSector(sector,crush);
|
||||
return crushed;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN)
|
||||
//
|
||||
void T_MoveFloor(floormove_t* floor)
|
||||
{
|
||||
result_e res;
|
||||
|
||||
res = T_MovePlane(floor->sector,
|
||||
floor->speed,
|
||||
floor->floordestheight,
|
||||
floor->crush,0,floor->direction);
|
||||
|
||||
if (!(leveltime&7))
|
||||
S_StartSound(&floor->sector->soundorg, sfx_stnmov);
|
||||
|
||||
if (res == pastdest)
|
||||
{
|
||||
floor->sector->specialdata = NULL;
|
||||
|
||||
if (floor->direction == 1)
|
||||
{
|
||||
switch(floor->type)
|
||||
{
|
||||
case donutRaise:
|
||||
floor->sector->special = floor->newspecial;
|
||||
floor->sector->floorpic = floor->texture;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (floor->direction == -1)
|
||||
{
|
||||
switch(floor->type)
|
||||
{
|
||||
case lowerAndChange:
|
||||
floor->sector->special = floor->newspecial;
|
||||
floor->sector->floorpic = floor->texture;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
P_RemoveThinker(&floor->thinker);
|
||||
|
||||
S_StartSound(&floor->sector->soundorg, sfx_pstop);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// HANDLE FLOOR TYPES
|
||||
//
|
||||
int
|
||||
EV_DoFloor
|
||||
( line_t* line,
|
||||
floor_e floortype )
|
||||
{
|
||||
int secnum;
|
||||
int rtn;
|
||||
int i;
|
||||
sector_t* sec;
|
||||
floormove_t* floor;
|
||||
|
||||
secnum = -1;
|
||||
rtn = 0;
|
||||
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
|
||||
// ALREADY MOVING? IF SO, KEEP GOING...
|
||||
if (sec->specialdata)
|
||||
continue;
|
||||
|
||||
// new floor thinker
|
||||
rtn = 1;
|
||||
floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
|
||||
P_AddThinker (&floor->thinker);
|
||||
sec->specialdata = floor;
|
||||
floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
|
||||
floor->type = floortype;
|
||||
floor->crush = false;
|
||||
|
||||
switch(floortype)
|
||||
{
|
||||
case lowerFloor:
|
||||
floor->direction = -1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight =
|
||||
P_FindHighestFloorSurrounding(sec);
|
||||
break;
|
||||
|
||||
case lowerFloorToLowest:
|
||||
floor->direction = -1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight =
|
||||
P_FindLowestFloorSurrounding(sec);
|
||||
break;
|
||||
|
||||
case turboLower:
|
||||
floor->direction = -1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED * 4;
|
||||
floor->floordestheight =
|
||||
P_FindHighestFloorSurrounding(sec);
|
||||
if (floor->floordestheight != sec->floorheight)
|
||||
floor->floordestheight += 8*FRACUNIT;
|
||||
break;
|
||||
|
||||
case raiseFloorCrush:
|
||||
floor->crush = true;
|
||||
// fall through
|
||||
case raiseFloor:
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight =
|
||||
P_FindLowestCeilingSurrounding(sec);
|
||||
if (floor->floordestheight > sec->ceilingheight)
|
||||
floor->floordestheight = sec->ceilingheight;
|
||||
floor->floordestheight -= (8*FRACUNIT)*
|
||||
(floortype == raiseFloorCrush);
|
||||
break;
|
||||
|
||||
case raiseFloorTurbo:
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED*4;
|
||||
floor->floordestheight =
|
||||
P_FindNextHighestFloor(sec,sec->floorheight);
|
||||
break;
|
||||
|
||||
case raiseFloorToNearest:
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight =
|
||||
P_FindNextHighestFloor(sec,sec->floorheight);
|
||||
break;
|
||||
|
||||
case raiseFloor24:
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight = floor->sector->floorheight +
|
||||
24 * FRACUNIT;
|
||||
break;
|
||||
case raiseFloor512:
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight = floor->sector->floorheight +
|
||||
512 * FRACUNIT;
|
||||
break;
|
||||
|
||||
case raiseFloor24AndChange:
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight = floor->sector->floorheight +
|
||||
24 * FRACUNIT;
|
||||
sec->floorpic = line->frontsector->floorpic;
|
||||
sec->special = line->frontsector->special;
|
||||
break;
|
||||
|
||||
case raiseToTexture:
|
||||
{
|
||||
int minsize = INT_MAX;
|
||||
side_t* side;
|
||||
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
for (i = 0; i < sec->linecount; i++)
|
||||
{
|
||||
if (twoSided (secnum, i) )
|
||||
{
|
||||
side = getSide(secnum,i,0);
|
||||
if (side->bottomtexture >= 0)
|
||||
if (textureheight[side->bottomtexture] <
|
||||
minsize)
|
||||
minsize =
|
||||
textureheight[side->bottomtexture];
|
||||
side = getSide(secnum,i,1);
|
||||
if (side->bottomtexture >= 0)
|
||||
if (textureheight[side->bottomtexture] <
|
||||
minsize)
|
||||
minsize =
|
||||
textureheight[side->bottomtexture];
|
||||
}
|
||||
}
|
||||
floor->floordestheight =
|
||||
floor->sector->floorheight + minsize;
|
||||
}
|
||||
break;
|
||||
|
||||
case lowerAndChange:
|
||||
floor->direction = -1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight =
|
||||
P_FindLowestFloorSurrounding(sec);
|
||||
floor->texture = sec->floorpic;
|
||||
|
||||
for (i = 0; i < sec->linecount; i++)
|
||||
{
|
||||
if ( twoSided(secnum, i) )
|
||||
{
|
||||
if (getSide(secnum,i,0)->sector-sectors == secnum)
|
||||
{
|
||||
sec = getSector(secnum,i,1);
|
||||
|
||||
if (sec->floorheight == floor->floordestheight)
|
||||
{
|
||||
floor->texture = sec->floorpic;
|
||||
floor->newspecial = sec->special;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sec = getSector(secnum,i,0);
|
||||
|
||||
if (sec->floorheight == floor->floordestheight)
|
||||
{
|
||||
floor->texture = sec->floorpic;
|
||||
floor->newspecial = sec->special;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// BUILD A STAIRCASE!
|
||||
//
|
||||
int
|
||||
EV_BuildStairs
|
||||
( line_t* line,
|
||||
stair_e type )
|
||||
{
|
||||
int secnum;
|
||||
int height;
|
||||
int i;
|
||||
int newsecnum;
|
||||
int texture;
|
||||
int ok;
|
||||
int rtn;
|
||||
|
||||
sector_t* sec;
|
||||
sector_t* tsec;
|
||||
|
||||
floormove_t* floor;
|
||||
|
||||
fixed_t stairsize = 0;
|
||||
fixed_t speed = 0;
|
||||
|
||||
secnum = -1;
|
||||
rtn = 0;
|
||||
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
|
||||
// ALREADY MOVING? IF SO, KEEP GOING...
|
||||
if (sec->specialdata)
|
||||
continue;
|
||||
|
||||
// new floor thinker
|
||||
rtn = 1;
|
||||
floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
|
||||
P_AddThinker (&floor->thinker);
|
||||
sec->specialdata = floor;
|
||||
floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
switch(type)
|
||||
{
|
||||
case build8:
|
||||
speed = FLOORSPEED/4;
|
||||
stairsize = 8*FRACUNIT;
|
||||
break;
|
||||
case turbo16:
|
||||
speed = FLOORSPEED*4;
|
||||
stairsize = 16*FRACUNIT;
|
||||
break;
|
||||
}
|
||||
floor->speed = speed;
|
||||
height = sec->floorheight + stairsize;
|
||||
floor->floordestheight = height;
|
||||
|
||||
texture = sec->floorpic;
|
||||
|
||||
// Find next sector to raise
|
||||
// 1. Find 2-sided line with same sector side[0]
|
||||
// 2. Other side is the next sector to raise
|
||||
do
|
||||
{
|
||||
ok = 0;
|
||||
for (i = 0;i < sec->linecount;i++)
|
||||
{
|
||||
if ( !((sec->lines[i])->flags & ML_TWOSIDED) )
|
||||
continue;
|
||||
|
||||
tsec = (sec->lines[i])->frontsector;
|
||||
newsecnum = tsec-sectors;
|
||||
|
||||
if (secnum != newsecnum)
|
||||
continue;
|
||||
|
||||
tsec = (sec->lines[i])->backsector;
|
||||
newsecnum = tsec - sectors;
|
||||
|
||||
if (tsec->floorpic != texture)
|
||||
continue;
|
||||
|
||||
height += stairsize;
|
||||
|
||||
if (tsec->specialdata)
|
||||
continue;
|
||||
|
||||
sec = tsec;
|
||||
secnum = newsecnum;
|
||||
floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
|
||||
|
||||
P_AddThinker (&floor->thinker);
|
||||
|
||||
sec->specialdata = floor;
|
||||
floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = speed;
|
||||
floor->floordestheight = height;
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
} while(ok);
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
|
@ -0,0 +1,916 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Handling interactions (i.e., collisions).
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "dstrings.h"
|
||||
#include "sounds.h"
|
||||
|
||||
#include "doomstat.h"
|
||||
|
||||
#include "m_random.h"
|
||||
#include "i_system.h"
|
||||
|
||||
#include "am_map.h"
|
||||
|
||||
#include "p_local.h"
|
||||
|
||||
#include "s_sound.h"
|
||||
|
||||
#include "p_inter.h"
|
||||
|
||||
|
||||
#define BONUSADD 6
|
||||
|
||||
|
||||
|
||||
|
||||
// a weapon is found with two clip loads,
|
||||
// a big item has five clip loads
|
||||
int maxammo[NUMAMMO] = {200, 50, 300, 50};
|
||||
int clipammo[NUMAMMO] = {10, 4, 20, 1};
|
||||
|
||||
|
||||
//
|
||||
// GET STUFF
|
||||
//
|
||||
|
||||
//
|
||||
// P_GiveAmmo
|
||||
// Num is the number of clip loads,
|
||||
// not the individual count (0= 1/2 clip).
|
||||
// Returns false if the ammo can't be picked up at all
|
||||
//
|
||||
|
||||
boolean
|
||||
P_GiveAmmo
|
||||
( player_t* player,
|
||||
ammotype_t ammo,
|
||||
int num )
|
||||
{
|
||||
int oldammo;
|
||||
|
||||
if (ammo == am_noammo)
|
||||
return false;
|
||||
|
||||
if (ammo > NUMAMMO)
|
||||
I_Error ("P_GiveAmmo: bad type %i", ammo);
|
||||
|
||||
if ( player->ammo[ammo] == player->maxammo[ammo] )
|
||||
return false;
|
||||
|
||||
if (num)
|
||||
num *= clipammo[ammo];
|
||||
else
|
||||
num = clipammo[ammo]/2;
|
||||
|
||||
if (gameskill == sk_baby
|
||||
|| gameskill == sk_nightmare)
|
||||
{
|
||||
// give double ammo in trainer mode,
|
||||
// you'll need in nightmare
|
||||
num <<= 1;
|
||||
}
|
||||
|
||||
|
||||
oldammo = player->ammo[ammo];
|
||||
player->ammo[ammo] += num;
|
||||
|
||||
if (player->ammo[ammo] > player->maxammo[ammo])
|
||||
player->ammo[ammo] = player->maxammo[ammo];
|
||||
|
||||
// If non zero ammo,
|
||||
// don't change up weapons,
|
||||
// player was lower on purpose.
|
||||
if (oldammo)
|
||||
return true;
|
||||
|
||||
// We were down to zero,
|
||||
// so select a new weapon.
|
||||
// Preferences are not user selectable.
|
||||
switch (ammo)
|
||||
{
|
||||
case am_clip:
|
||||
if (player->readyweapon == wp_fist)
|
||||
{
|
||||
if (player->weaponowned[wp_chaingun])
|
||||
player->pendingweapon = wp_chaingun;
|
||||
else
|
||||
player->pendingweapon = wp_pistol;
|
||||
}
|
||||
break;
|
||||
|
||||
case am_shell:
|
||||
if (player->readyweapon == wp_fist
|
||||
|| player->readyweapon == wp_pistol)
|
||||
{
|
||||
if (player->weaponowned[wp_shotgun])
|
||||
player->pendingweapon = wp_shotgun;
|
||||
}
|
||||
break;
|
||||
|
||||
case am_cell:
|
||||
if (player->readyweapon == wp_fist
|
||||
|| player->readyweapon == wp_pistol)
|
||||
{
|
||||
if (player->weaponowned[wp_plasma])
|
||||
player->pendingweapon = wp_plasma;
|
||||
}
|
||||
break;
|
||||
|
||||
case am_misl:
|
||||
if (player->readyweapon == wp_fist)
|
||||
{
|
||||
if (player->weaponowned[wp_missile])
|
||||
player->pendingweapon = wp_missile;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_GiveWeapon
|
||||
// The weapon name may have a MF_DROPPED flag ored in.
|
||||
//
|
||||
boolean
|
||||
P_GiveWeapon
|
||||
( player_t* player,
|
||||
weapontype_t weapon,
|
||||
boolean dropped )
|
||||
{
|
||||
boolean gaveammo;
|
||||
boolean gaveweapon;
|
||||
|
||||
if (netgame && (deathmatch!=2) && !dropped )
|
||||
{
|
||||
// leave placed weapons forever on net games
|
||||
if (player->weaponowned[weapon])
|
||||
return false;
|
||||
|
||||
player->bonuscount += BONUSADD;
|
||||
player->weaponowned[weapon] = true;
|
||||
|
||||
if (deathmatch)
|
||||
P_GiveAmmo (player, weaponinfo[weapon].ammo, 5);
|
||||
else
|
||||
P_GiveAmmo (player, weaponinfo[weapon].ammo, 2);
|
||||
player->pendingweapon = weapon;
|
||||
|
||||
if (player == &players[consoleplayer])
|
||||
S_StartSound (NULL, sfx_wpnup);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (weaponinfo[weapon].ammo != am_noammo)
|
||||
{
|
||||
// give one clip with a dropped weapon,
|
||||
// two clips with a found weapon
|
||||
if (dropped)
|
||||
gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 1);
|
||||
else
|
||||
gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
gaveammo = false;
|
||||
}
|
||||
|
||||
if (player->weaponowned[weapon])
|
||||
{
|
||||
gaveweapon = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
gaveweapon = true;
|
||||
player->weaponowned[weapon] = true;
|
||||
player->pendingweapon = weapon;
|
||||
}
|
||||
|
||||
return (gaveweapon || gaveammo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// P_GiveBody
|
||||
// Returns false if the body isn't needed at all
|
||||
//
|
||||
boolean
|
||||
P_GiveBody
|
||||
( player_t* player,
|
||||
int num )
|
||||
{
|
||||
if (player->health >= MAXHEALTH)
|
||||
return false;
|
||||
|
||||
player->health += num;
|
||||
if (player->health > MAXHEALTH)
|
||||
player->health = MAXHEALTH;
|
||||
player->mo->health = player->health;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// P_GiveArmor
|
||||
// Returns false if the armor is worse
|
||||
// than the current armor.
|
||||
//
|
||||
boolean
|
||||
P_GiveArmor
|
||||
( player_t* player,
|
||||
int armortype )
|
||||
{
|
||||
int hits;
|
||||
|
||||
hits = armortype*100;
|
||||
if (player->armorpoints >= hits)
|
||||
return false; // don't pick up
|
||||
|
||||
player->armortype = armortype;
|
||||
player->armorpoints = hits;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// P_GiveCard
|
||||
//
|
||||
void
|
||||
P_GiveCard
|
||||
( player_t* player,
|
||||
card_t card )
|
||||
{
|
||||
if (player->cards[card])
|
||||
return;
|
||||
|
||||
player->bonuscount = BONUSADD;
|
||||
player->cards[card] = 1;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_GivePower
|
||||
//
|
||||
boolean
|
||||
P_GivePower
|
||||
( player_t* player,
|
||||
int /*powertype_t*/ power )
|
||||
{
|
||||
if (power == pw_invulnerability)
|
||||
{
|
||||
player->powers[power] = INVULNTICS;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (power == pw_invisibility)
|
||||
{
|
||||
player->powers[power] = INVISTICS;
|
||||
player->mo->flags |= MF_SHADOW;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (power == pw_infrared)
|
||||
{
|
||||
player->powers[power] = INFRATICS;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (power == pw_ironfeet)
|
||||
{
|
||||
player->powers[power] = IRONTICS;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (power == pw_strength)
|
||||
{
|
||||
P_GiveBody (player, 100);
|
||||
player->powers[power] = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player->powers[power])
|
||||
return false; // already got it
|
||||
|
||||
player->powers[power] = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// P_TouchSpecialThing
|
||||
//
|
||||
void
|
||||
P_TouchSpecialThing
|
||||
( mobj_t* special,
|
||||
mobj_t* toucher )
|
||||
{
|
||||
player_t* player;
|
||||
int i;
|
||||
fixed_t delta;
|
||||
int sound;
|
||||
|
||||
delta = special->z - toucher->z;
|
||||
|
||||
if (delta > toucher->height
|
||||
|| delta < -8*FRACUNIT)
|
||||
{
|
||||
// out of reach
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
sound = sfx_itemup;
|
||||
player = toucher->player;
|
||||
|
||||
// Dead thing touching.
|
||||
// Can happen with a sliding player corpse.
|
||||
if (toucher->health <= 0)
|
||||
return;
|
||||
|
||||
// Identify by sprite.
|
||||
switch (special->sprite)
|
||||
{
|
||||
// armor
|
||||
case SPR_ARM1:
|
||||
if (!P_GiveArmor (player, GREEN_ARMOR_CLASS))
|
||||
return;
|
||||
player->message = GOTARMOR;
|
||||
break;
|
||||
|
||||
case SPR_ARM2:
|
||||
if (!P_GiveArmor (player, BLUE_ARMOR_CLASS))
|
||||
return;
|
||||
player->message = GOTMEGA;
|
||||
break;
|
||||
|
||||
// bonus items
|
||||
case SPR_BON1:
|
||||
player->health++; // can go over 100%
|
||||
if (player->health > MAX_HEALTH)
|
||||
player->health = MAX_HEALTH;
|
||||
player->mo->health = player->health;
|
||||
player->message = GOTHTHBONUS;
|
||||
break;
|
||||
|
||||
case SPR_BON2:
|
||||
player->armorpoints++; // can go over 100%
|
||||
if (player->armorpoints > MAX_ARMOR)
|
||||
player->armorpoints = MAX_ARMOR;
|
||||
if (!player->armortype)
|
||||
player->armortype = 1;
|
||||
player->message = GOTARMBONUS;
|
||||
break;
|
||||
|
||||
case SPR_SOUL:
|
||||
player->health += SOULSPHERE_HEALTH;
|
||||
if (player->health > MAX_SOULSPHERE)
|
||||
player->health = MAX_SOULSPHERE;
|
||||
player->mo->health = player->health;
|
||||
player->message = GOTSUPER;
|
||||
sound = sfx_getpow;
|
||||
break;
|
||||
|
||||
case SPR_MEGA:
|
||||
if (gamemode != commercial)
|
||||
return;
|
||||
player->health = MEGASPHERE_HEALTH;
|
||||
player->mo->health = player->health;
|
||||
// We always give armor type 2 for the megasphere; dehacked only
|
||||
// affects the MegaArmor.
|
||||
P_GiveArmor (player, 2);
|
||||
player->message = GOTMSPHERE;
|
||||
sound = sfx_getpow;
|
||||
break;
|
||||
|
||||
// cards
|
||||
// leave cards for everyone
|
||||
case SPR_BKEY:
|
||||
if (!player->cards[it_bluecard])
|
||||
player->message = GOTBLUECARD;
|
||||
P_GiveCard (player, it_bluecard);
|
||||
if (!netgame)
|
||||
break;
|
||||
return;
|
||||
|
||||
case SPR_YKEY:
|
||||
if (!player->cards[it_yellowcard])
|
||||
player->message = GOTYELWCARD;
|
||||
P_GiveCard (player, it_yellowcard);
|
||||
if (!netgame)
|
||||
break;
|
||||
return;
|
||||
|
||||
case SPR_RKEY:
|
||||
if (!player->cards[it_redcard])
|
||||
player->message = GOTREDCARD;
|
||||
P_GiveCard (player, it_redcard);
|
||||
if (!netgame)
|
||||
break;
|
||||
return;
|
||||
|
||||
case SPR_BSKU:
|
||||
if (!player->cards[it_blueskull])
|
||||
player->message = GOTBLUESKUL;
|
||||
P_GiveCard (player, it_blueskull);
|
||||
if (!netgame)
|
||||
break;
|
||||
return;
|
||||
|
||||
case SPR_YSKU:
|
||||
if (!player->cards[it_yellowskull])
|
||||
player->message = GOTYELWSKUL;
|
||||
P_GiveCard (player, it_yellowskull);
|
||||
if (!netgame)
|
||||
break;
|
||||
return;
|
||||
|
||||
case SPR_RSKU:
|
||||
if (!player->cards[it_redskull])
|
||||
player->message = GOTREDSKULL;
|
||||
P_GiveCard (player, it_redskull);
|
||||
if (!netgame)
|
||||
break;
|
||||
return;
|
||||
|
||||
// medikits, heals
|
||||
case SPR_STIM:
|
||||
if (!P_GiveBody (player, 10))
|
||||
return;
|
||||
player->message = GOTSTIM;
|
||||
break;
|
||||
|
||||
case SPR_MEDI:
|
||||
if (!P_GiveBody (player, 25))
|
||||
return;
|
||||
|
||||
if (player->health < 25)
|
||||
player->message = GOTMEDINEED;
|
||||
else
|
||||
player->message = GOTMEDIKIT;
|
||||
break;
|
||||
|
||||
|
||||
// power ups
|
||||
case SPR_PINV:
|
||||
if (!P_GivePower (player, pw_invulnerability))
|
||||
return;
|
||||
player->message = GOTINVUL;
|
||||
sound = sfx_getpow;
|
||||
break;
|
||||
|
||||
case SPR_PSTR:
|
||||
if (!P_GivePower (player, pw_strength))
|
||||
return;
|
||||
player->message = GOTBERSERK;
|
||||
if (player->readyweapon != wp_fist)
|
||||
player->pendingweapon = wp_fist;
|
||||
sound = sfx_getpow;
|
||||
break;
|
||||
|
||||
case SPR_PINS:
|
||||
if (!P_GivePower (player, pw_invisibility))
|
||||
return;
|
||||
player->message = GOTINVIS;
|
||||
sound = sfx_getpow;
|
||||
break;
|
||||
|
||||
case SPR_SUIT:
|
||||
if (!P_GivePower (player, pw_ironfeet))
|
||||
return;
|
||||
player->message = GOTSUIT;
|
||||
sound = sfx_getpow;
|
||||
break;
|
||||
|
||||
case SPR_PMAP:
|
||||
if (!P_GivePower (player, pw_allmap))
|
||||
return;
|
||||
player->message = GOTMAP;
|
||||
sound = sfx_getpow;
|
||||
break;
|
||||
|
||||
case SPR_PVIS:
|
||||
if (!P_GivePower (player, pw_infrared))
|
||||
return;
|
||||
player->message = GOTVISOR;
|
||||
sound = sfx_getpow;
|
||||
break;
|
||||
|
||||
// ammo
|
||||
case SPR_CLIP:
|
||||
if (special->flags & MF_DROPPED)
|
||||
{
|
||||
if (!P_GiveAmmo (player,am_clip,0))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!P_GiveAmmo (player,am_clip,1))
|
||||
return;
|
||||
}
|
||||
player->message = GOTCLIP;
|
||||
break;
|
||||
|
||||
case SPR_AMMO:
|
||||
if (!P_GiveAmmo (player, am_clip,5))
|
||||
return;
|
||||
player->message = GOTCLIPBOX;
|
||||
break;
|
||||
|
||||
case SPR_ROCK:
|
||||
if (!P_GiveAmmo (player, am_misl,1))
|
||||
return;
|
||||
player->message = GOTROCKET;
|
||||
break;
|
||||
|
||||
case SPR_BROK:
|
||||
if (!P_GiveAmmo (player, am_misl,5))
|
||||
return;
|
||||
player->message = GOTROCKBOX;
|
||||
break;
|
||||
|
||||
case SPR_CELL:
|
||||
if (!P_GiveAmmo (player, am_cell,1))
|
||||
return;
|
||||
player->message = GOTCELL;
|
||||
break;
|
||||
|
||||
case SPR_CELP:
|
||||
if (!P_GiveAmmo (player, am_cell,5))
|
||||
return;
|
||||
player->message = GOTCELLBOX;
|
||||
break;
|
||||
|
||||
case SPR_SHEL:
|
||||
if (!P_GiveAmmo (player, am_shell,1))
|
||||
return;
|
||||
player->message = GOTSHELLS;
|
||||
break;
|
||||
|
||||
case SPR_SBOX:
|
||||
if (!P_GiveAmmo (player, am_shell,5))
|
||||
return;
|
||||
player->message = GOTSHELLBOX;
|
||||
break;
|
||||
|
||||
case SPR_BPAK:
|
||||
if (!player->backpack)
|
||||
{
|
||||
for (i=0 ; i<NUMAMMO ; i++)
|
||||
player->maxammo[i] *= 2;
|
||||
player->backpack = true;
|
||||
}
|
||||
for (i=0 ; i<NUMAMMO ; i++)
|
||||
P_GiveAmmo (player, i, 1);
|
||||
player->message = GOTBACKPACK;
|
||||
break;
|
||||
|
||||
// weapons
|
||||
case SPR_BFUG:
|
||||
if (!P_GiveWeapon (player, wp_bfg, false) )
|
||||
return;
|
||||
player->message = GOTBFG9000;
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
|
||||
case SPR_MGUN:
|
||||
if (!P_GiveWeapon (player, wp_chaingun, (special->flags&MF_DROPPED) != 0) )
|
||||
return;
|
||||
player->message = GOTCHAINGUN;
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
|
||||
case SPR_CSAW:
|
||||
if (!P_GiveWeapon (player, wp_chainsaw, false) )
|
||||
return;
|
||||
player->message = GOTCHAINSAW;
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
|
||||
case SPR_LAUN:
|
||||
if (!P_GiveWeapon (player, wp_missile, false) )
|
||||
return;
|
||||
player->message = GOTLAUNCHER;
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
|
||||
case SPR_PLAS:
|
||||
if (!P_GiveWeapon (player, wp_plasma, false) )
|
||||
return;
|
||||
player->message = GOTPLASMA;
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
|
||||
case SPR_SHOT:
|
||||
if (!P_GiveWeapon (player, wp_shotgun, (special->flags&MF_DROPPED) != 0 ) )
|
||||
return;
|
||||
player->message = GOTSHOTGUN;
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
|
||||
case SPR_SGN2:
|
||||
if (!P_GiveWeapon (player, wp_supershotgun, (special->flags&MF_DROPPED) != 0 ) )
|
||||
return;
|
||||
player->message = GOTSHOTGUN2;
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
|
||||
default:
|
||||
I_Error ("P_SpecialThing: Unknown gettable thing");
|
||||
}
|
||||
|
||||
if (special->flags & MF_COUNTITEM)
|
||||
player->itemcount++;
|
||||
P_RemoveMobj (special);
|
||||
player->bonuscount += BONUSADD;
|
||||
if (player == &players[consoleplayer])
|
||||
S_StartSound (NULL, sound);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// KillMobj
|
||||
//
|
||||
void
|
||||
P_KillMobj
|
||||
( mobj_t* source,
|
||||
mobj_t* target )
|
||||
{
|
||||
mobjtype_t item;
|
||||
mobj_t* mo;
|
||||
|
||||
target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY);
|
||||
|
||||
if (target->type != MT_SKULL)
|
||||
target->flags &= ~MF_NOGRAVITY;
|
||||
|
||||
target->flags |= MF_CORPSE|MF_DROPOFF;
|
||||
target->height >>= 2;
|
||||
|
||||
if (source && source->player)
|
||||
{
|
||||
// count for intermission
|
||||
if (target->flags & MF_COUNTKILL)
|
||||
source->player->killcount++;
|
||||
|
||||
if (target->player)
|
||||
source->player->frags[target->player-players]++;
|
||||
}
|
||||
else if (!netgame && (target->flags & MF_COUNTKILL) )
|
||||
{
|
||||
// count all monster deaths,
|
||||
// even those caused by other monsters
|
||||
players[0].killcount++;
|
||||
}
|
||||
|
||||
if (target->player)
|
||||
{
|
||||
// count environment kills against you
|
||||
if (!source)
|
||||
target->player->frags[target->player-players]++;
|
||||
|
||||
target->flags &= ~MF_SOLID;
|
||||
target->player->playerstate = PST_DEAD;
|
||||
P_DropWeapon (target->player);
|
||||
|
||||
if (target->player == &players[consoleplayer]
|
||||
&& automapactive)
|
||||
{
|
||||
// don't die in auto map,
|
||||
// switch view prior to dying
|
||||
AM_Stop ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (target->health < -target->info->spawnhealth
|
||||
&& target->info->xdeathstate)
|
||||
{
|
||||
P_SetMobjState (target, target->info->xdeathstate);
|
||||
}
|
||||
else
|
||||
P_SetMobjState (target, target->info->deathstate);
|
||||
target->tics -= P_Random()&3;
|
||||
|
||||
if (target->tics < 1)
|
||||
target->tics = 1;
|
||||
|
||||
// I_StartSound (&actor->r, actor->info->deathsound);
|
||||
|
||||
// In Chex Quest, monsters don't drop items.
|
||||
|
||||
if (gameversion == exe_chex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Drop stuff.
|
||||
// This determines the kind of object spawned
|
||||
// during the death frame of a thing.
|
||||
switch (target->type)
|
||||
{
|
||||
case MT_WOLFSS:
|
||||
case MT_POSSESSED:
|
||||
item = MT_CLIP;
|
||||
break;
|
||||
|
||||
case MT_SHOTGUY:
|
||||
item = MT_SHOTGUN;
|
||||
break;
|
||||
|
||||
case MT_CHAINGUY:
|
||||
item = MT_CHAINGUN;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
mo = P_SpawnMobj (target->x,target->y,ONFLOORZ, item);
|
||||
mo->flags |= MF_DROPPED; // special versions of items
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// P_DamageMobj
|
||||
// Damages both enemies and players
|
||||
// "inflictor" is the thing that caused the damage
|
||||
// creature or missile, can be NULL (slime, etc)
|
||||
// "source" is the thing to target after taking damage
|
||||
// creature or NULL
|
||||
// Source and inflictor are the same for melee attacks.
|
||||
// Source can be NULL for slime, barrel explosions
|
||||
// and other environmental stuff.
|
||||
//
|
||||
void
|
||||
P_DamageMobj
|
||||
( mobj_t* target,
|
||||
mobj_t* inflictor,
|
||||
mobj_t* source,
|
||||
int damage )
|
||||
{
|
||||
unsigned ang;
|
||||
int saved;
|
||||
player_t* player;
|
||||
fixed_t thrust;
|
||||
int temp;
|
||||
|
||||
if ( !(target->flags & MF_SHOOTABLE) )
|
||||
return; // shouldn't happen...
|
||||
|
||||
if (target->health <= 0)
|
||||
return;
|
||||
|
||||
if ( target->flags & MF_SKULLFLY )
|
||||
{
|
||||
target->momx = target->momy = target->momz = 0;
|
||||
}
|
||||
|
||||
player = target->player;
|
||||
if (player && gameskill == sk_baby)
|
||||
damage >>= 1; // take half damage in trainer mode
|
||||
|
||||
|
||||
// Some close combat weapons should not
|
||||
// inflict thrust and push the victim out of reach,
|
||||
// thus kick away unless using the chainsaw.
|
||||
if (inflictor
|
||||
&& !(target->flags & MF_NOCLIP)
|
||||
&& (!source
|
||||
|| !source->player
|
||||
|| source->player->readyweapon != wp_chainsaw))
|
||||
{
|
||||
ang = R_PointToAngle2 ( inflictor->x,
|
||||
inflictor->y,
|
||||
target->x,
|
||||
target->y);
|
||||
|
||||
thrust = damage*(FRACUNIT>>3)*100/target->info->mass;
|
||||
|
||||
// make fall forwards sometimes
|
||||
if ( damage < 40
|
||||
&& damage > target->health
|
||||
&& target->z - inflictor->z > 64*FRACUNIT
|
||||
&& (P_Random ()&1) )
|
||||
{
|
||||
ang += ANG180;
|
||||
thrust *= 4;
|
||||
}
|
||||
|
||||
ang >>= ANGLETOFINESHIFT;
|
||||
target->momx += FixedMul (thrust, finecosine[ang]);
|
||||
target->momy += FixedMul (thrust, finesine[ang]);
|
||||
}
|
||||
|
||||
// player specific
|
||||
if (player)
|
||||
{
|
||||
// end of game hell hack
|
||||
if (target->subsector->sector->special == 11
|
||||
&& damage >= target->health)
|
||||
{
|
||||
damage = target->health - 1;
|
||||
}
|
||||
|
||||
|
||||
// Below certain threshold,
|
||||
// ignore damage in GOD mode, or with INVUL power.
|
||||
if ( damage < 1000
|
||||
&& ( (player->cheats&CF_GODMODE)
|
||||
|| player->powers[pw_invulnerability] ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->armortype)
|
||||
{
|
||||
if (player->armortype == 1)
|
||||
saved = damage/3;
|
||||
else
|
||||
saved = damage/2;
|
||||
|
||||
if (player->armorpoints <= saved)
|
||||
{
|
||||
// armor is used up
|
||||
saved = player->armorpoints;
|
||||
player->armortype = 0;
|
||||
}
|
||||
player->armorpoints -= saved;
|
||||
damage -= saved;
|
||||
}
|
||||
player->health -= damage; // mirror mobj health here for Dave
|
||||
if (player->health < 0)
|
||||
player->health = 0;
|
||||
|
||||
player->attacker = source;
|
||||
player->damagecount += damage; // add damage after armor / invuln
|
||||
|
||||
if (player->damagecount > 100)
|
||||
player->damagecount = 100; // teleport stomp does 10k points...
|
||||
|
||||
temp = damage < 100 ? damage : 100;
|
||||
|
||||
if (player == &players[consoleplayer])
|
||||
I_Tactile (40,10,40+temp*2);
|
||||
}
|
||||
|
||||
// do the damage
|
||||
target->health -= damage;
|
||||
if (target->health <= 0)
|
||||
{
|
||||
P_KillMobj (source, target);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (P_Random () < target->info->painchance)
|
||||
&& !(target->flags&MF_SKULLFLY) )
|
||||
{
|
||||
target->flags |= MF_JUSTHIT; // fight back!
|
||||
|
||||
P_SetMobjState (target, target->info->painstate);
|
||||
}
|
||||
|
||||
target->reactiontime = 0; // we're awake now...
|
||||
|
||||
if ( (!target->threshold || target->type == MT_VILE)
|
||||
&& source && source != target
|
||||
&& source->type != MT_VILE)
|
||||
{
|
||||
// if not intent on another player,
|
||||
// chase after this one
|
||||
target->target = source;
|
||||
target->threshold = BASETHRESHOLD;
|
||||
if (target->state == &states[target->info->spawnstate]
|
||||
&& target->info->seestate != S_NULL)
|
||||
P_SetMobjState (target, target->info->seestate);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
#ifndef __P_INTER__
|
||||
#define __P_INTER__
|
||||
|
||||
|
||||
|
||||
|
||||
boolean P_GivePower(player_t*, int);
|
||||
|
||||
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue