1
0
mirror of https://github.com/livingcomputermuseum/ContrAlto.git synced 2026-01-20 09:54:35 +00:00

Small tweaks, draft of annotated XMesa microcode assembly added.

This commit is contained in:
Josh Dersch 2015-11-24 17:27:06 -08:00
parent b13944c81c
commit f256042cf4
19 changed files with 145 additions and 77 deletions

View File

@ -103,6 +103,7 @@ namespace Contralto.CPU
Logging.Log.Write(Logging.LogComponent.Microcode, "SWMODE: Current Bank {0}", _microcodeBank);
// 2K ROM
/*
switch(_microcodeBank)
{
case MicrocodeBank.ROM0:
@ -116,10 +117,10 @@ namespace Contralto.CPU
case MicrocodeBank.RAM0:
_microcodeBank = (nextAddress & 0x100) == 0 ? MicrocodeBank.ROM0 : MicrocodeBank.ROM1;
break;
}
} */
// for 1K ROM
//_microcodeBank = _microcodeBank == MicrocodeBank.ROM0 ? MicrocodeBank.RAM0 : MicrocodeBank.ROM0;
_microcodeBank = _microcodeBank == MicrocodeBank.ROM0 ? MicrocodeBank.RAM0 : MicrocodeBank.ROM0;
Logging.Log.Write(Logging.LogComponent.Microcode, "SWMODE: New Bank {0}", _microcodeBank);
}
@ -144,7 +145,7 @@ namespace Contralto.CPU
_lowHalfsel,
Conversion.ToOctal(_ramAddr));
UInt32 data = _uCodeRam[_ramAddr + (_ramBank * 1024)];
UInt32 data = MapRAMWord(_uCodeRam[_ramAddr + (_ramBank * 1024)]);
// Flip the necessary bits before returning them.
// (See table in section 8.3 of HWRef.)
@ -181,7 +182,7 @@ namespace Contralto.CPU
ushort address = (ushort)(_ramAddr + _ramBank * 1024);
_uCodeRam[address] = ((UInt32)(high) << 16) | low;
_uCodeRam[address] = MapRAMWord(((UInt32)(high) << 16) | low);
UpdateRAMCache(address);
}
@ -283,7 +284,7 @@ namespace Contralto.CPU
private static void UpdateRAMCache(ushort address)
{
UInt32 instructionWord = _uCodeRam[address];
_decodeCache[2048 + address] = new MicroInstruction(MapRAMWord(instructionWord));
_decodeCache[2048 + address] = new MicroInstruction(instructionWord);
//Console.WriteLine(_decodeCache[2048 + address]);
}

View File

@ -108,14 +108,42 @@
<None Include="Disassembly\altoIIcode3.mu">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Disassembly\MesaROM-full-annotated.mu" />
<None Include="Disk\bcpl.dsk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Disk\Clark-Games.dsk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Disk\diag.dsk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Disk\games.dsk">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Disk\gamesb.dsk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Disk\gsl.dsk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Disk\mazeWar.dsk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Disk\mazeWarTry2.dsk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Disk\nonprog.dsk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Disk\st76boot.dsk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Disk\tdisk4.dsk">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Disk\xmsmall.dsk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="ROM\2kctl.u3">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>

View File

@ -1071,6 +1071,14 @@ namespace Contralto
_keyMap.Add(Keys.RShiftKey, AltoKey.RShift);
_keyMap.Add(Keys.ControlKey, AltoKey.CTRL);
_keyMap.Add(Keys.Return, AltoKey.Return);
_keyMap.Add(Keys.F1, AltoKey.BlankTop);
_keyMap.Add(Keys.F2, AltoKey.BlankMiddle);
_keyMap.Add(Keys.F3, AltoKey.BlankBottom);
_keyMap.Add(Keys.Back, AltoKey.BS);
_keyMap.Add(Keys.Tab, AltoKey.TAB);
_keyMap.Add(Keys.OemSemicolon, AltoKey.Semicolon);
_keyMap.Add(Keys.OemOpenBrackets, AltoKey.LBracket);
_keyMap.Add(Keys.OemCloseBrackets, AltoKey.RBracket);
}

