Skip to content

Commit

Permalink
Add Int 7b skeleton + stop using instruction cache on EXEs (#471)
Browse files Browse the repository at this point in the history
* Int21h Refactor to use Blocking Collection

* Refactoring EXERuntime to use LocalConsoleSession

* ExeRuntime refactored to use LocalConsoleSession

- Sets up ability to host EXE's through rlogin, Telnet, etc.
- `fgets()` working from EXE, `scanf()` still returning after 1st character

* Temporary checkin

* Add assertion on env length

* Additional Interrupts for INT 10h

* Added INT 10h Comments

* Added Clear Screen/Cursor Position APIs to INT 10h

* Cleanup INT 21h for Console Input

* Add CMDLINE.EXE integration test

* Fix lodsb/lodsw

* Fix build issues post-merge

* Post Merge Fixes

* Add IStream interface and implements around stdin,out,err

* Stop the SessionBase in ExeRuntime when done

* Helps to actually store the sessionBase when passed in ...

* Add TODO for in/out, small fix for Int21 07h

* Start investigating PIT

* Implement basic PIT

* Implement a non-elegant interrupt routine

* Add PIT tests

* Remove unused interrupt execution code in CpuCore

* Support retf + argument to modify SP

* Add std support

* Implement dos int21 CreateFile

Also added support for Btrieve interrupt, which is int 123 and has an
interrupt offset of 0x33

* Convert DOS paths -> System paths

* var

* Create a skeleton for Btrieve int 7b.

Stop using instruction cache for EXEs

* Function to => thingee

Co-authored-by: Eric Nusbaum <eric@enusbaum.com>
  • Loading branch information
paladine and enusbaum committed Apr 10, 2021
1 parent 1f9ad5c commit daaa079
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 20 deletions.
1 change: 1 addition & 0 deletions MBBSEmu/DOS/ExeRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public ExeRuntime(MZFile file, IClock clock, ILogger logger, IFileUtility fileUt
new Int1Ah(Registers, Memory, clock),
new Int3Eh(),
new Int10h(Registers, _logger, stdout),
new Int7Bh(_logger, Registers, Memory),
},
new Dictionary<int, IIOPort>
{
Expand Down
6 changes: 3 additions & 3 deletions MBBSEmu/DOS/Interrupts/Int21h.cs
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ private void SetInterruptVector_0x25()
_memory.SetPointer(ptr, newVectorPointer);
}

_logger.Info($"Set interrupt vector {interruptVector} at {ptr} to {newVectorPointer}");
_logger.Debug($"Set interrupt vector {interruptVector} at {ptr} to {newVectorPointer}");
}

private void GetCurrentDate_0x2A()
Expand Down Expand Up @@ -877,14 +877,14 @@ private void CloseFile_0x3E()

var fileHandle = Registers.BX;

_logger.Debug($"Closing file {fileHandle}");

if (!_fileHandles.TryGetValue(fileHandle, out var fileStream))
{
SetCarryFlagErrorCodeInAX(DOSErrorCode.INVALID_HANDLE);
return;
}

_logger.Debug($"Closing file {fileHandle}");

_fileHandles.Remove(fileHandle);

fileStream.Close();
Expand Down
110 changes: 110 additions & 0 deletions MBBSEmu/DOS/Interrupts/Int7Bh.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
using MBBSEmu.CPU;
using MBBSEmu.Memory;
using NLog;
using System;
using System.Runtime.InteropServices;

