Skip to content

Commit df6d6f1

Browse files
refactor: remove EmulatorEventClock - not needed
1 parent f3a884a commit df6d6f1

File tree

8 files changed

+101
-308
lines changed

8 files changed

+101
-308
lines changed

src/Spice86.Core/Emulator/Devices/Input/Keyboard/Intel8042PS2KeyboardMouseController.cs

Lines changed: 31 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
using Spice86.Core.Emulator.Devices.ExternalInput;
77
using Spice86.Core.Emulator.IOPorts;
88
using Spice86.Core.Emulator.Memory;
9-
using Spice86.Core.Emulator.VM;
109
using Spice86.Shared.Interfaces;
1110

1211
using System;
@@ -16,7 +15,6 @@
1615
/// C# port of intel8042.cpp - The PS/2 keyboard and mouse controller.
1716
/// </summary>
1817
public sealed class Intel8042Controller : DefaultIOPortHandler {
19-
private const uint IrqNumKbdPcjr = 6;
2018
private const uint IrqNumKbdIbmPc = 1;
2119
private const uint IrqNumMouse = 12;
2220

@@ -25,7 +23,7 @@ public sealed class Intel8042Controller : DefaultIOPortHandler {
2523

2624
private const int BufferSize = 64; // in bytes
2725
// delay appropriate for 20-30 kHz serial clock and 11 bits/byte
28-
private const double PortDelayMs = 0.300;
26+
private const long PortDelayCycles = 300; // Converted from 0.3ms to cycles
2927

3028
// Controller internal buffer
3129
private struct BufferEntry {
@@ -42,10 +40,9 @@ private struct BufferEntry {
4240
private int _waitingBytesFromAux = 0;
4341
private int _waitingBytesFromKbd = 0;
4442

45-
// true = delay timer is in progress
46-
private bool _delayRunning = false;
47-
// true = delay timer expired, event can be sent immediately
48-
private bool _delayExpired = true;
43+
// CPU cycle-based delay tracking
44+
private long _delayExpiryCycles = 0;
45+
private bool _delayActive = false;
4946

5047
// Executing command, do not notify devices about readiness for accepting frame
5148
private bool _shouldSkipDeviceNotify = false;
@@ -67,25 +64,25 @@ private struct BufferEntry {
6764

6865
private readonly A20Gate _a20Gate;
6966
private readonly DualPic _dualPic;
70-
private readonly EmulatorEventClock _eventClock;
67+
private readonly State _cpuState;
7168

7269
public PS2Keyboard KeyboardDevice { get; }
7370

7471
/// <summary>
7572
/// Initializes a new instance of the <see cref="Intel8042Controller"/> class.
7673
/// </summary>
7774
public Intel8042Controller(State state, IOPortDispatcher ioPortDispatcher,
78-
A20Gate a20Gate, DualPic dualPic, EmulatorEventClock eventClock,
75+
A20Gate a20Gate, DualPic dualPic,
7976
ILoggerService loggerService, bool failOnUnhandledPort,
8077
IGuiKeyboardEvents? gui = null)
8178
: base(state, failOnUnhandledPort, loggerService)
8279
{
8380
_a20Gate = a20Gate;
8481
_dualPic = dualPic;
85-
_eventClock = eventClock;
82+
_cpuState = state;
8683

8784
// Create the keyboard implementation
88-
KeyboardDevice = new PS2Keyboard(this, eventClock, loggerService, gui);
85+
KeyboardDevice = new PS2Keyboard(this, state, loggerService, gui);
8986

9087
InitPortHandlers(ioPortDispatcher);
9188

@@ -103,19 +100,19 @@ private void InitPortHandlers(IOPortDispatcher ioPortDispatcher) {
103100
// ***************************************************************************
104101

105102
private void WarnBufferFull() {
106-
const uint thresholdMs = 15 * 1000; // 15 seconds
103+
const long thresholdCycles = 15000000; // 15 seconds worth of cycles
107104

108105
// Static-like behavior using class fields
109-
if (!_bufferFullWarned || (_eventClock.EmulatorUpTimeInMs - _lastBufferFullTimestamp > thresholdMs)) {
106+
if (!_bufferFullWarned || (_cpuState.Cycles - _lastBufferFullCycles > thresholdCycles)) {
110107
if (_loggerService.IsEnabled(LogEventLevel.Warning)) {
111108
_loggerService.Warning("I8042: Internal buffer overflow");
112109
}
113-
_lastBufferFullTimestamp = (uint)_eventClock.EmulatorUpTimeInMs;
110+
_lastBufferFullCycles = _cpuState.Cycles;
114111
_bufferFullWarned = true;
115112
}
116113
}
117114
private bool _bufferFullWarned = false;
118-
private uint _lastBufferFullTimestamp = 0;
115+
private long _lastBufferFullCycles = 0;
119116

120117
private void WarnControllerMode() {
121118
if (!_controllerModeWarned) {
@@ -238,7 +235,6 @@ private uint GetIrqMouse() {
238235
}
239236

240237
private uint GetIrqKeyboard() {
241-
// Note: We simplified machine detection, always use standard IRQ1
242238
return IrqNumKbdIbmPc;
243239
}
244240

@@ -288,20 +284,22 @@ private void EnforceBufferSpace(int numBytes = 1) {
288284
}
289285
}
290286

291-
private void DelayHandler() {
292-
_delayRunning = false;
293-
_delayExpired = true;
294-
295-
MaybeTransferBuffer();
287+
private void StartDelay(long delayCycles = PortDelayCycles) {
288+
_delayExpiryCycles = _cpuState.Cycles + delayCycles;
289+
_delayActive = true;
296290
}
297291

298-
private void RestartDelayTimer(double timeMs = PortDelayMs) {
299-
if (_delayRunning) {
300-
_eventClock.RemoveEvent("I8042DelayHandler");
292+
private bool IsDelayExpired() {
293+
if (!_delayActive) {
294+
return true;
295+
}
296+
297+
if (_cpuState.Cycles >= _delayExpiryCycles) {
298+
_delayActive = false;
299+
return true;
301300
}
302-
_eventClock.AddEvent(DelayHandler, timeMs, "I8042DelayHandler");
303-
_delayRunning = true;
304-
_delayExpired = false;
301+
302+
return false;
305303
}
306304

307305
private void MaybeTransferBuffer() {
@@ -313,7 +311,7 @@ private void MaybeTransferBuffer() {
313311

314312
// If not set to skip the delay, do not send byte until timer expires
315313
int idx = _bufferStartIdx;
316-
if (!_delayExpired && !_buffer[idx].SkipDelay) {
314+
if (!IsDelayExpired() && !_buffer[idx].SkipDelay) {
317315
return;
318316
}
319317

@@ -329,7 +327,7 @@ private void MaybeTransferBuffer() {
329327
_statusByte &= unchecked((byte)~(1 << 5)); // is_data_from_aux = false
330328
}
331329
_statusByte |= (1 << 0); // is_data_new = true
332-
RestartDelayTimer();
330+
StartDelay();
333331
ActivateIrqsIfNeeded();
334332
}
335333

@@ -598,7 +596,7 @@ private void ExecuteCommand(KeyboardCommand command) {
598596
// Read test bits:
599597
// bit 0: keyboard clock in
600598
// bit 1: (AT) keyboard data in, or (PS/2) mouse clock in
601-
// Not fully implemented, follows DOSBox-X behaviour.
599+
// Not fully implemented
602600
WarnReadTestInputs();
603601
FlushBuffer();
604602
BufferAdd(0x00);
@@ -629,9 +627,6 @@ private void ExecuteCommand(KeyboardCommand command) {
629627
}
630628

631629
private void ExecuteCommand(KeyboardCommand command, byte param) {
632-
// LOG_INFO("I8042: Command 0x%02x, parameter 0x%02x",
633-
// static_cast<int>(command), param);
634-
635630
switch (command) {
636631
case KeyboardCommand.WriteByteConfig: // 0x60
637632
// Writes the keyboard controller configuration byte
@@ -671,7 +666,7 @@ private void ExecuteCommand(KeyboardCommand command, byte param) {
671666
// To prevent excessive inter-module communication,
672667
// aux (mouse) part is implemented completely within
673668
// the mouse module
674-
RestartDelayTimer(PortDelayMs * 2); // 'round trip' delay
669+
StartDelay(PortDelayCycles * 2); // 'round trip' delay
675670
_statusByte &= unchecked((byte)~(1 << 6)); // clear timeout flag
676671
// TODO: Mouse support
677672
// _statusByte |= (1 << 6) * (!MOUSEPS2_PortWrite(param));
@@ -775,7 +770,7 @@ public override byte ReadByte(ushort port) {
775770
// Enforce the simulated data transfer delay, as some software
776771
// (Tyrian 2000 setup) reads the port without waiting for the
777772
// interrupt.
778-
RestartDelayTimer(PortDelayMs);
773+
StartDelay(PortDelayCycles);
779774

780775
return retVal;
781776

@@ -817,7 +812,7 @@ public override void WriteByte(ushort port, byte value) {
817812
_configByte &= unchecked((byte)~(1 << 4)); // auto-enable keyboard port
818813

819814
FlushBuffer();
820-
RestartDelayTimer(PortDelayMs * 2); // 'round trip' delay
815+
StartDelay(PortDelayCycles * 2); // 'round trip' delay
821816
KeyboardDevice.PortWrite(value);
822817
}
823818
break;

src/Spice86.Core/Emulator/Devices/Input/Keyboard/KeyboardScancodeConverter.cs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,15 @@ public KbdKey ConvertToKbdKey(PhysicalKey key) {
8888
/// </summary>
8989
public List<byte> GetScancodes(KbdKey keyType, bool isPressed, byte codeSet) {
9090
if (keyType == KbdKey.None) {
91-
return new List<byte>();
91+
return [];
9292
}
9393

94-
switch(codeSet) {
95-
case 1: return GetScanCode1(keyType, isPressed);
96-
case 2: return GetScanCode2(keyType, isPressed);
97-
case 3: return GetScanCode3(keyType, isPressed);
98-
default: return GetScanCode1(keyType, isPressed); // Default to set 1
99-
}
94+
return codeSet switch {
95+
1 => GetScanCode1(keyType, isPressed),
96+
2 => GetScanCode2(keyType, isPressed),
97+
3 => GetScanCode3(keyType, isPressed),
98+
_ => GetScanCode1(keyType, isPressed),// Default to set 1
99+
};
100100
}
101101

102102
public List<byte> GetScanCode1(KbdKey keyType, bool isPressed) {
@@ -227,26 +227,26 @@ public List<byte> GetScanCode1(KbdKey keyType, bool isPressed) {
227227
case KbdKey.Pause:
228228
if (isPressed) {
229229
// Pause key gets released as soon as it is pressed
230-
return new List<byte> {
230+
return [
231231
0xE1, 0x1D, 0x45, 0xE1,
232232
(byte)(0x1D | 0x80), (byte)(0x45 | 0x80)
233-
};
233+
];
234234
}
235-
return new List<byte>();
235+
return [];
236236

237237
case KbdKey.PrintScreen:
238-
return new List<byte> {
238+
return [
239239
0xE0,
240240
(byte)(0x2A | (isPressed ? 0 : 0x80)),
241241
0xE0,
242242
(byte)(0x37 | (isPressed ? 0 : 0x80))
243-
};
243+
];
244244

245245
default:
246-
return new List<byte>();
246+
return [];
247247
}
248248

249-
List<byte> result = new List<byte>();
249+
List<byte> result = [];
250250

251251
if (extend) {
252252
result.Add(0xE0);

0 commit comments

Comments
 (0)