Skip to content

Commit

Permalink
Add cncsig() ordinal and tests (#338)
Browse files Browse the repository at this point in the history
* Add cncsig() ordinal and tests

* formatting

* formatting

* Added better logic on SIGIDC

* Update Test, failing

* Added test for nxtcmdoffset
  • Loading branch information
tuday2 committed Dec 24, 2020
1 parent 6aeb160 commit 9098378
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 1 deletion.
50 changes: 50 additions & 0 deletions MBBSEmu.Tests/ExportedModules/Majorbbs/cncsig_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using MBBSEmu.Memory;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace MBBSEmu.Tests.ExportedModules.Majorbbs
{
public class cncsig_Tests : ExportedModuleTestBase
{
private const int CNCSIG_ORDINAL = 128;

[Theory]
[InlineData("FIRST SECOND\0", 0, "/FIRST", 6, "SECOND")]
[InlineData("FIRST SECOND\0", 6, "/SECOND", 13, "")]
[InlineData("FIRST SECOND THIRD\0", 1, "/IRST", 6, "SECOND THIRD")]
[InlineData("FIRST SECOND THIRD\0", 13, "/THIRD", 19, "")]
[InlineData(" /MyUser\0", 0, "/MyUser", 9, "")]
[InlineData("/MyUser\0", 0, "/MyUser", 8, "")]
[InlineData("/MyUserNameIsTooLong\0", 0, "/MyUserNa", 9, "meIsTooLong")]
[InlineData("123456789012345678901234567890\0", 0, "/12345678", 8, "9012345678901234567890")]
[InlineData("\0", 0, "", 0, "")]
public void cncsig_Test(string inputString, ushort nxtcmdStartingOffset, string expectedResult, ushort expectedNxtcmdOffset, string expectedNxtcmdRemaining)
{
//Reset State
Reset();

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

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

//Set nxtcmd
var currentNxtcmd = mbbsEmuMemoryCore.GetPointer("NXTCMD");
currentNxtcmd.Offset += nxtcmdStartingOffset;
mbbsEmuMemoryCore.SetPointer("NXTCMD", currentNxtcmd);

//Execute Test
ExecuteApiTest(HostProcess.ExportedModules.Majorbbs.Segment, CNCSIG_ORDINAL, new List<IntPtr16>());

//Verify Results
var expectedResultPointer = mbbsEmuMemoryCore.GetVariablePointer("INPUT");

expectedResultPointer.Offset += expectedNxtcmdOffset;
Assert.Equal(expectedNxtcmdRemaining, Encoding.ASCII.GetString(mbbsEmuMemoryCore.GetString(mbbsEmuMemoryCore.GetPointer("NXTCMD"),true )));
Assert.Equal(expectedResult, Encoding.ASCII.GetString(mbbsEmuMemoryCore.GetString(mbbsEmuCpuCore.Registers.DX, mbbsEmuCpuCore.Registers.AX, true)));
Assert.Equal(expectedResultPointer, mbbsEmuMemoryCore.GetPointer("NXTCMD"));
}
}
}
85 changes: 84 additions & 1 deletion MBBSEmu/HostProcess/ExportedModules/Majorbbs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,9 @@ public ReadOnlySpan<byte> Invoke(ushort ordinal, bool offsetsOnly = false)
case 64:
alcdup();
break;
case 128:
cncsig();
break;
default:
_logger.Error($"Unknown Exported Function Ordinal in MAJORBBS: {ordinal}:{Ordinals.MAJORBBS[ordinal]}");
throw new ArgumentOutOfRangeException($"Unknown Exported Function Ordinal in MAJORBBS: {ordinal}:{Ordinals.MAJORBBS[ordinal]}");
Expand Down Expand Up @@ -7265,7 +7268,7 @@ private void gen_haskey()
/// <summary>
/// Expect a Word from the user (character from the current command)
///
/// cncwrd() is executed after begincnc(), which runs rstrin() replacing the null separtors
/// cncwrd() is executed after begincnc(), which runs rstrin() replacing the null separators
/// in the string with spaces once again.
/// </summary>
private void cncwrd()
Expand Down Expand Up @@ -7648,5 +7651,85 @@ private void alcdup()

Registers.SetPointer(destinationAllocatedPointer);
}

/// <summary>
/// Expect a forum name, with or without '/' prefix
///
/// Signature: char *signam=cncsig();
/// </summary>
private void cncsig()
{
//Get Input
var inputPointer = Module.Memory.GetVariablePointer("INPUT");
var nxtcmdPointer = Module.Memory.GetPointer("NXTCMD");
var inputLength = Module.Memory.GetWord("INPLEN");

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

//Skip any excessive spacing
while (Module.Memory.GetByte(nxtcmdPointer) == ' ' && remainingCharactersInCommand > 0)
{
nxtcmdPointer.Offset++;
remainingCharactersInCommand--;
}
var returnPointer = Module.Memory.GetOrAllocateVariablePointer("CNCSIG", 0xA); //max length is 10 characters
Registers.SetPointer(returnPointer);

//Verify we're not at the end of the input
if (remainingCharactersInCommand == 0 || Module.Memory.GetByte(nxtcmdPointer) == 0)
{
//Write null to output
Module.Memory.SetByte(returnPointer, 0);
return;
}

var inputString = Module.Memory.GetArray(nxtcmdPointer, (ushort)remainingCharactersInCommand);

//Make room for leading forward slash (SIGIDC) if missing
if (inputString[0] != (byte) '/')
remainingCharactersInCommand += 1;

var returnedSig = new MemoryStream(remainingCharactersInCommand);

//Add leading forward slash (SIGIDC) if missing
if (inputString[0] != (byte) '/')
{
returnedSig.WriteByte((byte) '/');
nxtcmdPointer--;
}

//Build Return Sig stopping when a space is encountered
foreach (var b in inputString)
{
if (b == ' ' || b == 0)
break;

returnedSig.WriteByte(b);
}

//Truncate to 9 bytes
if (returnedSig.Length > 9)
{
returnedSig.SetLength(9);
nxtcmdPointer--;
}

returnedSig.WriteByte(0);

Module.Memory.SetArray(returnPointer, returnedSig.ToArray());

//Modify the Counters
remainingCharactersInCommand -= (int)returnedSig.Length;
nxtcmdPointer.Offset += (ushort)returnedSig.Length;

//Advance to the next, non-space character
while (Module.Memory.GetByte(nxtcmdPointer) == ' ' && remainingCharactersInCommand > 0)
{
nxtcmdPointer.Offset++;
remainingCharactersInCommand--;
}

Module.Memory.SetPointer("NXTCMD", new IntPtr16(nxtcmdPointer.Segment, (ushort)(nxtcmdPointer.Offset)));
}
}
}

0 comments on commit 9098378

Please sign in to comment.