File diff suppressed because one or more lines are too long

View File

@ -40,15 +40,15 @@
033:175550 - INCLO# 3,3 ; Data address (gets 400 (STA at 14))
034:000000 - JMP 0 ; non-error interrupt mask
035:000000 - JMP 0 ; error interrupt mask
036:000000 - JMP 0 ; reserved
037:000000 - JMP 0 ; disk address
036:000000 - JMP 0 ; reserved ; header checked/written here, this is always zero
037:000000 - JMP 0 ; disk address ; address is checked
; 1st copy of label block at 402 starts here
040:130374 - COMSC# 1,2,SZR ; 000400 - disk address (?)
041:000000 - JMP 0 ; 120374 - previous disk address
040:130374 - COMSC# 1,2,SZR ; 000400 - disk address (?) ; next address ? Not checked; read
041:000000 - JMP 0 ; 120374 - previous disk address ; previous address (checked)
042:000000 - JMP 0 ; 000000 - blank
043:000000 - JMP 0 ; 001000 - num chars
044:176007 - ADC 3,3,SBN ; 000001 - page number
043:000000 - JMP 0 ; 001000 - num chars ; checked
044:176007 - ADC 3,3,SBN ; 000001 - page number ; not checked
045:000001 - JMP 1 ; 000001 - version
046:000000 - JMP 0 ; 000000 - sn high
047:000176 - JMP 176 ; 000176 - sn low
@ -63,7 +63,7 @@
055:176150 - ADCLO# 3,3 ; Data address
056:000000 - JMP 0 ; non-error interrupt mask
057:000000 - JMP 0 ; error interrupt mask
060:000000 - JMP 0 ; reserved
060:000000 - JMP 0 ; reserved ; header checked/written here
061:130374 - COMSC# 1,2,SZR ; disk address
; 2nd copy of label block at 402 starts here (and magically matches

Binary file not shown.

BIN
Contralto/Disk/bcpl.dsk Normal file

Binary file not shown.

BIN
Contralto/Disk/gamesb.dsk Normal file

Binary file not shown.

BIN
Contralto/Disk/gsl.dsk Normal file

Binary file not shown.

BIN
Contralto/Disk/mazeWar.dsk Normal file

Binary file not shown.

Binary file not shown.

BIN
Contralto/Disk/nonprog.dsk Normal file

Binary file not shown.

BIN
Contralto/Disk/st76boot.dsk Normal file

Binary file not shown.

BIN
Contralto/Disk/xmsmall.dsk Normal file

Binary file not shown.

View File

@ -64,7 +64,7 @@ namespace Contralto.Display
_cursorRegLatch = false;
_cursorXLatch = false;
_verticalBlankEndWakeup = new Event(_verticalBlankDuration, null, VerticalBlankEndCallback);
_verticalBlankScanlineWakeup = new Event(_verticalBlankDuration, null, VerticalBlankScanlineCallback);
_horizontalWakeup = new Event(_horizontalBlankDuration, null, HorizontalBlankEndCallback);
_wordWakeup = new Event(_wordDuration, null, WordCallback);
@ -74,7 +74,7 @@ namespace Contralto.Display
private void FieldStart()
{
// Start of Vertical Blanking (end of last field). This lasts for 16 scanline times or so.
// Start of Vertical Blanking (end of last field). This lasts for 34 scanline times or so.
_evenField = !_evenField;
// Wakeup DVT
@ -86,34 +86,47 @@ namespace Contralto.Display
_fields++;
_scanline = _evenField ? 0 : 1;
_scanline = _evenField ? 0 : 1;
// Schedule wakeup for end of vblank
_verticalBlankEndWakeup.TimestampNsec = _verticalBlankDuration;
_system.Scheduler.Schedule(_verticalBlankEndWakeup);
_vblankScanlineCount = 0;
// Schedule wakeup for first scanline of vblank
_verticalBlankScanlineWakeup.TimestampNsec = _verticalBlankScanlineDuration;
_system.Scheduler.Schedule(_verticalBlankScanlineWakeup);
}
private void VerticalBlankEndCallback(ulong timeNsec, ulong skewNsec, object context)
private void VerticalBlankScanlineCallback(ulong timeNsec, ulong skewNsec, object context)
{
// End of VBlank, start new visible frame at beginning of first horizontal blanking period.
// End of VBlank scanline.
_vblankScanlineCount++;
// Wake up DHT
_system.CPU.WakeupTask(TaskType.DisplayHorizontal);
_dataBuffer.Clear();
_dwtBlocked = false;
_dhtBlocked = false;
// Schedule HBlank wakeup for end of first HBlank
_horizontalWakeup.TimestampNsec = _horizontalBlankDuration - skewNsec;
_system.Scheduler.Schedule(_horizontalWakeup);
// Run MRT
//_system.CPU.WakeupTask(TaskType.MemoryRefresh);
_system.CPU.WakeupTask(TaskType.MemoryRefresh);
if (_vblankScanlineCount > (_evenField ? 33 : 34))
{
// End of vblank:
// Wake up DHT
_system.CPU.WakeupTask(TaskType.DisplayHorizontal);
// Run CURT
_system.CPU.WakeupTask(TaskType.Cursor);
_dataBuffer.Clear();
_dwtBlocked = false;
_dhtBlocked = false;
// Run CURT
_system.CPU.WakeupTask(TaskType.Cursor);
// Schedule HBlank wakeup for end of first HBlank
_horizontalWakeup.TimestampNsec = _horizontalBlankDuration - skewNsec;
_system.Scheduler.Schedule(_horizontalWakeup);
}
else
{
// Do the next vblank scanline
_verticalBlankScanlineWakeup.TimestampNsec = _verticalBlankScanlineDuration;
_system.Scheduler.Schedule(_verticalBlankScanlineWakeup);
}
}
private void HorizontalBlankEndCallback(ulong timeNsec, ulong skewNsec, object context)
@ -121,14 +134,7 @@ namespace Contralto.Display
// Reset scanline word counter
_word = 0;
// Deal with SWMODE latches for the scanline we're about to draw
if (_swModeLatch)
{
_lowRes = _lowResLatch;
_whiteOnBlack = _whiteOnBlackLatch;
_swModeLatch = false;
}
// Deal with cursor latches for this scanline
if (_cursorRegLatch)
{
_cursorRegLatched = _cursorReg;
@ -141,9 +147,6 @@ namespace Contralto.Display
_cursorXLatch = false;
}
// Run MRT on end of hsync
_system.CPU.WakeupTask(TaskType.MemoryRefresh);
// Schedule immediate wakeup for first word on this scanline
_wordWakeup.TimestampNsec = 0;
_system.Scheduler.Schedule(_wordWakeup);
@ -213,15 +216,24 @@ namespace Contralto.Display
{
// More scanlines to do.
// Run CURT at end of scanline
_system.CPU.WakeupTask(TaskType.Cursor);
// Run CURT and MRT at end of scanline
_system.CPU.WakeupTask(TaskType.Cursor);
_system.CPU.WakeupTask(TaskType.MemoryRefresh);
// Schedule HBlank wakeup for end of next HBlank
_horizontalWakeup.TimestampNsec = _horizontalBlankDuration - skewNsec;
_system.Scheduler.Schedule(_horizontalWakeup);
_dwtBlocked = false;
_dataBuffer.Clear();
_dataBuffer.Clear();
// Deal with SWMODE latches for the scanline we're about to draw
if (_swModeLatch)
{
_lowRes = _lowResLatch;
_whiteOnBlack = _whiteOnBlackLatch;
_swModeLatch = false;
}
}
}
else
@ -367,13 +379,16 @@ namespace Contralto.Display
// ~35 scanlines for vblank (1330uS)
private const double _scale = 1.0;
private const ulong _verticalBlankDuration = (ulong)(665000.0 * _scale); // 665uS
private const ulong _verticalBlankScanlineDuration = (ulong)(38080 * _scale); // 38uS
private const ulong _horizontalBlankDuration = (ulong)(6084 * _scale); // 6uS
private const ulong _wordDuration = (ulong)(842.0 * _scale); // 32/38uS
private int _vblankScanlineCount;
//
// Scheduler events
//
private Event _verticalBlankEndWakeup;
private Event _verticalBlankScanlineWakeup;
private Event _horizontalWakeup;
private Event _wordWakeup;
}

