From 90983781274ef340c24e24f02d25e1a0387783d7 Mon Sep 17 00:00:00 2001 From: Jonathan Sider Date: Wed, 23 Dec 2020 20:57:58 -0600 Subject: [PATCH] Add cncsig() ordinal and tests (#338) * Add cncsig() ordinal and tests * formatting * formatting * Added better logic on SIGIDC * Update Test, failing * Added test for nxtcmdoffset --- .../ExportedModules/Majorbbs/cncsig_Tests.cs | 50 +++++++++++ .../HostProcess/ExportedModules/Majorbbs.cs | 85 ++++++++++++++++++- 2 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 MBBSEmu.Tests/ExportedModules/Majorbbs/cncsig_Tests.cs diff --git a/MBBSEmu.Tests/ExportedModules/Majorbbs/cncsig_Tests.cs b/MBBSEmu.Tests/ExportedModules/Majorbbs/cncsig_Tests.cs new file mode 100644 index 00000000..8adde854 --- /dev/null +++ b/MBBSEmu.Tests/ExportedModules/Majorbbs/cncsig_Tests.cs @@ -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()); + + //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")); + } + } +} diff --git a/MBBSEmu/HostProcess/ExportedModules/Majorbbs.cs b/MBBSEmu/HostProcess/ExportedModules/Majorbbs.cs index f864819c..5bd66c74 100644 --- a/MBBSEmu/HostProcess/ExportedModules/Majorbbs.cs +++ b/MBBSEmu/HostProcess/ExportedModules/Majorbbs.cs @@ -1249,6 +1249,9 @@ public ReadOnlySpan 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]}"); @@ -7265,7 +7268,7 @@ private void gen_haskey() /// /// 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. /// private void cncwrd() @@ -7648,5 +7651,85 @@ private void alcdup() Registers.SetPointer(destinationAllocatedPointer); } + + /// + /// Expect a forum name, with or without '/' prefix + /// + /// Signature: char *signam=cncsig(); + /// + 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))); + } } }