Added acanline rendering. Fixed interrupts. Added XInput support

This commit is contained in:
2026-05-12 23:13:23 +01:00
parent edb41bdb3a
commit d571fe7187
6 changed files with 222 additions and 255 deletions

27
Desktop/Controller.cs Normal file
View File

@@ -0,0 +1,27 @@
using System.Runtime.InteropServices;
public static class XInput
{
// Reach into the Windows OS API
[DllImport("xinput1_4.dll")]
public static extern int XInputGetState(int dwUserIndex, out XINPUT_STATE pState);
[StructLayout(LayoutKind.Sequential)]
public struct XINPUT_STATE
{
public uint dwPacketNumber;
public XINPUT_GAMEPAD Gamepad;
}
[StructLayout(LayoutKind.Sequential)]
public struct XINPUT_GAMEPAD
{
public ushort wButtons;
public byte bLeftTrigger;
public byte bRightTrigger;
public short sThumbLX;
public short sThumbLY;
public short sThumbRX;
public short sThumbRY;
}
}

View File

@@ -56,7 +56,7 @@ namespace Desktop
try
{
// Ask the main form to step the WHOLE machine, not just the Z80!
_mainForm.StepEmulator();
//_mainForm.StepEmulator();
UpdateDisplay();
}
catch (Exception ex)

View File

@@ -100,7 +100,23 @@ namespace Desktop
// Mark exactly when the emulator starts thinking
double frameStartTime = _stopwatch.Elapsed.TotalMilliseconds;
// 1. Do the heavy lifting (Z80 and VDP)
// --- POLL PHYSICAL CONTROLLER ---
if (XInput.XInputGetState(0, out XInput.XINPUT_STATE state) == 0)
{
ushort btns = state.Gamepad.wButtons;
byte padState = 0xFF;
if ((btns & 0x0001) != 0) padState &= 0xFE; // Up
if ((btns & 0x0002) != 0) padState &= 0xFD; // Down
if ((btns & 0x0004) != 0) padState &= 0xFB; // Left
if ((btns & 0x0008) != 0) padState &= 0xF7; // Right
if ((btns & 0x1000) != 0) padState &= 0xEF; // Button 1
if ((btns & 0x2000) != 0) padState &= 0xDF; // Button 2
// THE FIX: Constantly update the gamepad state, even when it's 0xFF!
_machine.IoBus.Joypad1Gamepad = padState;
}
// --------------------------------
_machine.RunFrame();
// 2. FIRE AND FORGET! Tell Windows to draw, but DO NOT WAIT for it to finish!
@@ -161,12 +177,6 @@ namespace Desktop
IsRunning = false;
}
public void StepEmulator()
{
_machine.StepMachine();
}
private async void LoadRomAndStart(string filePath)
{
StopEmulator();
@@ -282,13 +292,11 @@ namespace Desktop
if (isPressed)
{
// Active-Low: Clear the specific bit to 0 using a bitwise AND with a NOT mask
_machine.IoBus.Joypad1State &= (byte)~bitMask;
_machine.IoBus.Joypad1Keyboard &= (byte)~bitMask; // Target Keyboard!
}
else
{
// Active-Low: Reset the specific bit to 1 using a bitwise OR mask
_machine.IoBus.Joypad1State |= bitMask;
_machine.IoBus.Joypad1Keyboard |= bitMask; // Target Keyboard!
}
}
}