Skip to content

Commit

Permalink
Merge pull request #594 from mbbsemu/stpans-implementation
Browse files Browse the repository at this point in the history
STPANS Implementation
  • Loading branch information
paladine authored Nov 6, 2023
2 parents e0cec17 + b3cbce1 commit 1284426
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 17 deletions.
49 changes: 49 additions & 0 deletions MBBSEmu.Tests/ExportedModules/Majorbbs/stpans_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using MBBSEmu.Memory;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace MBBSEmu.Tests.ExportedModules.Majorbbs
{
public class stpans_Tests : ExportedModuleTestBase
{
private const int STPANS_ORDINAL = 712;

[Theory]
[InlineData("\u001b[31mRed Text\u001b[0m", "Red Text")]
[InlineData("\u001b[31;1mBold Red Text\u001b[22;39m", "Bold Red Text")]
[InlineData("\u001b[31;44mRed on Blue\u001b[0m Text", "Red on Blue Text")]
[InlineData("Normal \u001b[33mYellow Text\u001b[0m", "Normal Yellow Text")]
[InlineData("\u001b[32mGreen\u001b[0m\u001b[33mYellow\u001b[0m", "GreenYellow")]
[InlineData("No Color Here", "No Color Here")]
[InlineData("\u001b[31m\u001b[32mNested \u001b[33mColors\u001b[0m", "Nested Colors")]
[InlineData("\u001b[0;31;51;101mComplex \u001b[0mText", "Complex Text")]
[InlineData("\u001b[1A", "")] // Cursor up
[InlineData("\u001b[2J", "")] // Clear screen
[InlineData("Text\u001b[0K", "Text")] // Clear line from cursor right
[InlineData("\u001b[7mReverse\u001b[27m", "Reverse")] // Reverse video on and off
[InlineData("\u001b]0;Title\u0007", "")] // OSC (Operating System Command) to set window title
[InlineData("\u001b[?25h", "")] // Show cursor
[InlineData("\u001b[?25l", "")] // Hide cursor
[InlineData("Normal Text\u001b[10CAfter Tab", "Normal TextAfter Tab")] // Move cursor forward 10 spaces
[InlineData("123456789\u001b[3D", "123456789")] // Move cursor back 3 spaces
[InlineData("Start\u001b[s\u001b[uEnd", "StartEnd")] // Save cursor position and restore it
public void STPANS_Test(string inputString, string expectedString)
{
//Reset State
Reset();

//Set Argument Values to be Passed In
var stringPointer = mbbsEmuMemoryCore.AllocateVariable("INPUT_STRING", (ushort)(inputString.Length + 1));
mbbsEmuMemoryCore.SetArray("INPUT_STRING", Encoding.ASCII.GetBytes(inputString));

//Execute Test
ExecuteApiTest(HostProcess.ExportedModules.Majorbbs.Segment, STPANS_ORDINAL, new List<FarPtr> { stringPointer });

//Verify Results
Assert.Equal(expectedString,
Encoding.ASCII.GetString(
mbbsEmuMemoryCore.GetString(mbbsEmuCpuRegisters.GetPointer(), true)));
}
}
}
4 changes: 2 additions & 2 deletions MBBSEmu.Tests/MBBSEmu.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
<PackageReference Include="Iced" Version="1.10.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
<PackageReference Include="xunit" Version="2.5.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.1">
<PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
83 changes: 68 additions & 15 deletions MBBSEmu/HostProcess/ExportedModules/Majorbbs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2348,7 +2348,7 @@ private void rand()
{
uint multiplier = 0x15A4E35;
var seed = Module.Memory.GetDWord("RANDSEED");

var newSeed = (seed * multiplier) + 1;

Module.Memory.SetDWord("RANDSEED", newSeed);
Expand Down Expand Up @@ -3850,17 +3850,21 @@ private enum ScanfParseState
PERCENT
};

