mirror of
https://github.com/livingcomputermuseum/ContrAlto.git
synced 2026-01-24 03:16:49 +00:00
Hooked disk emulation up to disk images (currently hardcoded). Fixed a small bug in IDISP, tiny stub of Nova disassembler added.
This commit is contained in:
parent
3b29addb98
commit
1dfd1e0be9
17
Contralto/CPU/NovaDisassembler.cs
Normal file
17
Contralto/CPU/NovaDisassembler.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Contralto.CPU
|
||||
{
|
||||
/// <summary>
|
||||
/// Quick and dirty disassembler for Nova instructions, so we can
|
||||
/// see what the emulator task is executing more clearly.
|
||||
/// </summary>
|
||||
public static class NovaDisassembler
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@ -127,7 +127,7 @@ namespace Contralto.CPU
|
||||
// Conditions ORed onto NEXT Comment
|
||||
//
|
||||
// if IR[0] = 1 3-IR[8-9] complement of SH field of IR
|
||||
// elseif IR[1-2] = 0 IR[3-4] JMP, JSR, ISZ, DSZ
|
||||
// elseif IR[1-2] = 0 IR[3-4] JMP, JSR, ISZ, DSZ ; dispatch selects register
|
||||
// elseif IR[1-2] = 1 4 LDA
|
||||
// elseif IR[1-2] = 2 5 STA
|
||||
// elseif IR[4-7] = 0 1
|
||||
@ -145,11 +145,11 @@ namespace Contralto.CPU
|
||||
{
|
||||
_nextModifier = (ushort)((_cpu._ir & 0x1800) >> 11);
|
||||
}
|
||||
else if ((_cpu._ir & 0x6000) == 0x4000)
|
||||
else if ((_cpu._ir & 0x6000) == 0x2000)
|
||||
{
|
||||
_nextModifier = 4;
|
||||
}
|
||||
else if ((_cpu._ir & 0x6000) == 0x6000)
|
||||
else if ((_cpu._ir & 0x6000) == 0x4000)
|
||||
{
|
||||
_nextModifier = 5;
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ using System.Threading.Tasks;
|
||||
namespace Contralto.CPU
|
||||
{
|
||||
// BUG: register assignments should come from L (not 0)
|
||||
public static class Disassembler
|
||||
public static class UCodeDisassembler
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
@ -47,7 +47,8 @@
|
||||
<Compile Include="CPU\ALU.cs" />
|
||||
<Compile Include="CPU\ConstantMemory.cs" />
|
||||
<Compile Include="CPU\CPU.cs" />
|
||||
<Compile Include="CPU\Disassembler.cs" />
|
||||
<Compile Include="CPU\NovaDisassembler.cs" />
|
||||
<Compile Include="CPU\UCodeDisassembler.cs" />
|
||||
<Compile Include="CPU\Tasks\DiskTask.cs" />
|
||||
<Compile Include="CPU\Tasks\EmulatorTask.cs" />
|
||||
<Compile Include="CPU\MicroInstruction.cs" />
|
||||
@ -62,6 +63,7 @@
|
||||
</Compile>
|
||||
<Compile Include="IClockable.cs" />
|
||||
<Compile Include="IO\DiskController.cs" />
|
||||
<Compile Include="IO\DiabloPack.cs" />
|
||||
<Compile Include="IO\Keyboard.cs" />
|
||||
<Compile Include="Memory\IMemoryMappedDevice.cs" />
|
||||
<Compile Include="Memory\Memory.cs" />
|
||||
@ -76,6 +78,9 @@
|
||||
<None Include="Disassembly\altoIIcode3.mu">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Disk\games.dsk">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="ROM\2kctl.u3">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
||||
BIN
Contralto/Disk/games.dsk
Normal file
BIN
Contralto/Disk/games.dsk
Normal file
Binary file not shown.
143
Contralto/IO/DiabloPack.cs
Normal file
143
Contralto/IO/DiabloPack.cs
Normal file
@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Contralto.IO
|
||||
{
|
||||
|
||||
public struct DiskGeometry
|
||||
{
|
||||
public DiskGeometry(int cylinders, int tracks, int sectors)
|
||||
{
|
||||
Cylinders = cylinders;
|
||||
Tracks = tracks;
|
||||
Sectors = sectors;
|
||||
}
|
||||
|
||||
public int Cylinders;
|
||||
public int Tracks;
|
||||
public int Sectors;
|
||||
}
|
||||
|
||||
public enum DiabloDiskType
|
||||
{
|
||||
Diablo31,
|
||||
Diablo44
|
||||
}
|
||||
|
||||
public class DiabloDiskSector
|
||||
{
|
||||
public DiabloDiskSector(byte[] header, byte[] label, byte[] data)
|
||||
{
|
||||
if (header.Length != 4 ||
|
||||
label.Length != 16 ||
|
||||
data.Length != 512)
|
||||
{
|
||||
throw new InvalidOperationException("Invalid sector header/label/data length.");
|
||||
}
|
||||
|
||||
Header = GetUShortArray(header);
|
||||
Label = GetUShortArray(label);
|
||||
Data = GetUShortArray(data);
|
||||
}
|
||||
|
||||
private ushort[] GetUShortArray(byte[] data)
|
||||
{
|
||||
if ((data.Length % 2) != 0)
|
||||
{
|
||||
throw new InvalidOperationException("Array length must be even.");
|
||||
}
|
||||
|
||||
ushort[] array = new ushort[data.Length / 2];
|
||||
|
||||
int offset = 0;
|
||||
for(int i=0;i<array.Length;i++)
|
||||
{
|
||||
array[i] = (ushort)((data[offset]) | (data[offset + 1] << 8));
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public ushort[] Header;
|
||||
public ushort[] Label;
|
||||
public ushort[] Data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulates disk image data for all disk packs used with the
|
||||
/// standard Alto Disk Controller (i.e. the 31 and 44, which differ
|
||||
/// only in the number of cylinders)
|
||||
/// </summary>
|
||||
public class DiabloPack
|
||||
{
|
||||
public DiabloPack(DiabloDiskType type)
|
||||
{
|
||||
_diskType = type;
|
||||
_geometry = new DiskGeometry(type == DiabloDiskType.Diablo31 ? 203 : 406, 2, 12);
|
||||
_sectors = new DiabloDiskSector[_geometry.Cylinders, _geometry.Tracks, _geometry.Sectors];
|
||||
}
|
||||
|
||||
public DiskGeometry Geometry
|
||||
{
|
||||
get { return _geometry; }
|
||||
}
|
||||
|
||||
public void Load(Stream imageStream)
|
||||
{
|
||||
for(int cylinder = 0; cylinder < _geometry.Cylinders; cylinder++)
|
||||
{
|
||||
for(int track = 0; track < _geometry.Tracks; track++)
|
||||
{
|
||||
for(int sector = 0; sector < _geometry.Sectors; sector++)
|
||||
{
|
||||
byte[] header = new byte[4]; // 2 words
|
||||
byte[] label = new byte[16]; // 8 words
|
||||
byte[] data = new byte[512]; // 256 words
|
||||
|
||||
//
|
||||
// Bitsavers images have an extra word in the header for some reason.
|
||||
// ignore it.
|
||||
// TODO: should support different formats ("correct" raw, Alto CopyDisk format, etc.)
|
||||
//
|
||||
imageStream.Seek(2, SeekOrigin.Current);
|
||||
if (imageStream.Read(header, 0, header.Length) != header.Length)
|
||||
{
|
||||
throw new InvalidOperationException("Short read while reading sector header.");
|
||||
}
|
||||
|
||||
if (imageStream.Read(label, 0, label.Length) != label.Length)
|
||||
{
|
||||
throw new InvalidOperationException("Short read while reading sector label.");
|
||||
}
|
||||
|
||||
if (imageStream.Read(data, 0, data.Length) != data.Length)
|
||||
{
|
||||
throw new InvalidOperationException("Short read while reading sector data.");
|
||||
}
|
||||
|
||||
_sectors[cylinder, track, sector] = new DiabloDiskSector(header, label, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (imageStream.Position != imageStream.Length)
|
||||
{
|
||||
throw new InvalidOperationException("Extra data at end of image file.");
|
||||
}
|
||||
}
|
||||
|
||||
public DiabloDiskSector GetSector(int cylinder, int track, int sector)
|
||||
{
|
||||
return _sectors[cylinder, track, sector];
|
||||
}
|
||||
|
||||
private DiabloDiskSector[,,] _sectors;
|
||||
private DiabloDiskType _diskType;
|
||||
private DiskGeometry _geometry;
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Contralto.Memory;
|
||||
using System.IO;
|
||||
|
||||
namespace Contralto.IO
|
||||
{
|
||||
@ -15,10 +16,18 @@ namespace Contralto.IO
|
||||
_system = system;
|
||||
Reset();
|
||||
|
||||
// Wakeup the sector task first thing
|
||||
_system.CPU.WakeupTask(CPU.TaskType.DiskSector);
|
||||
// Load the pack
|
||||
_pack = new DiabloPack(DiabloDiskType.Diablo31);
|
||||
|
||||
|
||||
// TODO: this does not belong here.
|
||||
FileStream fs = new FileStream("Disk\\games.dsk", FileMode.Open, FileAccess.Read);
|
||||
|
||||
_pack.Load(fs);
|
||||
|
||||
fs.Close();
|
||||
|
||||
// Wakeup the sector task first thing
|
||||
_system.CPU.WakeupTask(CPU.TaskType.DiskSector);
|
||||
}
|
||||
|
||||
public ushort KDATA
|
||||
@ -419,31 +428,37 @@ namespace Contralto.IO
|
||||
|
||||
private void LoadSector()
|
||||
{
|
||||
// Fill in sector with test data; eventually actually load real disk data!
|
||||
//
|
||||
// Pull data off disk and pack it into our faked-up sector.
|
||||
// Note that this data is packed in in REVERSE ORDER because that's
|
||||
// how it gets written out and it's how the Alto expects it to be read back in.
|
||||
//
|
||||
DiabloDiskSector sector = _pack.GetSector(_cylinder, _head, _sector);
|
||||
|
||||
|
||||
// Header (2 words data, 1 word cksum)
|
||||
for (int i = _headerOffset + 1; i < _headerOffset + 3; i++)
|
||||
for (int i = _headerOffset + 1, j = 1; i < _headerOffset + 3; i++, j--)
|
||||
{
|
||||
// actual data to be loaded from disk / cksum calculated
|
||||
_sectorData[i] = new DataCell(0xbeef, CellType.Data);
|
||||
_sectorData[i] = new DataCell(sector.Header[j], CellType.Data);
|
||||
}
|
||||
|
||||
_sectorData[_headerOffset + 3].Data = CalculateChecksum(_sectorData, _headerOffset + 1, 2);
|
||||
|
||||
// Label (8 words data, 1 word cksum)
|
||||
for (int i = _labelOffset + 1; i < _labelOffset + 9; i++)
|
||||
for (int i = _labelOffset + 1, j = 7; i < _labelOffset + 9; i++, j--)
|
||||
{
|
||||
// actual data to be loaded from disk / cksum calculated
|
||||
_sectorData[i] = new DataCell(0xdead, CellType.Data);
|
||||
_sectorData[i] = new DataCell(sector.Label[j], CellType.Data);
|
||||
}
|
||||
|
||||
_sectorData[_labelOffset + 9].Data = CalculateChecksum(_sectorData, _labelOffset + 1, 8);
|
||||
|
||||
// sector data (256 words data, 1 word cksum)
|
||||
for (int i = _dataOffset + 1; i < _dataOffset + 257; i++)
|
||||
for (int i = _dataOffset + 1, j = 255; i < _dataOffset + 257; i++, j--)
|
||||
{
|
||||
// actual data to be loaded from disk / cksum calculated
|
||||
_sectorData[i] = new DataCell((ushort)(0x7000 + i), CellType.Data);
|
||||
_sectorData[i] = new DataCell(sector.Data[j], CellType.Data);
|
||||
}
|
||||
|
||||
_sectorData[_dataOffset + 257].Data = CalculateChecksum(_sectorData, _dataOffset + 1, 256);
|
||||
@ -454,7 +469,6 @@ namespace Contralto.IO
|
||||
{
|
||||
// Fill in sector with default data (basically, fill in non-data areas).
|
||||
|
||||
|
||||
//
|
||||
// header delay, 22 words
|
||||
for (int i=0; i < _headerOffset; i++)
|
||||
@ -602,6 +616,8 @@ namespace Contralto.IO
|
||||
private double _elapsedSeekTime;
|
||||
private double _seekClocks;
|
||||
|
||||
// The pack loaded into the drive
|
||||
DiabloPack _pack;
|
||||
|
||||
private AltoSystem _system;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user