1
0
mirror of https://github.com/livingcomputermuseum/ContrAlto.git synced 2026-01-17 16:44:29 +00:00

187 lines
4.7 KiB
C#

using Contralto.CPU;
using Contralto.Memory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Contralto.IO
{
[Flags]
public enum AltoMouseButton
{
None = 0x0,
Middle = 0x1,
Right = 0x2,
Left = 0x4,
}
public class Mouse : IMemoryMappedDevice
{
public Mouse()
{
_lock = new ReaderWriterLockSlim();
Reset();
}
public void Reset()
{
// cheat for synchronization: this is approximately where the mouse is initialized to
// at alto boot.
_mouseY = 80;
_mouseX = 0;
}
public ushort Read(int address, TaskType task, bool extendedMemoryReference)
{
return (ushort)(~_buttons);
}
public void Load(int address, ushort data, TaskType task, bool extendedMemoryReference)
{
// nothing
}
public void MouseMove(int dx, int dy)
{
_lock.EnterWriteLock();
// Calculate number of steps in x and y to be decremented every call to PollMouseBits
_xSteps = Math.Abs(dx);
_xDir = Math.Sign(dx);
_ySteps = Math.Abs(dy);
_yDir = Math.Sign(dy);
//Console.WriteLine("Mouse move from ({0},{1}) to ({2},{3}).", _mouseX, _mouseY, _destX, _destY);
_lock.ExitWriteLock();
}
public void MouseDown(AltoMouseButton button)
{
_buttons |= button;
}
public void MouseUp(AltoMouseButton button)
{
_buttons ^= button;
}
/// <summary>
/// Gets the bits read by the "<-MOUSE" special function, and moves
/// the pointer one step closer to its final destination (if it has moved at all).
/// </summary>
/// <returns></returns>
public ushort PollMouseBits()
{
//
// The bits returned correspond to the delta incurred by mouse movement in the X and Y direction
// and map to:
// 0 : no change in X or Y
// 1 : dy = -1
// 2 : dy = 1
// 3 : dx = -1
// 4 : dy = -1, dx = -1
// 5 : dy = 1, dx = -1
// 6 : dx = 1
// 7 : dy = -1, dx = 1
// 8 : dy = 1, dx =1
ushort bits = 0;
_lock.EnterReadLock();
// TODO: optimize this
if (_yDir == -1 && _xDir == 0)
{
bits = 1;
}
else if (_yDir == 1 && _xDir == 0)
{
bits = 2;
}
else if (_yDir == 0 && _xDir == -1)
{
bits = 3;
}
else if (_yDir == -1 && _xDir == -1)
{
bits = 4;
}
else if (_yDir == 1 && _xDir == -1)
{
bits = 5;
}
else if (_yDir == 0 && _xDir == 1)
{
bits = 6;
}
else if (_yDir == -1 && _xDir == 1)
{
bits = 7;
}
else if (_yDir == 1 && _xDir == 1)
{
bits = 8;
}
//Console.WriteLine("Mouse poll: xdir {0}, ydir {1}, bits {2}", _xDir, _yDir, Conversion.ToOctal(bits));
// Move the mouse closer to its destination
if (_xSteps > 0)
{
_mouseX += _xDir;
_xSteps--;
if (_xSteps == 0)
{
_xDir = 0;
}
}
if (_ySteps > 0)
{
_mouseY += _yDir;
_ySteps--;
if (_ySteps == 0)
{
_yDir = 0;
}
}
_lock.ExitReadLock();
return bits;
}
public MemoryRange[] Addresses
{
get { return _addresses; }
}
private readonly MemoryRange[] _addresses =
{
new MemoryRange(0xfe18, 0xfe1b), // UTILIN: 177030-177033
};
// Mouse buttons:
AltoMouseButton _buttons;
/// <summary>
/// Where the mouse is currently reported to be
/// </summary>
private int _mouseX;
private int _mouseY;
/// <summary>
/// Where the mouse is moving to every time PollMouseBits is called.
/// </summary>
private int _xSteps;
private int _xDir;
private double _ySteps;
private int _yDir;
private ReaderWriterLockSlim _lock;
}
}