1
0
mirror of https://github.com/livingcomputermuseum/ContrAlto.git synced 2026-01-24 03:16:49 +00:00
Josh Dersch 523a4bb27f Initial implementation of Trident controller and drives (supporting T-80 and T-300 packs). TFU works and can certify, erase, exercise and manipulate files on Trident packs. TriEx doesn't quite work properly yet. Still some issues to iron out.
Added file-backed disk image implementation for use with Trident disk images, did some basic refactoring of disk load/unload logic, added support for creating new (empty) disk images for both Trident and Diablo disks.

Added UI for loading/unloading/creating up to 8 trident packs; added blank Diablo pack creation UI.  (Both Windows and *nix interfaces.)

Added configuration support for same (both Windows and *nix.)

Small correction to Print output path browsing logic.

Fixed Windows installer, now places the right ROMs for Alto I configurations in the right place.

Fixed issue when starting up with corrupted configuration.  Corrupted configuration is ignored and ContrAlto will run with default config.
2017-08-22 13:18:31 -07:00

158 lines
5.8 KiB
C#

/*
This file is part of ContrAlto.
ContrAlto is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ContrAlto is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with ContrAlto. If not, see <http://www.gnu.org/licenses/>.
*/
using Contralto.IO;
using System;
namespace Contralto.CPU
{
public partial class AltoCPU
{
/// <summary>
/// TridentTask implements the microcode special functions for the Trident
/// disk controller (for both the read and write tasks).
/// </summary>
private sealed class TridentTask : Task
{
public TridentTask(AltoCPU cpu, bool input) : base(cpu)
{
_taskType = input ? TaskType.TridentInput : TaskType.TridentOutput;
_wakeup = false;
_tridentController = cpu._system.TridentController;
// Both Trident tasks are RAM-related
_ramTask = true;
}
public override void SoftReset()
{
//
// Stop the controller.
//
_tridentController.Stop();
base.SoftReset();
}
protected override ushort GetBusSource(MicroInstruction instruction)
{
//
// The Trident tasks are wired to be RAM-enabled tasks so they can use
// S registers.
// This code is stolen from the Emulator task; we should REALLY refactor this
// since both this and the Orbit Task need it.
//
EmulatorBusSource ebs = (EmulatorBusSource)instruction.BS;
switch (ebs)
{
case EmulatorBusSource.ReadSLocation:
if (instruction.RSELECT != 0)
{
return _cpu._s[_rb][instruction.RSELECT];
}
else
{
// "...when reading data from the S registers onto the processor bus,
// the RSELECT value 0 causes the current value of the M register to
// appear on the bus..."
return _cpu._m;
}
case EmulatorBusSource.LoadSLocation:
// "When an S register is being loaded from M, the processor bus receives an
// undefined value rather than being set to zero."
_loadS = true;
return 0xffff; // Technically this is an "undefined value," we're defining it as -1.
default:
throw new InvalidOperationException(String.Format("Unhandled bus source {0}", instruction.BS));
}
}
protected override void ExecuteSpecialFunction2PostBusSource(MicroInstruction instruction)
{
TridentF2 tf2 = (TridentF2)instruction.F2;
switch (tf2)
{
case TridentF2.ReadKDTA:
//
// <-KDTA is actually MD<- (SF 6), repurposed to gate disk data onto the bus
// iff BS is None. Otherwise it behaves like a normal MD<-. We'll let
// the normal Task implementation handle the actual MD<- operation.
//
if (instruction.BS == BusSource.None)
{
// _busData at this point should be 0xffff. We could technically
// just directly assign the bits...
_busData &= _tridentController.KDTA;
}
break;
case TridentF2.STATUS:
_busData &= _tridentController.STATUS;
break;
case TridentF2.EMPTY:
_tridentController.WaitForEmpty();
break;
}
}
protected override void ExecuteSpecialFunction2(MicroInstruction instruction)
{
TridentF2 tf2 = (TridentF2)instruction.F2;
switch (tf2)
{
case TridentF2.KTAG:
_tridentController.TagInstruction(_busData);
break;
case TridentF2.WriteKDTA:
_tridentController.KDTA = _busData;
break;
case TridentF2.WAIT:
case TridentF2.WAIT2:
// Identical to BLOCK
this.BlockTask();
break;
case TridentF2.RESET:
_tridentController.ControllerReset();
break;
case TridentF2.STATUS:
case TridentF2.EMPTY:
// Handled in PostBusSource override.
break;
default:
throw new InvalidOperationException(String.Format("Unhandled trident special function 2 {0}", tf2));
}
}
private TridentController _tridentController;
}
}
}