Skip to content

Commit

Permalink
Input fixes for MMUD (#525)
Browse files Browse the repository at this point in the history
* Input fixes for MMUD

Push polling status & then pop it during poll routine

Ignore TransparentMode when handling \r on input

Fix line break crash related to backspace/deletes

* Add \r to the input stream while in CYCLE but don't trigger STTROU

Co-authored-by: Eric P. Nusbaum <eric@enusbaum.com>
  • Loading branch information
paladine and enusbaum committed Jan 2, 2022
1 parent e95eb35 commit 656887c
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 21 deletions.
2 changes: 1 addition & 1 deletion MBBSEmu.Tests/ExportedModules/Majorbbs/cncall_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public void cncall_Test(string inputString, ushort nxtcmdStartingOffset, string
Reset();

//Set Input Values
var inputLength = (ushort)inputString.Length;
var inputLength = (ushort) (inputString.Length - 1);

mbbsModule.Memory.SetArray("INPUT", Encoding.ASCII.GetBytes(inputString));
mbbsModule.Memory.SetWord("INPLEN", inputLength);
Expand Down
9 changes: 4 additions & 5 deletions MBBSEmu.Tests/ExportedModules/Majorbbs/endcnc_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ public class endcnc_Tests : ExportedModuleTestBase
{
private const int ENDCNC_ORDINAL = 191;

[Theory]

//Simple commands with nxtcmd == input
[Theory]
[InlineData("123 ABC\0", 1, 0, "23\0ABC\0", 2)]
[InlineData("123 ABC\0", 3, 0, "ABC\0", 1)]
[InlineData("123 ABC\0", 4, 0, "ABC\0", 1)]
[InlineData("123 ABC\0", 5, 0, "BC\0", 1)]
[InlineData("\0", 0, 1, "", 0)]
[InlineData("\0", 0, 1, "\0", 0)]
public void endcnc_Test(string inputString, ushort nxtcmdStartingOffset, char expectedResult, string expectedInputString, ushort expectedMargc)
{
//Reset State
Expand All @@ -26,7 +25,7 @@ public void endcnc_Test(string inputString, ushort nxtcmdStartingOffset, char ex
var inputLength = (ushort)inputString.Length;

mbbsModule.Memory.SetArray("INPUT", Encoding.ASCII.GetBytes(inputString));
mbbsModule.Memory.SetWord("INPLEN", inputLength);
mbbsModule.Memory.SetWord("INPLEN", (ushort) (inputLength - 1));

//Set nxtcmd
var currentNxtcmd = mbbsEmuMemoryCore.GetPointer("NXTCMD");
Expand All @@ -38,7 +37,7 @@ public void endcnc_Test(string inputString, ushort nxtcmdStartingOffset, char ex

//Gather Results
var actualResult = mbbsEmuCpuCore.Registers.AX;
var actualInputString = Encoding.ASCII.GetString(mbbsEmuMemoryCore.GetArray("INPUT", mbbsEmuMemoryCore.GetWord("INPLEN")));
var actualInputString = Encoding.ASCII.GetString(mbbsEmuMemoryCore.GetArray("INPUT", (ushort) (mbbsEmuMemoryCore.GetWord("INPLEN") + 1)));
var actualMargc = mbbsEmuMemoryCore.GetWord("MARGC");
//Verify Results
Assert.Equal(expectedInputString, actualInputString);
Expand Down
2 changes: 1 addition & 1 deletion MBBSEmu.Tests/ExportedModules/Majorbbs/rstrin_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public void rstrin_Test(string inputCommand)

//Set Input Values
mbbsEmuMemoryCore.SetArray("INPUT", Encoding.ASCII.GetBytes(inputCommand));
mbbsEmuMemoryCore.SetWord("INPLEN", (ushort)inputCommand.Length);
mbbsEmuMemoryCore.SetWord("INPLEN", (ushort) (inputCommand.Length - 1));

ExecuteApiTest(HostProcess.ExportedModules.Majorbbs.Segment, RSTRIN_ORDINAL, new List<FarPtr>());

Expand Down
38 changes: 29 additions & 9 deletions MBBSEmu/HostProcess/ExportedModules/Majorbbs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -370,20 +370,19 @@ public void ProcessChannelInput(ushort channelNumber)
var inputPointer = Module.Memory.GetVariablePointer("INPUT");
Module.Memory.SetZero(inputPointer, 0xFF);
var inputFromChannel = ChannelDictionary[channelNumber].InputCommand;
var inputLength = (ushort)ChannelDictionary[ChannelNumber].InputCommand.Length;
var inputLength = (ushort)(ChannelDictionary[ChannelNumber].InputCommand.Length - 1);
Module.Memory.SetArray(inputPointer, inputFromChannel);
Module.Memory.SetByte(inputPointer + inputFromChannel.Length, 0);
Module.Memory.SetWord("INPLEN", inputLength);
inputLength = setINPLEN(inputPointer);

ChannelDictionary[channelNumber].UsrPtr.Flags = 0;

parsin();

//Set Concex flag on 0 input
//TODO -- Need to verify this is correct
if (Module.Memory.GetWord("INPLEN") == 0)
if (inputLength == 0)
ChannelDictionary[channelNumber].UsrPtr.Flags |= (uint)EnumRuntimeFlags.Concex;

}

/// <summary>
Expand Down Expand Up @@ -3717,7 +3716,7 @@ private void rstrin()
if (inputLength == 0)
return;

for (var i = inputPointer.Offset; i < inputPointer.Offset + (inputLength - 1); i++)
for (var i = inputPointer.Offset; i < inputPointer.Offset + inputLength; i++)
{
if (Module.Memory.GetByte(inputPointer.Segment, i) == 0)
Module.Memory.SetByte(inputPointer.Segment, i, (byte)' ');
Expand Down Expand Up @@ -4289,9 +4288,10 @@ private void parsin()
margvPointer.Offset += FarPtr.Size;

}
Module.Memory.SetWord("INPLEN", (ushort)parsedInput.Length);

Module.Memory.SetArray("INPUT", Encoding.ASCII.GetBytes(parsedInput));
Module.Memory.SetWord("MARGC", margCount);
//setINPLEN();
}

/// <summary>
Expand Down Expand Up @@ -5577,7 +5577,7 @@ private void endcnc()
var nxtcmdPointer = Module.Memory.GetPointer("NXTCMD");
var inputLength = Module.Memory.GetWord("INPLEN");

var remainingCharactersInCommand = inputLength - (nxtcmdPointer.Offset - inputPointer.Offset);
var remainingCharactersInCommand = inputLength - (nxtcmdPointer.Offset - inputPointer.Offset) + 1;

//Check to see if nxtcmd is on a space, if so, increment it by 1
if (Module.Memory.GetByte(nxtcmdPointer) == 0x20)
Expand All @@ -5595,7 +5595,7 @@ private void endcnc()
//Get Remaining Characters & Save to Input
var remainingInput = Module.Memory.GetArray(nxtcmdPointer, (ushort)(remainingCharactersInCommand));
Module.Memory.SetArray(inputPointer, remainingInput);
Module.Memory.SetWord("INPLEN", (ushort)remainingCharactersInCommand);
setINPLEN(inputPointer);
Module.Memory.SetPointer("NXTCMD", inputPointer);
parsin();

Expand Down Expand Up @@ -5647,7 +5647,7 @@ private void cncall()
Registers.SetPointer(nxtcmdPointer);

//Set NXTCMD to the end of the INPUT
var newNxtcmd = new FarPtr(inputPointer.Segment, (ushort)(inputPointer.Offset + inputLength - 1));
var newNxtcmd = new FarPtr(inputPointer.Segment, (ushort)(inputPointer.Offset + inputLength));
Module.Memory.SetPointer("NXTCMD", newNxtcmd);
}

Expand Down Expand Up @@ -8243,5 +8243,25 @@ private void cncuid()
//Sets DX:AX registers to the return value
Registers.SetPointer(returnPointer);
}

/// <summary>
/// Sets the INPLEN variable based on the length of INPUT
/// </summary>
/// <returns>The value written to INPLEN</returns>
private ushort setINPLEN() => setINPLEN(Module.Memory.GetVariablePointer("INPUT"));

/// <summary>
/// Sets the INPLEN variable based on the length of the string from input
/// </summary>
/// <param name="input">Null-terminated string pointer</param>
/// <returns>The value written to INPLEN</returns>
private ushort setINPLEN(FarPtr input)
{
var sz = (ushort) Module.Memory.GetString(input, true).Length;

Module.Memory.SetWord("INPLEN", sz);

return sz;
}
}
}
16 changes: 11 additions & 5 deletions MBBSEmu/HostProcess/MbbsHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -356,11 +356,9 @@ private void WorkerThread()
//If the channel has been registered with BEGIN_POLLING
if (session.PollingRoutine != null)
{
session.Status.Enqueue(EnumUserStatus.POLLING_STATUS);
ProcessPollingRoutine(session);

//Keep the user in Polling Status if the polling routine is still there
if (session.PollingRoutine != FarPtr.Empty)
session.Status.Enqueue(EnumUserStatus.POLLING_STATUS);
session.Status.Dequeue();
}

