mirror of
https://github.com/digital-jellyfish/Virtu.git
synced 2024-05-31 15:41:33 +00:00
Cleaned up repository after conversion from Svn to Hg.
This commit is contained in:
parent
8d302f35e9
commit
01a1c1b1f5
2
.hgignore
Normal file
2
.hgignore
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
relre:/(bin|obj)/
|
||||||
|
relre:\.(cachefile|suo|user|vs10x)$
|
|
@ -1,27 +0,0 @@
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Jellyfish.Library
|
|
||||||
{
|
|
||||||
public static class StringBuilderExtensions
|
|
||||||
{
|
|
||||||
public static StringBuilder AppendWithoutGarbage(this StringBuilder builder, int number)
|
|
||||||
{
|
|
||||||
if (number < 0)
|
|
||||||
{
|
|
||||||
builder.Append('-');
|
|
||||||
}
|
|
||||||
|
|
||||||
int index = builder.Length;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
builder.Insert(index, Digits, (number % 10) + 9, 1);
|
|
||||||
number /= 10;
|
|
||||||
}
|
|
||||||
while (number != 0);
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly char[] Digits = new char[] { '9', '8', '7', '6', '5', '4', '3', '2', '1', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
|
|
||||||
}
|
|
||||||
}
|
|
240
Virtu/DiskII.cs
240
Virtu/DiskII.cs
|
@ -1,240 +0,0 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using Jellyfish.Virtu.Services;
|
|
||||||
|
|
||||||
namespace Jellyfish.Virtu
|
|
||||||
{
|
|
||||||
public sealed class DiskII : MachineComponent
|
|
||||||
{
|
|
||||||
public DiskII(Machine machine) :
|
|
||||||
base(machine)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
_drives[0].InsertDisk("Default.dsk", StorageService.GetResourceStream("Disks/Default.dsk", 0x23000), false);
|
|
||||||
|
|
||||||
#if WINDOWS
|
|
||||||
var settings = Machine.Settings.DiskII;
|
|
||||||
if (settings.Disk1.Name.Length > 0)
|
|
||||||
{
|
|
||||||
_drives[0].InsertDisk(settings.Disk1.Name, settings.Disk1.IsWriteProtected);
|
|
||||||
}
|
|
||||||
if (settings.Disk2.Name.Length > 0)
|
|
||||||
{
|
|
||||||
_drives[1].InsertDisk(settings.Disk2.Name, settings.Disk2.IsWriteProtected);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Reset()
|
|
||||||
{
|
|
||||||
_phaseStates = 0;
|
|
||||||
SetMotorOn(false);
|
|
||||||
SetDriveNumber(0);
|
|
||||||
_loadMode = false;
|
|
||||||
_writeMode = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Uninitialize()
|
|
||||||
{
|
|
||||||
Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
|
|
||||||
public int Read(int address)
|
|
||||||
{
|
|
||||||
switch (address & 0xF)
|
|
||||||
{
|
|
||||||
case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7:
|
|
||||||
SetPhase(address);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x8:
|
|
||||||
SetMotorOn(false);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x9:
|
|
||||||
SetMotorOn(true);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xA:
|
|
||||||
SetDriveNumber(0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xB:
|
|
||||||
SetDriveNumber(1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xC:
|
|
||||||
_loadMode = false;
|
|
||||||
if (_motorOn)
|
|
||||||
{
|
|
||||||
if (!_writeMode)
|
|
||||||
{
|
|
||||||
return _latch = _drives[_driveNumber].Read();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WriteLatch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xD:
|
|
||||||
_loadMode = true;
|
|
||||||
if (_motorOn && !_writeMode)
|
|
||||||
{
|
|
||||||
// write protect is forced if phase 1 is on [F9.7]
|
|
||||||
_latch &= 0x7F;
|
|
||||||
if (_drives[_driveNumber].IsWriteProtected ||
|
|
||||||
(_phaseStates & Phase1On) != 0)
|
|
||||||
{
|
|
||||||
_latch |= 0x80;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xE:
|
|
||||||
_writeMode = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xF:
|
|
||||||
_writeMode = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((address & 1) == 0)
|
|
||||||
{
|
|
||||||
// only even addresses return the latch
|
|
||||||
if (_motorOn)
|
|
||||||
{
|
|
||||||
return _latch;
|
|
||||||
}
|
|
||||||
|
|
||||||
// simple hack to fool DOS SAMESLOT drive spin check (usually at $BD34)
|
|
||||||
_driveSpin = !_driveSpin;
|
|
||||||
return _driveSpin ? 0x7E : 0x7F;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Machine.Video.ReadFloatingBus(); // [5-40]
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(int address, int data)
|
|
||||||
{
|
|
||||||
switch (address & 0xF)
|
|
||||||
{
|
|
||||||
case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7:
|
|
||||||
SetPhase(address);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x8:
|
|
||||||
SetMotorOn(false);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x9:
|
|
||||||
SetMotorOn(true);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xA:
|
|
||||||
SetDriveNumber(0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xB:
|
|
||||||
SetDriveNumber(1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xC:
|
|
||||||
_loadMode = false;
|
|
||||||
if (_writeMode)
|
|
||||||
{
|
|
||||||
WriteLatch();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xD:
|
|
||||||
_loadMode = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xE:
|
|
||||||
_writeMode = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xF:
|
|
||||||
_writeMode = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_motorOn && _writeMode)
|
|
||||||
{
|
|
||||||
if (_loadMode)
|
|
||||||
{
|
|
||||||
// any address writes latch for sequencer LD; OE1/2 irrelevant ['323 datasheet]
|
|
||||||
_latch = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WriteLatch()
|
|
||||||
{
|
|
||||||
// write protect is forced if phase 1 is on [F9.7]
|
|
||||||
if ((_phaseStates & Phase1On) == 0)
|
|
||||||
{
|
|
||||||
_drives[_driveNumber].Write(_latch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Flush()
|
|
||||||
{
|
|
||||||
_drives[_driveNumber].FlushTrack();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetDriveNumber(int driveNumber)
|
|
||||||
{
|
|
||||||
if (_driveNumber != driveNumber)
|
|
||||||
{
|
|
||||||
Flush();
|
|
||||||
_driveNumber = driveNumber;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetMotorOn(bool state)
|
|
||||||
{
|
|
||||||
if (_motorOn && !state)
|
|
||||||
{
|
|
||||||
Flush();
|
|
||||||
}
|
|
||||||
_motorOn = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetPhase(int address)
|
|
||||||
{
|
|
||||||
int phase = (address >> 1) & 0x3;
|
|
||||||
int state = address & 1;
|
|
||||||
_phaseStates &= ~(1 << phase);
|
|
||||||
_phaseStates |= (state << phase);
|
|
||||||
|
|
||||||
if (_motorOn)
|
|
||||||
{
|
|
||||||
_drives[_driveNumber].ApplyPhaseChange(_phaseStates);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
|
|
||||||
public Drive525[] Drives { get { return _drives; } }
|
|
||||||
|
|
||||||
private const int Phase0On = 1 << 0;
|
|
||||||
private const int Phase1On = 1 << 1;
|
|
||||||
private const int Phase2On = 1 << 2;
|
|
||||||
private const int Phase3On = 1 << 3;
|
|
||||||
|
|
||||||
private Drive525[] _drives = new Drive525[] { new Drive525(), new Drive525() };
|
|
||||||
private int _latch;
|
|
||||||
private int _phaseStates;
|
|
||||||
private bool _motorOn;
|
|
||||||
private int _driveNumber;
|
|
||||||
private bool _loadMode;
|
|
||||||
private bool _writeMode;
|
|
||||||
private bool _driveSpin;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,120 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Security;
|
|
||||||
using Jellyfish.Library;
|
|
||||||
|
|
||||||
namespace Jellyfish.Virtu
|
|
||||||
{
|
|
||||||
public sealed class Drive525
|
|
||||||
{
|
|
||||||
public Drive525()
|
|
||||||
{
|
|
||||||
DriveArmStepDelta[0] = new int[] { 0, 0, 1, 1, 0, 0, 1, 1, -1, -1, 0, 0, -1, -1, 0, 0 }; // phase 0
|
|
||||||
DriveArmStepDelta[1] = new int[] { 0, -1, 0, -1, 1, 0, 1, 0, 0, -1, 0, -1, 1, 0, 1, 0 }; // phase 1
|
|
||||||
DriveArmStepDelta[2] = new int[] { 0, 0, -1, -1, 0, 0, -1, -1, 1, 1, 0, 0, 1, 1, 0, 0 }; // phase 2
|
|
||||||
DriveArmStepDelta[3] = new int[] { 0, 1, 0, 1, -1, 0, -1, 0, 0, 1, 0, 1, -1, 0, -1, 0 }; // phase 3
|
|
||||||
}
|
|
||||||
|
|
||||||
[SecurityCritical]
|
|
||||||
public void InsertDisk(string fileName, bool isWriteProtected)
|
|
||||||
{
|
|
||||||
using (var stream = File.OpenRead(fileName))
|
|
||||||
{
|
|
||||||
InsertDisk(fileName, stream, isWriteProtected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void InsertDisk(string name, Stream stream, bool isWriteProtected)
|
|
||||||
{
|
|
||||||
FlushTrack();
|
|
||||||
|
|
||||||
// TODO handle null param/empty string for eject, or add Eject()
|
|
||||||
|
|
||||||
_disk = Disk525.CreateDisk(name, stream.ReadAllBytes(), isWriteProtected);
|
|
||||||
_trackLoaded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ApplyPhaseChange(int phaseState)
|
|
||||||
{
|
|
||||||
// step the drive head according to stepper magnet changes
|
|
||||||
int delta = DriveArmStepDelta[_trackNumber & 0x3][phaseState];
|
|
||||||
if (delta != 0)
|
|
||||||
{
|
|
||||||
int newTrackNumber = MathHelpers.Clamp(_trackNumber + delta, 0, TrackNumberMax);
|
|
||||||
if (newTrackNumber != _trackNumber)
|
|
||||||
{
|
|
||||||
FlushTrack();
|
|
||||||
_trackNumber = newTrackNumber;
|
|
||||||
_trackOffset = 0;
|
|
||||||
_trackLoaded = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Read()
|
|
||||||
{
|
|
||||||
if (LoadTrack())
|
|
||||||
{
|
|
||||||
int data = _trackData[_trackOffset++];
|
|
||||||
if (_trackOffset >= Disk525.TrackSize)
|
|
||||||
{
|
|
||||||
_trackOffset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _random.Next(0x01, 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(int data)
|
|
||||||
{
|
|
||||||
if (LoadTrack())
|
|
||||||
{
|
|
||||||
_trackChanged = true;
|
|
||||||
_trackData[_trackOffset++] = (byte)data;
|
|
||||||
if (_trackOffset >= Disk525.TrackSize)
|
|
||||||
{
|
|
||||||
_trackOffset = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool LoadTrack()
|
|
||||||
{
|
|
||||||
if (!_trackLoaded && (_disk != null))
|
|
||||||
{
|
|
||||||
_disk.ReadTrack(_trackNumber, 0, _trackData);
|
|
||||||
_trackLoaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _trackLoaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void FlushTrack()
|
|
||||||
{
|
|
||||||
if (_trackChanged)
|
|
||||||
{
|
|
||||||
_disk.WriteTrack(_trackNumber, 0, _trackData);
|
|
||||||
_trackChanged = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsWriteProtected { get { return _disk.IsWriteProtected; } }
|
|
||||||
|
|
||||||
private const int TrackNumberMax = 0x44;
|
|
||||||
|
|
||||||
private const int PhaseCount = 4;
|
|
||||||
|
|
||||||
private readonly int[][] DriveArmStepDelta = new int[PhaseCount][];
|
|
||||||
|
|
||||||
private Disk525 _disk;
|
|
||||||
private bool _trackLoaded;
|
|
||||||
private bool _trackChanged;
|
|
||||||
private int _trackNumber;
|
|
||||||
private int _trackOffset;
|
|
||||||
private byte[] _trackData = new byte[Disk525.TrackSize];
|
|
||||||
|
|
||||||
private Random _random = new Random();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,198 +1,198 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
|
||||||
namespace Jellyfish.Virtu
|
namespace Jellyfish.Virtu
|
||||||
{
|
{
|
||||||
public sealed class NoSlotClock
|
public sealed class NoSlotClock
|
||||||
{
|
{
|
||||||
public NoSlotClock()
|
public NoSlotClock()
|
||||||
{
|
{
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
// SmartWatch reset - whether tied to system reset is component specific
|
// SmartWatch reset - whether tied to system reset is component specific
|
||||||
_comparisonRegister.Reset();
|
_comparisonRegister.Reset();
|
||||||
_clockRegisterEnabled = false;
|
_clockRegisterEnabled = false;
|
||||||
_writeEnabled = true;
|
_writeEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Read(int address, int data)
|
public int Read(int address, int data)
|
||||||
{
|
{
|
||||||
// this may read or write the clock
|
// this may read or write the clock
|
||||||
if ((address & 0x4) != 0)
|
if ((address & 0x4) != 0)
|
||||||
{
|
{
|
||||||
return ClockRead(data);
|
return ClockRead(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClockWrite(address);
|
ClockWrite(address);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(int address)
|
public void Write(int address)
|
||||||
{
|
{
|
||||||
// this may read or write the clock
|
// this may read or write the clock
|
||||||
if ((address & 0x4) != 0)
|
if ((address & 0x4) != 0)
|
||||||
{
|
{
|
||||||
ClockRead(0);
|
ClockRead(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ClockWrite(address);
|
ClockWrite(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ClockRead(int data)
|
public int ClockRead(int data)
|
||||||
{
|
{
|
||||||
// for a ROM, A2 high = read, and data out (if any) is on D0
|
// for a ROM, A2 high = read, and data out (if any) is on D0
|
||||||
if (!_clockRegisterEnabled)
|
if (!_clockRegisterEnabled)
|
||||||
{
|
{
|
||||||
_comparisonRegister.Reset();
|
_comparisonRegister.Reset();
|
||||||
_writeEnabled = true;
|
_writeEnabled = true;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = _clockRegister.ReadBit(data);
|
data = _clockRegister.ReadBit(data);
|
||||||
if (_clockRegister.NextBit())
|
if (_clockRegister.NextBit())
|
||||||
{
|
{
|
||||||
_clockRegisterEnabled = false;
|
_clockRegisterEnabled = false;
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClockWrite(int address)
|
public void ClockWrite(int address)
|
||||||
{
|
{
|
||||||
// for a ROM, A2 low = write, and data in is on A0
|
// for a ROM, A2 low = write, and data in is on A0
|
||||||
if (!_writeEnabled)
|
if (!_writeEnabled)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_clockRegisterEnabled)
|
if (!_clockRegisterEnabled)
|
||||||
{
|
{
|
||||||
if ((_comparisonRegister.CompareBit(address)))
|
if ((_comparisonRegister.CompareBit(address)))
|
||||||
{
|
{
|
||||||
if (_comparisonRegister.NextBit())
|
if (_comparisonRegister.NextBit())
|
||||||
{
|
{
|
||||||
_clockRegisterEnabled = true;
|
_clockRegisterEnabled = true;
|
||||||
PopulateClockRegister();
|
PopulateClockRegister();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// mismatch ignores further writes
|
// mismatch ignores further writes
|
||||||
_writeEnabled = false;
|
_writeEnabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (_clockRegister.NextBit())
|
else if (_clockRegister.NextBit())
|
||||||
{
|
{
|
||||||
// simulate writes, but our clock register is read-only
|
// simulate writes, but our clock register is read-only
|
||||||
_clockRegisterEnabled = false;
|
_clockRegisterEnabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PopulateClockRegister()
|
private void PopulateClockRegister()
|
||||||
{
|
{
|
||||||
// all values are in packed BCD format (4 bits per decimal digit)
|
// all values are in packed BCD format (4 bits per decimal digit)
|
||||||
var now = DateTime.Now;
|
var now = DateTime.Now;
|
||||||
|
|
||||||
int centisecond = now.Millisecond / 10; // 00-99
|
int centisecond = now.Millisecond / 10; // 00-99
|
||||||
_clockRegister.WriteNibble(centisecond % 10);
|
_clockRegister.WriteNibble(centisecond % 10);
|
||||||
_clockRegister.WriteNibble(centisecond / 10);
|
_clockRegister.WriteNibble(centisecond / 10);
|
||||||
|
|
||||||
int second = now.Second; // 00-59
|
int second = now.Second; // 00-59
|
||||||
_clockRegister.WriteNibble(second % 10);
|
_clockRegister.WriteNibble(second % 10);
|
||||||
_clockRegister.WriteNibble(second / 10);
|
_clockRegister.WriteNibble(second / 10);
|
||||||
|
|
||||||
int minute = now.Minute; // 00-59
|
int minute = now.Minute; // 00-59
|
||||||
_clockRegister.WriteNibble(minute % 10);
|
_clockRegister.WriteNibble(minute % 10);
|
||||||
_clockRegister.WriteNibble(minute / 10);
|
_clockRegister.WriteNibble(minute / 10);
|
||||||
|
|
||||||
int hour = now.Hour; // 01-23
|
int hour = now.Hour; // 01-23
|
||||||
_clockRegister.WriteNibble(hour % 10);
|
_clockRegister.WriteNibble(hour % 10);
|
||||||
_clockRegister.WriteNibble(hour / 10);
|
_clockRegister.WriteNibble(hour / 10);
|
||||||
|
|
||||||
int day = (int)now.DayOfWeek + 1; // 01-07 (1 = Sunday)
|
int day = (int)now.DayOfWeek + 1; // 01-07 (1 = Sunday)
|
||||||
_clockRegister.WriteNibble(day % 10);
|
_clockRegister.WriteNibble(day % 10);
|
||||||
_clockRegister.WriteNibble(day / 10);
|
_clockRegister.WriteNibble(day / 10);
|
||||||
|
|
||||||
int date = now.Day; // 01-31
|
int date = now.Day; // 01-31
|
||||||
_clockRegister.WriteNibble(date % 10);
|
_clockRegister.WriteNibble(date % 10);
|
||||||
_clockRegister.WriteNibble(date / 10);
|
_clockRegister.WriteNibble(date / 10);
|
||||||
|
|
||||||
int month = now.Month; // 01-12
|
int month = now.Month; // 01-12
|
||||||
_clockRegister.WriteNibble(month % 10);
|
_clockRegister.WriteNibble(month % 10);
|
||||||
_clockRegister.WriteNibble(month / 10);
|
_clockRegister.WriteNibble(month / 10);
|
||||||
|
|
||||||
int year = now.Year % 100; // 00-99
|
int year = now.Year % 100; // 00-99
|
||||||
_clockRegister.WriteNibble(year % 10);
|
_clockRegister.WriteNibble(year % 10);
|
||||||
_clockRegister.WriteNibble(year / 10);
|
_clockRegister.WriteNibble(year / 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
private const ulong ClockInitSequence = 0x5CA33AC55CA33AC5;
|
private const ulong ClockInitSequence = 0x5CA33AC55CA33AC5;
|
||||||
|
|
||||||
private bool _clockRegisterEnabled;
|
private bool _clockRegisterEnabled;
|
||||||
private bool _writeEnabled;
|
private bool _writeEnabled;
|
||||||
private RingRegister _clockRegister = new RingRegister();
|
private RingRegister _clockRegister = new RingRegister();
|
||||||
private RingRegister _comparisonRegister = new RingRegister(ClockInitSequence);
|
private RingRegister _comparisonRegister = new RingRegister(ClockInitSequence);
|
||||||
|
|
||||||
private sealed class RingRegister
|
private sealed class RingRegister
|
||||||
{
|
{
|
||||||
public RingRegister(ulong data = 0)
|
public RingRegister(ulong data = 0)
|
||||||
{
|
{
|
||||||
_register = data;
|
_register = data;
|
||||||
|
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
_mask = 0x1;
|
_mask = 0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteNibble(int data)
|
public void WriteNibble(int data)
|
||||||
{
|
{
|
||||||
WriteBits(data, 4);
|
WriteBits(data, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteBits(int data, int count)
|
public void WriteBits(int data, int count)
|
||||||
{
|
{
|
||||||
for (int i = 1; i <= count; i++)
|
for (int i = 1; i <= count; i++)
|
||||||
{
|
{
|
||||||
WriteBit(data);
|
WriteBit(data);
|
||||||
NextBit();
|
NextBit();
|
||||||
data >>= 1;
|
data >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteBit(int data)
|
public void WriteBit(int data)
|
||||||
{
|
{
|
||||||
_register = ((data & 0x1) != 0) ? (_register | _mask) : (_register & ~_mask);
|
_register = ((data & 0x1) != 0) ? (_register | _mask) : (_register & ~_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ReadBit(int data)
|
public int ReadBit(int data)
|
||||||
{
|
{
|
||||||
return ((_register & _mask) != 0) ? (data | 0x1) : (data & ~0x1);
|
return ((_register & _mask) != 0) ? (data | 0x1) : (data & ~0x1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CompareBit(int data)
|
public bool CompareBit(int data)
|
||||||
{
|
{
|
||||||
return (((_register & _mask) != 0) == ((data & 0x1) != 0));
|
return (((_register & _mask) != 0) == ((data & 0x1) != 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool NextBit()
|
public bool NextBit()
|
||||||
{
|
{
|
||||||
if ((_mask <<= 1) == 0)
|
if ((_mask <<= 1) == 0)
|
||||||
{
|
{
|
||||||
_mask = 0x1;
|
_mask = 0x1;
|
||||||
return true; // wrap
|
return true; // wrap
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ulong _mask;
|
private ulong _mask;
|
||||||
private ulong _register;
|
private ulong _register;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
99
Virtu/Properties/SR.Designer.cs
generated
99
Virtu/Properties/SR.Designer.cs
generated
|
@ -1,99 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// <auto-generated>
|
|
||||||
// This code was generated by a tool.
|
|
||||||
// Runtime Version:2.0.50727.4927
|
|
||||||
//
|
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
|
||||||
// the code is regenerated.
|
|
||||||
// </auto-generated>
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace Jellyfish.Virtu.Properties {
|
|
||||||
using System;
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
|
||||||
/// </summary>
|
|
||||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
|
||||||
// class via a tool like ResGen or Visual Studio.
|
|
||||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
|
||||||
// with the /str option, or rebuild your VS project.
|
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
|
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
|
||||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
|
||||||
internal class SR {
|
|
||||||
|
|
||||||
private static global::System.Resources.ResourceManager resourceMan;
|
|
||||||
|
|
||||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
|
||||||
|
|
||||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
|
||||||
internal SR() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the cached ResourceManager instance used by this class.
|
|
||||||
/// </summary>
|
|
||||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
|
||||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
|
||||||
get {
|
|
||||||
if (object.ReferenceEquals(resourceMan, null)) {
|
|
||||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Jellyfish.Virtu.Properties.SR", typeof(SR).Assembly);
|
|
||||||
resourceMan = temp;
|
|
||||||
}
|
|
||||||
return resourceMan;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Overrides the current thread's CurrentUICulture property for all
|
|
||||||
/// resource lookups using this strongly typed resource class.
|
|
||||||
/// </summary>
|
|
||||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
|
||||||
internal static global::System.Globalization.CultureInfo Culture {
|
|
||||||
get {
|
|
||||||
return resourceCulture;
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
resourceCulture = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Resource '{0}' invalid..
|
|
||||||
/// </summary>
|
|
||||||
internal static string ResourceInvalid {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("ResourceInvalid", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Resource '{0}' not found..
|
|
||||||
/// </summary>
|
|
||||||
internal static string ResourceNotFound {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("ResourceNotFound", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Service type '{0}' already present..
|
|
||||||
/// </summary>
|
|
||||||
internal static string ServiceAlreadyPresent {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("ServiceAlreadyPresent", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Service type '{0}' must be assignable from service provider '{1}'..
|
|
||||||
/// </summary>
|
|
||||||
internal static string ServiceMustBeAssignable {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("ServiceMustBeAssignable", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.IO.IsolatedStorage;
|
|
||||||
|
|
||||||
namespace Jellyfish.Virtu.Services
|
|
||||||
{
|
|
||||||
public sealed class SilverlightStorageService : StorageService
|
|
||||||
{
|
|
||||||
public SilverlightStorageService(Machine machine) :
|
|
||||||
base(machine)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Load(string path, Action<Stream> reader)
|
|
||||||
{
|
|
||||||
if (reader == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("reader");
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
|
|
||||||
{
|
|
||||||
using (var stream = new IsolatedStorageFileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, store))
|
|
||||||
{
|
|
||||||
reader(stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (FileNotFoundException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
catch (IsolatedStorageException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Save(string path, Action<Stream> writer)
|
|
||||||
{
|
|
||||||
if (writer == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("writer");
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
|
|
||||||
{
|
|
||||||
using (var stream = new IsolatedStorageFileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, store))
|
|
||||||
{
|
|
||||||
writer(stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (IsolatedStorageException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
|
||||||
<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2009/deployment" AppPlatformVersion="7.0">
|
|
||||||
<App xmlns="" ProductID="{89a50370-1ed9-4cf1-ad08-043b6e6f3c90}" Title="Virtu" RuntimeType="XNA" Version="1.0.0.0" Genre="Apps.Games" Author="" Description="" Publisher="">
|
|
||||||
<IconPath IsRelative="true" IsResource="false">AppThumbnail.png</IconPath>
|
|
||||||
<Capabilities>
|
|
||||||
<Capability Name="ID_CAP_NETWORKING" />
|
|
||||||
<Capability Name="ID_CAP_LOCATION" />
|
|
||||||
<Capability Name="ID_CAP_SENSORS" />
|
|
||||||
<Capability Name="ID_CAP_MICROPHONE" />
|
|
||||||
<Capability Name="ID_CAP_MEDIALIB" />
|
|
||||||
<Capability Name="ID_CAP_GAMERSERVICES" />
|
|
||||||
<Capability Name="ID_CAP_PHONEDIALER" />
|
|
||||||
<Capability Name="ID_CAP_PUSH_NOTIFICATION" />
|
|
||||||
<Capability Name="ID_CAP_WEBBROWSERCOMPONENT" />
|
|
||||||
</Capabilities>
|
|
||||||
<Tasks>
|
|
||||||
<DefaultTask Name="_default" PlaceHolderString="Default task" />
|
|
||||||
</Tasks>
|
|
||||||
<Tokens>
|
|
||||||
<PrimaryToken TokenID="Jellyfish.Virtu.Xna.Phone.Token" TaskName="_default">
|
|
||||||
<TemplateType5>
|
|
||||||
<BackgroundImageURI IsRelative="true" IsResource="false">AppThumbnail.png</BackgroundImageURI>
|
|
||||||
<Count>0</Count>
|
|
||||||
<Title>Virtu</Title>
|
|
||||||
</TemplateType5>
|
|
||||||
</PrimaryToken>
|
|
||||||
</Tokens>
|
|
||||||
</App>
|
|
||||||
</Deployment>
|
|
Loading…
Reference in New Issue
Block a user