namespace MBBSEmu.DOS.Interrupts
{
public enum BtrieveError
{
Success = 0,
InvalidOperation = 1,
IOError = 2,
FileNotOpen = 3,
KeyValueNotFound = 4,
DuplicateKeyValue = 5,
InvalidKeyNumber = 6,
DifferentKeyNumber = 7,
InvalidPositioning = 8,
EOF = 9 ,
}

// https://docs.actian.com/psql/psqlv13/index.html#page/btrieveapi/btrintro.htm
// http://www.nomad.ee/btrieve/errors/index.shtml

/// <summary>
/// Btrieve interrupt handler
/// </summary>
public class Int7Bh : IInterruptHandler
{
private readonly ILogger _logger;
private readonly IMemoryCore _memory;
private readonly ICpuRegisters _registers;

public byte Vector => 0x7B;


protected struct BtrieveCommand
{
public ushort data_buffer_offset;
public ushort data_buffer_segment;

public ushort data_buffer_length;

public ushort position_block_offset;
public ushort position_block_segment;

public ushort fcb_offset;
public ushort fcb_segment;

public ushort operation;

public ushort key_buffer_offset;
public ushort key_buffer_segment;

public byte key_buffer_length;

public byte key_number;

public ushort status_code_pointer_offset;
public ushort status_code_pointer_segment;

public ushort interface_id; // should always be 0x6176

public void Log(ILogger logger)
{
/*foreach (var c in memory)
{
_logger.Error($"Byte: {c:X2}");
}*/


logger.Error($"DataBufferSegment: {new FarPtr(data_buffer_segment, data_buffer_offset)}:{data_buffer_length}");
logger.Error($"PosBlock: {new FarPtr(position_block_segment, position_block_offset)}");
logger.Error($"FCB: {new FarPtr(fcb_segment, fcb_offset)}");
logger.Error($"Operation: {operation}");
logger.Error($"KeyBuffer: {new FarPtr(key_buffer_segment, key_buffer_offset)}:{key_buffer_length}");
}
}

public Int7Bh(ILogger logger, ICpuRegisters registers, IMemoryCore memory)
{
_logger = logger;
_registers = registers;
_memory = memory;
}

public void Handle()
{
// DS:DX is argument
var data = ByteArrayToStructure<BtrieveCommand>(_memory.GetArray(_registers.DS, _registers.DX, 28).ToArray());
data.Log(_logger);

if (data.interface_id != 0x6176)
throw new ArgumentException($"Bad interface_id");

_memory.SetWord(data.status_code_pointer_segment, data.status_code_pointer_offset, (ushort)BtrieveError.FileNotOpen);
//_registers.CarryFlag = true;
//throw new ArgumentException($"Btrieve operation {data.operation}");
}

unsafe T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
fixed (byte* ptr = &bytes[0])
{
return (T)Marshal.PtrToStructure((IntPtr)ptr, typeof(T));
}
}
}
}
46 changes: 29 additions & 17 deletions MBBSEmu/Memory/RealModeMemoryCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,36 @@ public class RealModeMemoryCore : AbstractMemoryCore, IMemoryCore

private MemoryAllocator _memoryAllocator;

private readonly Dictionary<int, Instruction> _instructionCache = new(128*1024);
/// <summary>
/// CodeReader implementation which feeds the Iced.Intel
/// decoder based on our current IP.
/// </summary>
private class RealModeCodeReader : CodeReader
{
private readonly byte[] _memory;
private int ip = 0;

public RealModeCodeReader(byte[] memory)
{
_memory = memory;
}

public override int ReadByte() => _memory[ip++];

public void SetCurrent(int position) => ip = position;
}

private readonly RealModeCodeReader _codeReader;

private readonly Decoder _decoder;

public RealModeMemoryCore(ushort heapBaseSegment, ILogger logger) : base(logger)
{
_heapBaseSegment = heapBaseSegment;

_codeReader = new(_memory);
_decoder = Decoder.Create(16, _codeReader);

// fill with halt instructions
Array.Fill(_memory, (byte)0);

Expand Down Expand Up @@ -79,24 +103,13 @@ public int GetAllocatedMemorySize(FarPtr ptr)
public Instruction GetInstruction(ushort segment, ushort instructionPointer)
{
var physicalAddress = VirtualToPhysicalAddress(segment, instructionPointer);
_codeReader.SetCurrent(physicalAddress);

if (_instructionCache.TryGetValue(physicalAddress, out var instruction))
return instruction;

var codeReader = new ByteArrayCodeReader(VirtualToPhysical(segment, instructionPointer).Slice(0, 10).ToArray());
var decoder = Decoder.Create(16, codeReader);
decoder.IP = instructionPointer;

instruction = decoder.Decode();
_instructionCache.Add(VirtualToPhysicalAddress(segment, instructionPointer), instruction);
return instruction;
_decoder.IP = instructionPointer;
return _decoder.Decode();
}

public Instruction Recompile(ushort segment, ushort instructionPointer)
{
_instructionCache.Remove(VirtualToPhysicalAddress(segment, instructionPointer));
return GetInstruction(segment, instructionPointer);
}
public Instruction Recompile(ushort segment, ushort instructionPointer) => GetInstruction(segment, instructionPointer);

public static int VirtualToPhysicalAddress(ushort segment, ushort offset) => ((segment << 4) + offset);
public static FarPtr PhysicalToVirtualAddress(int offset) => new FarPtr((ushort)(offset >> 4), (ushort)(offset & 0xF));
Expand All @@ -105,7 +118,6 @@ public override void Clear()
{
base.Clear();

_instructionCache.Clear();
_memoryAllocator = new MemoryAllocator(_logger, new FarPtr(_heapBaseSegment, 0), HEAP_MAX_SIZE, alignment: 16);
Array.Fill(_memory, (byte)0);
}
Expand Down

0 comments on commit daaa079

Please sign in to comment.