View File

@ -264,10 +264,12 @@ namespace Contralto.IO
_seclateEvent.TimestampNsec = _seclateDuration;
_system.Scheduler.Schedule(_seclateEvent);
}
// Schedule next sector pulse
_sectorEvent.TimestampNsec = _sectorDuration - skewNsec;
_system.Scheduler.Schedule(_sectorEvent);
else
{
// Schedule next sector pulse
_sectorEvent.TimestampNsec = _sectorDuration - skewNsec;
_system.Scheduler.Schedule(_sectorEvent);
}
}
private void WordCallback(ulong timeNsec, ulong skewNsec, object context)
@ -280,6 +282,12 @@ namespace Contralto.IO
_wordEvent.TimestampNsec = _wordDuration - skewNsec;
_system.Scheduler.Schedule(_wordEvent);
}
else
{
// // Schedule next sector pulse immediately
_sectorEvent.TimestampNsec = skewNsec;
_system.Scheduler.Schedule(_sectorEvent);
}
}
private void SeekCallback(ulong timeNsec, ulong skewNsec, object context)
@ -383,7 +391,7 @@ namespace Contralto.IO
_kStat |= 0x0040;
// And figure out how long this will take.
_seekDuration = CalculateSeekTime();
_seekDuration = (ulong)(CalculateSeekTime() / (ulong)(Math.Abs(_destCylinder - _cylinder) + 1));
_seekEvent.TimestampNsec = _seekDuration;
_system.Scheduler.Schedule(_seekEvent);
@ -403,7 +411,7 @@ namespace Contralto.IO
//
double seekTimeMsec = 15.0 + 8.6 * Math.Sqrt(dt);
return (ulong)(seekTimeMsec * Conversion.MsecToNsec) / 100; // hack to speed things up
return (ulong)(seekTimeMsec * Conversion.MsecToNsec); // hack to speed things up
}
/// <summary>
@ -435,13 +443,7 @@ namespace Contralto.IO
// actual data (it could be the pre-header delay, inter-record gaps or sync words)
// and we may not actually end up doing anything with it, but we may
// need it to decide whether to do anything at all.
//
if (_sectorWordIndex >= _sectorWordCount)
{
return;
}
//
ushort diskWord = _sectorData[_sectorWordIndex].Data;
bool bWakeup = false;
@ -463,9 +465,11 @@ namespace Contralto.IO
{
if (!_xferOff)
{
if (_debugRead)
// Debugging: on a read/check, if we are overwriting a word that was never read by the
// microcode via KDATA, log it.
if (_debugRead && (((KADR & 0x00c0) >> 6) == 0 || ((KADR & 0x00c0) >> 6) == 1))
{
//Console.WriteLine("--- missed word {0}({1}) ---", _sectorWordIndex, _kDataRead);
Console.WriteLine("--- missed sector word {0}({1}) ---", _sectorWordIndex, _kDataRead);
}
Log.Write(LogType.Verbose, LogComponent.DiskWordTask, "Sector {0} Word {1} read into KDATA", _sector, Conversion.ToOctal(diskWord));
@ -645,10 +649,10 @@ namespace Contralto.IO
// $MIR0BL $177775; DISK INTERRECORD PREAMBLE IS 3 WORDS <<-- writing
// $MRPAL $177775; DISK READ POSTAMBLE LENGTH IS 3 WORDS
// $MWPAL $177773; DISK WRITE POSTAMBLE LENGTH IS 5 WORDS <<-- writing, clearly.
private static double _scale = 1.0;
private static double _scale = 1.5;
private static ulong _sectorDuration = (ulong)((40.0 / 12.0) * Conversion.MsecToNsec * _scale); // time in nsec for one sector
private static int _sectorWordCount = 269 + 22 + 34; // Based on : 269 data words (+ cksums) / sector, + X words for delay / preamble / sync
private static ulong _wordDuration = (ulong)((_sectorDuration / (ulong)(_sectorWordCount + 1)) * _scale); // time in nsec for one word
private static ulong _wordDuration = (ulong)((_sectorDuration / (ulong)(_sectorWordCount)) * _scale); // time in nsec for one word
private int _sectorWordIndex; // current word being read
private Event _sectorEvent;
@ -662,7 +666,7 @@ namespace Contralto.IO
// SECLATE data.
// 8.5uS for seclate delay (approx. 50 clocks)
private static ulong _seclateDuration = 85 * Conversion.UsecToNsec;
private static ulong _seclateDuration = (ulong)(85.0 * Conversion.UsecToNsec * _scale);
private bool _seclateEnable;
private bool _seclate;
private Event _seclateEvent;

View File

@ -44,7 +44,7 @@ namespace Contralto.Logging
static Log()
{
// TODO: make configurable
_components = LogComponent.None; //LogComponent.Memory; // | LogComponent.Microcode;
_components = LogComponent.Memory; // LogComponent.DiskController | LogComponent.DiskSectorTask;
_type = LogType.Normal | LogType.Warning | LogType.Error;
}

View File

@ -29,11 +29,16 @@ namespace Contralto.Memory
{
// Check for XM registers; this occurs regardless of XM flag since it's in the I/O page.
if (address >= _xmBanksStart && address < _xmBanksStart + 16)
{
return _xmBanks[address - _xmBanksStart];
{
return (ushort)(0xfff0 |_xmBanks[address - _xmBanksStart]);
}
else
{
/*
if (extendedMemory)
{
Log.Write(LogComponent.Memory, "Extended memory read, bank {0} address {1}, read {2}", GetBankNumber(task, extendedMemory), Conversion.ToOctal(address), Conversion.ToOctal(_mem[address + 0x10000 * GetBankNumber(task, extendedMemory)]));
} */
address += 0x10000 * GetBankNumber(task, extendedMemory);
return _mem[address];
}
@ -52,6 +57,11 @@ namespace Contralto.Memory
}
else
{
/*
if (extendedMemory)
{
Log.Write(LogComponent.Memory, "Extended memory write, bank {0} address {1}, data {2}", GetBankNumber(task, extendedMemory), Conversion.ToOctal(address), Conversion.ToOctal(data));
} */
address += 0x10000 * GetBankNumber(task, extendedMemory);
_mem[address] = data;
}
@ -64,7 +74,7 @@ namespace Contralto.Memory
private int GetBankNumber(TaskType task, bool extendedMemory)
{
return extendedMemory ? _xmBanks[(int)task] & 0x3 : (_xmBanks[(int)task] & 0xc) >> 2;
return extendedMemory ? (_xmBanks[(int)task]) & 0x3 : ((_xmBanks[(int)task]) & 0xc) >> 2;
}
private readonly MemoryRange[] _addresses =

View File

@ -1,11 +1,12 @@
namespace Contralto
using Contralto.CPU;
namespace Contralto
{
class Program
{
static void Main(string[] args)
{
AltoSystem system = new AltoSystem();
AltoSystem system = new AltoSystem();
// for now everything is driven through the debugger
Debugger d = new Debugger(system);