private struct ScanfState {
private struct ScanfState
{
private ScanfParseState _scanfParseState = ScanfParseState.NORMAL;

public ScanfState() {
public ScanfState()
{
Length = 0;
IsLongInteger = false;
}

public ScanfParseState State {
public ScanfParseState State
{
get => _scanfParseState;
set {
set
{
_scanfParseState = value;
Length = 0;
IsLongInteger = false;
Expand Down Expand Up @@ -3944,7 +3948,8 @@ private void scanf(IEnumerator<char> input, string formatString, int startingPar
var defaultLength = (formatChar == 's') ? int.MaxValue : 1;
var length = parseState.Length > 0 ? parseState.Length : defaultLength;
var count = 0;
(var stringValue, moreInput) = ReadString(input, c => {
(var stringValue, moreInput) = ReadString(input, c =>
{
return (count++ < length) ?
ExportedModuleBase.CharacterAccepterResponse.ACCEPT :
ExportedModuleBase.CharacterAccepterResponse.ABORT;
Expand All @@ -3956,7 +3961,7 @@ private void scanf(IEnumerator<char> input, string formatString, int startingPar
if (stringValue.Length > 0)
++matches;
if (formatChar == 's') // null terminate
Module.Memory.SetByte(destinationPtr + stringValue.Length, 0);
Module.Memory.SetByte(destinationPtr + stringValue.Length, 0);

startingParameterOrdinal += 2;
parseState.State = ScanfParseState.NORMAL;
Expand Down Expand Up @@ -5039,23 +5044,71 @@ private void xlttxv()
private void stpans()
{
var stringToStripPointer = GetParameterPointer(0);
var stringToStrip = Module.Memory.GetString(stringToStripPointer);
var inputString = Module.Memory.GetString(stringToStripPointer);

var ansiFound = false;
foreach (var t in stringToStrip)
Module.Memory.GetOrAllocateVariablePointer("STPANS", 1920); //Max Screen Size of 80x24

if (inputString.Length > 1920)
{
if (t == 0x1B)
ansiFound = true;
_logger.Warn(
$"String to Strip is larger than 1920 bytes, truncating to 1920 bytes as to not overflow buffer");
inputString = inputString.Slice(0, 1920);
}

//Declare Return
var cleanedStringBuilder = new StringBuilder(1920);

for (int i = 0; i < inputString.Length;)
{
if (inputString[i] == '\x1b') // Start of an escape sequence
{
i++; // Increment to skip the escape character

// Check if it's a CSI sequence which starts with '['
if (i < inputString.Length && inputString[i] == '[')
{
i++; // Skip the '['
// Skip the parameters and intermediate bytes
while (i < inputString.Length && inputString[i] > 0x1F && inputString[i] < 0x40)
{
i++;
}
// Now skip the final byte
if (i < inputString.Length && inputString[i] >= 0x40 && inputString[i] <= 0x7E)
{
i++;
}
}
// Check if it's an OSC sequence which starts with ']'
else if (i < inputString.Length && inputString[i] == ']')
{
i++; // Skip the ']'
// OSC sequence ends with BEL (0x07)
while (i < inputString.Length && inputString[i] != 0x07)
{
i++;
}
if (i < inputString.Length) // Check to avoid IndexOutOfRangeException
{
i++; // Skip the BEL character
}
}
}
else if (i < inputString.Length) // Check to avoid IndexOutOfRangeException
{
// Regular character, append it
cleanedStringBuilder.Append((char)inputString[i]);
i++;
}
}

if (ansiFound)
_logger.Warn($"({Module.ModuleIdentifier}) ANSI found but was not stripped. Process not implemented.");
Module.Memory.SetArray("STPANS", Encoding.ASCII.GetBytes(cleanedStringBuilder.ToString()));

#if DEBUG
_logger.Debug($"({Module.ModuleIdentifier}) Ignoring, not stripping ANSI");
#endif

Registers.SetPointer(stringToStripPointer);
Registers.SetPointer(Module.Memory.GetVariablePointer("STPANS"));
}

/// <summary>
Expand Down

0 comments on commit 1284426

Please sign in to comment.