Skip to content

Commit 2f69b5b

Browse files
feature: proper dos process managment
- Added `_lastReturnCode` and `_lastTerminationMode` to track the last executed child process's return code and termination mode. - Introduced `CreateNewPsp` and `CreateChildPsp` methods for managing Program Segment Prefixes (PSPs). - Corrected method name for consistency and added `GetReturnCode` action. - Enhanced `TerminateAndStayResident` and `QuitWithExitCode` methods for better process termination and memory management. - Updated `LoadAndOrExecute` method to log execution details and indicate success or failure. - Refactored parameter preparation methods and introduced a new `DosTerminationMode` enum.
1 parent 54025b8 commit 2f69b5b

File tree

9 files changed

+1040
-186
lines changed

9 files changed

+1040
-186
lines changed

src/Spice86.Core/Emulator/InterruptHandlers/Dos/DosInt21Handler.cs

Lines changed: 269 additions & 15 deletions
Large diffs are not rendered by default.

src/Spice86.Core/Emulator/LoadableFile/Bios/BiosLoader.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ public BiosLoader(IMemory memory, State state, ILoggerService loggerService) : b
3838
}
3939

4040
/// <summary>
41-
/// Loads the specified BIOS <paramref name="file"/> into memory and sets the entry point to the BIOS address.
41+
/// Loads the specified BIOS <paramref name="filePath"/> into memory and sets the entry point to the BIOS address.
4242
/// </summary>
43-
/// <param name="file">The path to the BIOS file to load.</param>
43+
/// <param name="filePath">The absolute path to the BIOS file to load.</param>
4444
/// <param name="arguments">Ignored for BIOS files.</param>
4545
/// <returns>The loaded BIOS file as a byte array.</returns>
46-
public override byte[] LoadFile(string file, string? arguments) {
47-
byte[] bios = ReadFile(file);
46+
public override byte[] LoadFile(string filePath, string? arguments) {
47+
byte[] bios = ReadFile(filePath);
4848
uint physicalStartAddress = MemoryUtils.ToPhysicalAddress(CodeSegment, 0);
4949
_memory.LoadData(physicalStartAddress, bios);
5050
SetEntryPoint(CodeSegment, CodeOffset);

src/Spice86.Core/Emulator/LoadableFile/ExecutableFileLoader.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
using Spice86.Shared.Interfaces;
66
using Spice86.Shared.Utils;
77

8-
using System.IO;
9-
108
/// <summary>
119
/// Base class for loading executable files in the VM like exe, bios, ...
1210
/// </summary>
@@ -43,10 +41,10 @@ protected ExecutableFileLoader(IMemory memory, State state, ILoggerService logge
4341
/// <summary>
4442
/// Loads an executable file and returns its bytes.
4543
/// </summary>
46-
/// <param name="file">The path of the file to load.</param>
44+
/// <param name="filePath">The absolute path to the executable file.</param>
4745
/// <param name="arguments">Optional arguments to pass to the loaded file.</param>
4846
/// <returns>The bytes of the loaded file.</returns>
49-
public abstract byte[] LoadFile(string file, string? arguments);
47+
public abstract byte[] LoadFile(string filePath, string? arguments);
5048

5149
/// <summary>
5250
/// Reads the contents of a file and returns its bytes.

src/Spice86.Core/Emulator/OperatingSystem/Dos.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ public Dos(Configuration configuration, IMemory memory,
172172
DosInt20Handler = new DosInt20Handler(_memory, functionHandlerProvider, stack, state, _loggerService);
173173
DosInt21Handler = new DosInt21Handler(_memory, pspTracker, functionHandlerProvider, stack, state,
174174
keyboardInt16Handler, CountryInfo, dosStringDecoder,
175-
MemoryManager, FileManager, DosDriveManager, clock, _loggerService);
175+
MemoryManager, ProcessManager, FileManager, DosDriveManager, clock, _loggerService);
176176
DosInt2FHandler = new DosInt2fHandler(_memory,
177177
functionHandlerProvider, stack, state, _loggerService, xms);
178178
DosInt25Handler = new DosDiskInt25Handler(_memory, DosDriveManager, functionHandlerProvider, stack, state, _loggerService);

src/Spice86.Core/Emulator/OperatingSystem/DosProcessManager.cs

Lines changed: 599 additions & 156 deletions
Large diffs are not rendered by default.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace Spice86.Core.Emulator.OperatingSystem.Enums;
2+
3+
/// <summary>
4+
/// Drives the INT21H Load and/or exec function behavior
5+
/// </summary>
6+
public enum DosExecuteMode : byte {
7+
/// <summary>
8+
/// Load and execute the program
9+
/// </summary>
10+
LoadAndExecute = 0,
11+
/// <summary>
12+
/// Load, create the program header, but do not run execution
13+
/// </summary>
14+
LoadButDoNotRun = 1,
15+
/// <summary>
16+
/// Load overlay. No header created.
17+
/// </summary>
18+
LoadOverlay = 3
19+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
namespace Spice86.Core.Emulator.OperatingSystem.Enums;
2+
3+
/// <summary>
4+
/// Represents the different ways a DOS process can terminate.
5+
/// Used by INT 21h function 4Dh (Get Return Code of Child Process).
6+
/// </summary>
7+
public enum DosTerminationMode : byte {
8+
/// <summary>
9+
/// Child terminated normally (that is, exited via INT 20h or INT 21h Function 00h or Function 4Ch).
10+
/// </summary>
11+
Normal = 0x00,
12+
13+
/// <summary>
14+
/// Child was terminated by user's entry of a Ctrl-C.
15+
/// </summary>
16+
ControlC = 0x01,
17+
18+
/// <summary>
19+
/// Child was terminated by critical error handler (either the user responded with A to the
20+
/// Abort, Retry, Ignore prompt from the system's default INT 24h handler, or a custom
21+
/// INT 24h handler returned to MS-DOS with action code = 02h in register AL).
22+
/// </summary>
23+
CriticalError = 0x02,
24+
25+
/// <summary>
26+
/// Child terminated normally and stayed resident (that is, exited via INT 21h Function 31h or INT 27h).
27+
/// </summary>
28+
TerminateAndStayResident = 0x03
29+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
namespace Spice86.Core.Emulator.OperatingSystem.Structures;
2+
3+
using Spice86.Core.Emulator.Memory.ReaderWriter;
4+
using Spice86.Core.Emulator.ReverseEngineer.DataStructure;
5+
using Spice86.Shared.Emulator.Memory;
6+
7+
/// <summary>
8+
/// Represents a DOS Execute Parameter Block (ExecParamRec) used for loading and executing programs.
9+
/// This structure is used in INT 21h function 0x4B.
10+
/// </summary>
11+
public abstract class DosExecuteParameterBlock : MemoryBasedDataStructure {
12+
/// <summary>
13+
/// Initializes a new instance of the <see cref="DosExecuteParameterBlock"/> class.
14+
/// </summary>
15+
/// <param name="byteReaderWriter">Where data is read and written.</param>
16+
/// <param name="baseAddress">The base address of the data structure.</param>
17+
protected DosExecuteParameterBlock(IByteReaderWriter byteReaderWriter,
18+
uint baseAddress) : base(byteReaderWriter, baseAddress) {
19+
}
20+
}
21+
22+
/// <summary>
23+
/// Parameter block for loading and executing a program (AL=0) or just loading (AL=1).
24+
/// </summary>
25+
public class DosLoadOrLoadAndExecuteParameterBlock : DosExecuteParameterBlock {
26+
public DosLoadOrLoadAndExecuteParameterBlock(IByteReaderWriter byteReaderWriter,
27+
uint baseAddress) : base(byteReaderWriter, baseAddress) {
28+
}
29+
30+
/// <summary>
31+
/// Gets or sets the segment of environment for child process.
32+
/// 0000h means use a copy of the current environment.
33+
/// </summary>
34+
public ushort EnvironmentSegment {
35+
get => UInt16[0x0];
36+
set => UInt16[0x0] = value;
37+
}
38+
39+
/// <summary>
40+
/// Gets or sets the address of command line text to place at PSP:0080.
41+
/// </summary>
42+
public uint CommandTailAddress {
43+
get => UInt32[0x2];
44+
set => UInt32[0x2] = value;
45+
}
46+
47+
/// <summary>
48+
/// Gets or sets the address of the first FCB to be placed at PSP:005C.
49+
/// </summary>
50+
public uint FirstFcbAddress {
51+
get => UInt32[0x6];
52+
set => UInt32[0x6] = value;
53+
}
54+
55+
/// <summary>
56+
/// Gets or sets the address of the second FCB to be placed at PSP:006C.
57+
/// </summary>
58+
public uint SecondFcbAddress {
59+
get => UInt32[0xA];
60+
set => UInt32[0xA] = value;
61+
}
62+
}
63+
64+
/// <summary>
65+
/// Parameter block for loading a program but not executing it (AL=1).
66+
/// </summary>
67+
public sealed class DosLoadProgramParameterBlock : DosLoadOrLoadAndExecuteParameterBlock {
68+
public DosLoadProgramParameterBlock(IByteReaderWriter byteReaderWriter,
69+
uint baseAddress) : base(byteReaderWriter, baseAddress) {
70+
}
71+
72+
/// <summary>
73+
/// Gets or sets the initial CS:IP of the loaded program. This is a return value.
74+
/// </summary>
75+
public SegmentedAddress EntryPointAddress {
76+
get => SegmentedAddress32[0xE];
77+
set => SegmentedAddress32[0xE] = value;
78+
}
79+
80+
/// <summary>
81+
/// Gets or sets the initial SS:SP of the loaded program. This is a return value.
82+
/// </summary>
83+
public SegmentedAddress StackAddress {
84+
get => SegmentedAddress32[0x12];
85+
set => SegmentedAddress32[0x12] = value;
86+
}
87+
}
88+
89+
/// <summary>
90+
/// Parameter block for loading an overlay (AL=3).
91+
/// </summary>
92+
public sealed class DosOverlayParameterBlock : DosExecuteParameterBlock {
93+
public DosOverlayParameterBlock(IByteReaderWriter byteReaderWriter,
94+
uint baseAddress) : base(byteReaderWriter, baseAddress) {
95+
}
96+
97+
/// <summary>
98+
/// Gets or sets the segment address where the file will be loaded.
99+
/// </summary>
100+
public ushort OverlayLoadSegment {
101+
get => UInt16[0x0];
102+
set => UInt16[0x0] = value;
103+
}
104+
105+
/// <summary>
106+
/// Gets or sets the relocation factor to be applied to the image.
107+
/// </summary>
108+
public ushort OverlayRelocationFactor {
109+
get => UInt16[0x2];
110+
set => UInt16[0x2] = value;
111+
}
112+
}

src/Spice86.Core/Emulator/OperatingSystem/Structures/DosProgramSegmentPrefix.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
namespace Spice86.Core.Emulator.OperatingSystem.Structures;
1+

2+
namespace Spice86.Core.Emulator.OperatingSystem.Structures;
23

34
using Spice86.Core.Emulator.Memory.ReaderWriter;
45
using Spice86.Core.Emulator.ReverseEngineer.DataStructure;
@@ -88,9 +89,7 @@ public DosProgramSegmentPrefix(IByteReaderWriter byteReaderWriter, uint baseAddr
8889

8990
public UInt8Array FirstFileControlBlock => GetUInt8Array(0x5C, 16);
9091

91-
public UInt8Array SecondFileControlBlock => GetUInt8Array(0x6C, 16);
92+
public UInt8Array SecondFileControlBlock => GetUInt8Array(0x6C, 20);
9293

93-
public UInt8Array Unused3 => GetUInt8Array(0x7C, 4);
94-
95-
public DosCommandTail DosCommandTail => new (ByteReaderWriter, BaseAddress + 0x80);
96-
}
94+
public DosCommandTail DosCommandTail => new(ByteReaderWriter, BaseAddress + 0x80);
95+
}

0 commit comments

Comments
 (0)