Skip to content

Commit 126048b

Browse files
committed
Added other missing bits
1 parent 3bfbe21 commit 126048b

13 files changed

Lines changed: 469 additions & 48 deletions

File tree

src/DoomSharp.Core/DoomGame.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,8 +1096,8 @@ private void ArbitrateNetStart()
10961096
return;
10971097
}
10981098

1099-
StartSkill = (SkillLevel)(netBuffer.RetransmitFrom & 15);
1100-
_game.DeathMatch = ((netBuffer.RetransmitFrom & 0xc0) >> 6) != 0;
1099+
StartSkill = (SkillLevel)(netBuffer.RetransmitFrom & 15);
1100+
_game.DeathMatch = (netBuffer.RetransmitFrom & 0xc0) >> 6;
11011101
var nomonsters = (netBuffer.RetransmitFrom & 0x20) > 0;
11021102
var respawnparm = (netBuffer.RetransmitFrom & 0x10) > 0;
11031103
StartMap = netBuffer.StartTic & 0x3f;
@@ -1119,9 +1119,9 @@ private void ArbitrateNetStart()
11191119
for (i = 0; i < _network.DoomCom.NumNodes; i++)
11201120
{
11211121
netBuffer.RetransmitFrom = (byte)StartSkill;
1122-
if (_game.DeathMatch)
1122+
if (_game.DeathMatch != 0)
11231123
{
1124-
netBuffer.RetransmitFrom |= (byte)((_game.DeathMatch ? 1 : 0) << 6);
1124+
netBuffer.RetransmitFrom |= (byte)(_game.DeathMatch << 6);
11251125
}
11261126
//if (nomonsters)
11271127
// netbuffer->retransmitfrom |= 0x20;
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
namespace DoomSharp.Core.GameLogic;
2+
3+
/// <summary>
4+
/// Cheat sequence checking - port of m_cheat.c from the original DOOM source.
5+
/// Uses the SCRAMBLE bit-shuffling algorithm to encode cheat sequences.
6+
/// </summary>
7+
public class CheatSequence
8+
{
9+
private static bool _firstTime = true;
10+
private static readonly byte[] CheatXlateTable = new byte[256];
11+
12+
private readonly byte[] _sequence;
13+
private int _position;
14+
15+
/// <summary>
16+
/// Create a cheat sequence from a plaintext string.
17+
/// The string is encoded using the SCRAMBLE algorithm.
18+
/// Use '\x01' as a placeholder for parameter characters (digits typed by user).
19+
/// Use no special suffix for sequences without parameters.
20+
/// </summary>
21+
public CheatSequence(string cheatString)
22+
{
23+
// Encode the cheat string using SCRAMBLE, then add 0xff terminator
24+
// Parameter placeholder bytes (0x01) are kept as-is
25+
_sequence = new byte[cheatString.Length + 1];
26+
for (var i = 0; i < cheatString.Length; i++)
27+
{
28+
var c = (byte)cheatString[i];
29+
_sequence[i] = c == 0x01 ? c : Scramble(c);
30+
}
31+
_sequence[cheatString.Length] = 0xff; // end marker
32+
33+
_position = 0;
34+
}
35+
36+
/// <summary>
37+
/// The SCRAMBLE macro from the original source - shuffles bits of a byte.
38+
/// </summary>
39+
private static byte Scramble(int a)
40+
{
41+
return (byte)(
42+
((a & 1) << 7) +
43+
((a & 2) << 5) +
44+
(a & 4) +
45+
((a & 8) << 1) +
46+
((a & 16) >> 1) +
47+
(a & 32) +
48+
((a & 64) >> 5) +
49+
((a & 128) >> 7)
50+
);
51+
}
52+
53+
/// <summary>
54+
/// Check if the given key advances or completes the cheat sequence.
55+
/// Returns true if the full cheat has been entered.
56+
/// Port of cht_CheckCheat from m_cheat.c.
57+
/// </summary>
58+
public bool CheckCheat(char key)
59+
{
60+
if (_firstTime)
61+
{
62+
_firstTime = false;
63+
for (var i = 0; i < 256; i++)
64+
{
65+
CheatXlateTable[i] = Scramble(i);
66+
}
67+
}
68+
69+
if (_sequence[_position] == 0)
70+
{
71+
// Parameter position - store the raw key
72+
_sequence[_position] = (byte)key;
73+
_position++;
74+
}
75+
else if (CheatXlateTable[(byte)key] == _sequence[_position])
76+
{
77+
_position++;
78+
}
79+
else
80+
{
81+
_position = 0;
82+
}
83+
84+
if (_sequence[_position] == 1)
85+
{
86+
// Hit a parameter marker - advance past it
87+
_position++;
88+
}
89+
else if (_sequence[_position] == 0xff)
90+
{
91+
// Completed the sequence
92+
_position = 0;
93+
return true;
94+
}
95+
96+
return false;
97+
}
98+
99+
/// <summary>
100+
/// Extract parameter characters that were captured during sequence entry.
101+
/// Port of cht_GetParam from m_cheat.c.
102+
/// </summary>
103+
public void GetParam(char[] buffer)
104+
{
105+
var p = 0;
106+
107+
// Skip past the encoded prefix to find the parameter bytes
108+
// In the sequence, parameters were originally 0x01 markers that got
109+
// replaced with 0x00 (zeroed) then filled with user keystrokes
110+
// Find the first 0x01 in the original sequence (which is now after the encoded chars)
111+
while (_sequence[p] != 1)
112+
{
113+
p++;
114+
}
115+
116+
// Skip the 0x01 marker
117+
p++;
118+
119+
// Copy parameter bytes into the buffer and zero them out
120+
var bufIdx = 0;
121+
do
122+
{
123+
var c = _sequence[p];
124+
buffer[bufIdx] = (char)c;
125+
_sequence[p] = 0;
126+
bufIdx++;
127+
p++;
128+
} while (buffer[bufIdx - 1] != 0 && _sequence[p] != 0xff);
129+
130+
if (_sequence[p] == 0xff)
131+
{
132+
buffer[bufIdx] = '\0';
133+
}
134+
}
135+
}

src/DoomSharp.Core/GameLogic/GameController.cs

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ public class GameController
3838

3939
private int _keyUp = (int)Keys.UpArrow;
4040
private int _keyDown = (int)Keys.DownArrow;
41-
private int _keyStrafeLeft = 'A';
42-
private int _keyStrafeRight = 'D';
43-
private int _keyFire = ' ';
44-
private int _keyUse = (int)Keys.Enter;
45-
private int _keyStrafe = (int)Keys.LAlt;
41+
private int _keyStrafeLeft = ',';
42+
private int _keyStrafeRight = '.';
43+
private int _keyFire = (int)Keys.RCtrl;
44+
private int _keyUse = ' ';
45+
private int _keyStrafe = (int)Keys.RAlt;
4646
private int _keySpeed = (int)Keys.RShift;
4747

4848
private int _mouseButtonFire = 0;
@@ -230,6 +230,7 @@ public GameController()
230230

231231
public SkillLevel GameSkill { get; set; }
232232
public bool RespawnMonsters { get; set; }
233+
public bool RespawnParm { get; set; }
233234
public bool FastParm { get; set; }
234235
public bool NoMonsters { get; set; }
235236
public int GameEpisode { get; set; }
@@ -247,7 +248,7 @@ public GameController()
247248

248249
public bool ViewActive { get; set; }
249250

250-
public bool DeathMatch { get; set; }
251+
public int DeathMatch { get; set; }
251252
public bool NetGame { get; set; } = false;
252253
public bool[] PlayerInGame { get; } = new bool[Constants.MaxPlayers];
253254
public Player[] Players { get; } = new Player[Constants.MaxPlayers];
@@ -615,7 +616,7 @@ private void DoReborn(int player)
615616
Players[player].MapObject!.Player = null;
616617

617618
// spawn at random spot if in death match
618-
if (DeathMatch)
619+
if (DeathMatch != 0)
619620
{
620621
DeathMatchSpawnPlayer(player);
621622
return;
@@ -664,8 +665,9 @@ private void DoPlayDemo()
664665
var skill = (SkillLevel)_demoData[_demoDataIdx++];
665666
var episode = _demoData[_demoDataIdx++];
666667
var map = _demoData[_demoDataIdx++];
667-
DeathMatch = _demoData[_demoDataIdx++] != 0;
668+
DeathMatch = _demoData[_demoDataIdx++];
668669
var respawnparm = _demoData[_demoDataIdx++] != 0;
670+
RespawnParm = respawnparm;
669671
FastParm = _demoData[_demoDataIdx++] != 0;
670672
NoMonsters = _demoData[_demoDataIdx++] != 0;
671673
ConsolePlayer = _demoData[_demoDataIdx++];
@@ -702,11 +704,11 @@ public void DoNewGame()
702704
DemoPlayback = false;
703705
NetDemo = false;
704706
NetGame = false;
705-
DeathMatch = false;
707+
DeathMatch = 0;
706708
PlayerInGame[1] = PlayerInGame[2] = PlayerInGame[3] = false;
707-
//respawnparm = false;
708-
//fastparm = false;
709-
//nomonsters = false;
709+
RespawnParm = false;
710+
FastParm = false;
711+
NoMonsters = false;
710712
ConsolePlayer = 0;
711713
InitNew(_d_skill, _d_episode, _d_map);
712714
GameAction = GameAction.Nothing;
@@ -762,7 +764,7 @@ public void InitNew(SkillLevel skill, int episode, int map)
762764

763765
DoomRandom.ClearRandom();
764766

765-
if (skill == SkillLevel.Nightmare || RespawnMonsters)
767+
if (skill == SkillLevel.Nightmare || RespawnParm)
766768
RespawnMonsters = true;
767769
else
768770
RespawnMonsters = false;
@@ -898,7 +900,7 @@ private void BeginRecording()
898900
_demoData[_demoDataIdx++] = (byte)GameSkill;
899901
_demoData[_demoDataIdx++] = (byte)GameEpisode;
900902
_demoData[_demoDataIdx++] = (byte)GameMap;
901-
_demoData[_demoDataIdx++] = (byte)(DeathMatch ? 1 : 0);
903+
_demoData[_demoDataIdx++] = (byte)DeathMatch;
902904
_demoData[_demoDataIdx++] = 0; // respawnparam
903905
_demoData[_demoDataIdx++] = 0; // fastparm;
904906
_demoData[_demoDataIdx++] = 0; // nomonsters;
@@ -1005,11 +1007,11 @@ public bool CheckDemoStatus()
10051007
DemoPlayback = false;
10061008
NetDemo = false;
10071009
NetGame = false;
1008-
DeathMatch = false;
1010+
DeathMatch = 0;
10091011
PlayerInGame[1] = PlayerInGame[2] = PlayerInGame[3] = false;
1010-
//respawnparm = false;
1011-
//fastparm = false;
1012-
//nomonsters = false;
1012+
RespawnParm = false;
1013+
FastParm = false;
1014+
NoMonsters = false;
10131015
ConsolePlayer = 0;
10141016
DoomGame.Instance.AdvanceDemo();
10151017
return true;
@@ -1112,8 +1114,8 @@ public void P_Ticker()
11121114

11131115
private void RespawnSpecials()
11141116
{
1115-
// only respawn items in deathmatch
1116-
if (!DeathMatch)
1117+
// only respawn items in deathmatch 2 (altdeath)
1118+
if (DeathMatch != 2)
11171119
{
11181120
return;
11191121
}
@@ -1423,7 +1425,7 @@ private void P_SpawnPlayer(MapThing mthing)
14231425
P_SetupPlayerSprites(p);
14241426

14251427
// give all cards in death match mode
1426-
if (DeathMatch)
1428+
if (DeathMatch != 0)
14271429
{
14281430
for (i = 0; i < (int)KeyCardType.NumberOfKeyCards; i++)
14291431
{
@@ -1661,7 +1663,7 @@ private void P_SpawnMapThing(MapThing mapThing)
16611663
{
16621664
// save spots for respawning in network games
16631665
_playerStarts[mapThing.Type - 1] = mapThing;
1664-
if (!DeathMatch)
1666+
if (DeathMatch == 0)
16651667
{
16661668
P_SpawnPlayer(mapThing);
16671669
}
@@ -1696,7 +1698,7 @@ private void P_SpawnMapThing(MapThing mapThing)
16961698
}
16971699

16981700
// don't spawn keycards and players in deathmatch
1699-
if (DeathMatch && (moInfo.Value.Flags & MapObjectFlag.MF_NOTDMATCH) != 0)
1701+
if (DeathMatch != 0 && (moInfo.Value.Flags & MapObjectFlag.MF_NOTDMATCH) != 0)
17001702
{
17011703
return;
17021704
}
@@ -4053,7 +4055,7 @@ private void SetupLevel(int episode, int map, int playerMask, SkillLevel skillLe
40534055
P_LoadThings(lumpNum + MapLumps.Things);
40544056

40554057
// if deathmatch, randomly spawn the active players
4056-
if (DeathMatch)
4058+
if (DeathMatch != 0)
40574059
{
40584060
for (var i = 0; i < Constants.MaxPlayers; i++)
40594061
{
@@ -5704,7 +5706,7 @@ public bool HandleEvent(InputEvent currentEvent)
57045706
if (GameState == GameState.Level &&
57055707
currentEvent.Type == EventType.KeyDown &&
57065708
currentEvent.Data1 == (int)Keys.F12 &&
5707-
(SingleDemo || !DeathMatch))
5709+
(SingleDemo || DeathMatch == 0))
57085710
{
57095711
// spy mode
57105712
do

src/DoomSharp.Core/GameLogic/Player.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,7 @@ public bool GiveAmmo(AmmoType ammo, int num)
663663
public bool GiveWeapon(WeaponType weapon, bool dropped)
664664
{
665665
var game = DoomGame.Instance.Game;
666-
if (game.NetGame && game.DeathMatch && !dropped)
666+
if (game.NetGame && game.DeathMatch != 2 && !dropped)
667667
{
668668
// leave placed weapons forever on net games
669669
if (WeaponOwned[(int)weapon])
@@ -674,7 +674,7 @@ public bool GiveWeapon(WeaponType weapon, bool dropped)
674674
BonusCount += GameController.BonusAdd;
675675
WeaponOwned[(int)weapon] = true;
676676

677-
if (game.DeathMatch)
677+
if (game.DeathMatch != 0)
678678
{
679679
GiveAmmo(WeaponInfo.GetByType(weapon).Ammo, 5);
680680
}

src/DoomSharp.Core/GameLogic/State.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ private static void ActionSaw(ActionParams actionParams)
344344
DoomGame.Instance.Sound.StartSound(player.MapObject, SoundType.sfx_sawhit);
345345

346346
// turn to face target
347-
player.MapObject.Angle = DoomGame.Instance.Renderer.PointToAngle2(
347+
angle = DoomGame.Instance.Renderer.PointToAngle2(
348348
player.MapObject.X,
349349
player.MapObject.Y,
350350
lineTarget.X,

src/DoomSharp.Core/GameLogic/Trigger.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,8 +1351,11 @@ public static bool DonutEvent(Line line)
13511351
var s2 = s1.Lines[0].GetNextSector(s1)!;
13521352
for (var i = 0; i < s2.LineCount; i++)
13531353
{
1354-
if ((s2.Lines[i].Flags & Constants.Line.TwoSided) == 0 ||
1355-
s2.Lines[i].BackSector == s1)
1354+
// NOTE: Original C code has a bug here: (!s2->lines[i]->flags & ML_TWOSIDED)
1355+
// Due to C operator precedence, ! binds tighter than &, so this evaluates as
1356+
// ((!flags) & ML_TWOSIDED) which is always false for non-zero flags.
1357+
// We replicate the vanilla bug for demo compatibility by omitting the two-sided check.
1358+
if (s2.Lines[i].BackSector == s1)
13561359
{
13571360
continue;
13581361
}

src/DoomSharp.Core/Networking/DoomCommunication.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class DoomCommunication
2626
// Flag: 1 = send a backup tic in every packet.
2727
public short ExtraTics { get; set; }
2828
// Flag: 1 = deathmatch.
29-
public bool DeathMatch { get; set; }
29+
public short DeathMatch { get; set; }
3030
// Flag: -1 = new game, 0-5 = load savegame
3131
public short SaveGame { get; set; }
3232
public short Episode { get; set; } // 1-3

src/DoomSharp.Core/Networking/NetworkController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public void Initialize()
1313
DoomGame.Instance.Game.NetGame = false;
1414
DoomCom.Id = Constants.DoomComId;
1515
DoomCom.NumPlayers = DoomCom.NumNodes = 1;
16-
DoomCom.DeathMatch = false;
16+
DoomCom.DeathMatch = 0;
1717
DoomCom.ConsolePlayer = 0;
1818

1919
// when multiplayer: setup netsend/netget functions

src/DoomSharp.Core/UI/HudController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ public bool HandleEvent(InputEvent currentEvent)
436436
{
437437
_messageOn = true;
438438
_messageCounter = MessageTimeout;
439-
return true;
439+
return true; // eat the key, matching original HU_Responder
440440
}
441441

442442
return false;

0 commit comments

Comments
 (0)