break;
Expand Down Expand Up @@ -852,7 +850,7 @@ private void ProcessIncomingCharacter(SessionBase session)
}

//Enter or Return
case 0xD when !session.TransparentMode && (session.SessionState != EnumSessionState.InFullScreenDisplay && session.SessionState != EnumSessionState.InFullScreenEditor):
case 0xD when (session.SessionState != EnumSessionState.InFullScreenDisplay && session.SessionState != EnumSessionState.InFullScreenEditor):
{
//If we're in transparent mode or BTUCHI has changed the character to null, don't echo
if (!session.TransparentMode && session.CharacterProcessed > 0)
Expand All @@ -861,6 +859,13 @@ private void ProcessIncomingCharacter(SessionBase session)
//If BTUCHI Injected a deferred Execution Status, respect that vs. processing the input
if (session.GetStatus() == EnumUserStatus.CYCLE)
{
//If we're cycling, ignore \r for triggering STTROU and add it to the input buffer for STSROU to handle
if (session.TransparentMode)
{
session.InputBuffer.WriteByte(session.CharacterProcessed);
break;
}

//Set Status == 3, which means there is a Command Ready
session.Status.Clear(); //Clear the 240
session.Status.Enqueue(EnumUserStatus.CR_TERMINATED_STRING_AVAILABLE); //Enqueue Status of 3
Expand All @@ -870,6 +875,7 @@ private void ProcessIncomingCharacter(SessionBase session)

//Always Enqueue Input Ready
session.Status.Enqueue(EnumUserStatus.CR_TERMINATED_STRING_AVAILABLE);

break;
}

Expand Down
6 changes: 6 additions & 0 deletions MBBSEmu/Session/LineBreaker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ namespace MBBSEmu.Session
{
public class LineBreaker
{
public const byte BACKSPACE = 8;
public const byte DELETE = 127;
public const byte ESCAPE = 0x1B;
public const int MAX_LINE = 512;
public const int MAX_OUTPUT_BUFFER = 4096;
Expand Down Expand Up @@ -124,8 +126,12 @@ public void SendBreakingIntoLines(byte[] buffer)
case ESCAPE: // escape
_parseState = ParseState.ESCAPE;
break;
case DELETE: // ignore
case (byte) '\n': // ignore
break;
case BACKSPACE:
_lineBufferLength = Math.Max(0, _lineBufferLength - 1);
break;
default:
_lineBuffer[_lineBufferLength] = b;
_lineBufferToRawBuffer[_lineBufferLength++] = _rawBufferLength - 1;
Expand Down

0 comments on commit 656887c

Please sign in to comment.