можно пойти длиинным путем) запустить в эмууле и сделать снапшот. Чиста для проверки. как раз и снапшоты проверишь, корректность...
В 128 должна надпись бежать плавнее, без рывков и дрожаний
Вид для печати
zebest,
да, я так уже и сделал.
в ZX128 буквы все в разложенном виде. Опять где-то проблема с contendent mem или io.
Я для проверки загрузил через магнитофонный вход - та же проблема с буквами. Ну значит по крайней мере SNA правильно работает.
Надо теперь думать что не так.
goodboy,
Просто из декодера порта 7FFD убрал проверку на A0. В оригинале, как во всех доках написано, А0 должен быть равен 1. Поэтому 7FFC не попадал. Ну раз в фирменном так сделано, значит пусть будет без A0.
- - - Добавлено - - -
Я теперь понимаю почему в Speccy2010 INT начинается в конце предыдущей строки, а не в начале.
У T80 тайминги сдвинуты.
Особо продвинутые чуваки, типа "PRESENTED BY PASHA NIKITIN" ничтоже сумняшеся щёлкали странички через "OUT #0D, A" и даже, о ужас, через "OUT #00, A". Нуачо, работает. :)
Заходим в BASIC, вводим OUT 0, 255 — красота. :)
Руки бы по отрывать дезигнерам спектрума.
- - - Добавлено - - -
Особо умиляет, что в пентагоне на обычной логике тех же времен сделали обращение к памяти без торможения, а на оригинале почему-то не смогли.
- - - Добавлено - - -
Кстати, на Т80 сигнал nRFSH не надо учитывать. Сам-то сигнал есть, а адреса на шине нет (ну или неправильный, я не проверял).
Т80 создавался по принципу "что мы знаем о Z80?". И постепенно допиливался и подгонялся. Наверное, можно считать что его допилили до почти совершенного состояния.
A-Z80 создавался по реальному железу, но реверсили без достаточно тщательности. Это же ведь тоже не автоматические действия. Там достаточно ручной работы. Поэтому есть ошибки. А автор уже отошел от этого проекта и не особо горит желанием фиксить. Я ему писал об ошибках, но он как-то вяло реагирует да и повторяет постоянно что уже многое забыл. А больше никто этим проектом не занимается.
В общем, вначале многообещающий проект превратился в недоделанный.
Это как с MOS6581/8580 - вроде и есть модель, и даже в большинстве случаев работает. Но не всегда. Тоже подгоняют по принципу "наверное, должно быть так". А настоящей модели нет. Точнее есть, но тоже нифига не доделанная.
- - - Добавлено - - -
кстати, по поводу contendent:
Оставлю этот кусок кода из ZXMAK2 тут для истории:
Меня привлекла внимание функция contendPortLate. Круто там навернули аж тройную проверку.Код:namespace ZXMAK2.Hardware.Spectrum
{
public class UlaSpectrum128_Early : UlaDeviceBase
{
public UlaSpectrum128_Early()
{
Name = "ZX Spectrum 128 [early model]";
}
#region IBusDevice
public override void BusInit(IBusManager bmgr)
{
base.BusInit(bmgr);
bmgr.Events.SubscribeRdMem(0xC000, 0x4000, ReadMem4000);
bmgr.Events.SubscribeRdMemM1(0xC000, 0x4000, ReadMem4000);
bmgr.Events.SubscribeRdMem(0xC000, 0xC000, ReadMemC000);
bmgr.Events.SubscribeRdMemM1(0xC000, 0xC000, ReadMemC000);
bmgr.Events.SubscribeRdNoMreq(0xC000, 0x4000, ContendNoMreq);
bmgr.Events.SubscribeWrNoMreq(0xC000, 0x4000, ContendNoMreq);
bmgr.Events.SubscribeRdNoMreq(0xC000, 0xC000, ContendNoMreq);
bmgr.Events.SubscribeWrNoMreq(0xC000, 0xC000, ContendNoMreq);
bmgr.Events.SubscribeRdIo(0x0000, 0x0000, ReadPortAll);
bmgr.Events.SubscribeWrIo(0x0000, 0x0000, WritePortAll);
}
#endregion
public override bool IsEarlyTimings
{
get { return true; }
}
protected override SpectrumRendererParams CreateSpectrumRendererParams()
{
// ZX Spectrum 128
// Total Size: 456 x 311
// Visible Size: 352 x 303 (48+256+48 x 55+192+56)
var timing = SpectrumRenderer.CreateParams();
timing.c_frameTactCount = 70908;
timing.c_ulaLineTime = 228;
timing.c_ulaFirstPaperLine = 63;
timing.c_ulaFirstPaperTact = 64; // 64 [40sync+24border+128scr+32border]
timing.c_ulaBorder4T = true;
timing.c_ulaBorder4Tstage = 2;
timing.c_ulaBorderTop = 32; //55
timing.c_ulaBorderBottom = 32; //56
timing.c_ulaBorderLeftT = 16; //16T
timing.c_ulaBorderRightT = 16; //32T
timing.c_ulaIntBegin = 64 + 2;
timing.c_ulaIntLength = 36; // according to fuse
timing.c_ulaWidth = (timing.c_ulaBorderLeftT + 128 + timing.c_ulaBorderRightT) * 2;
timing.c_ulaHeight = (timing.c_ulaBorderTop + 192 + timing.c_ulaBorderBottom);
return timing;
}
#region Bus Handlers
protected override void WriteMem4000(ushort addr, byte value)
{
contendMemory();
base.WriteMem4000(addr, value);
}
protected override void WriteMemC000(ushort addr, byte value)
{
if ((m_pageC000 & 1) != 0)
contendMemory();
base.WriteMemC000(addr, value);
}
protected void ReadMem4000(ushort addr, ref byte value)
{
contendMemory();
}
protected void ReadMemC000(ushort addr, ref byte value)
{
if ((m_pageC000 & 1) != 0)
contendMemory();
}
#region The same as 48
protected void ContendNoMreq(ushort addr)
{
if (IsContended(addr))
contendMemory();
}
protected override void WritePortFE(ushort addr, byte value, ref bool handled)
{
}
private void WritePortAll(ushort addr, byte value, ref bool handled)
{
contendPortEarly(addr);
contendPortLate(addr);
if ((addr & 0x0001) == 0)
{
int frameTact = (int)((CPU.Tact - 2) % FrameTactCount);
UpdateState(frameTact);
PortFE = value;
}
}
private void ReadPortAll(ushort addr, ref byte value, ref bool handled)
{
contendPortEarly(addr);
contendPortLate(addr);
int frameTact = (int)((CPU.Tact - 1) % FrameTactCount);
base.ReadPortFF(frameTact, ref value);
}
#endregion
#endregion
private bool IsContended(int addr)
{
int test = addr & 0xC000;
return (test == 0x4000 || (test == 0xC000 && (m_pageC000 & 1) != 0));
}
private bool IsPortUla(int addr)
{
return (addr & 1) == 0;
}
#region The same as 48
private void contendMemory()
{
int frameTact = (int)(CPU.Tact % FrameTactCount);
CPU.Tact += m_contention[frameTact];
}
private void contendPortEarly(int addr)
{
if (IsContended(addr))
{
int frameTact = (int)(CPU.Tact % FrameTactCount);
CPU.Tact += m_contention[frameTact];
}
}
private void contendPortLate(int addr)
{
int shift = 1;
int frameTact = (int)((CPU.Tact + shift) % FrameTactCount);
if (IsPortUla(addr))
{
CPU.Tact += m_contention[frameTact];
}
else if (IsContended(addr))
{
CPU.Tact += m_contention[frameTact];
frameTact += m_contention[frameTact];
frameTact++;
frameTact %= FrameTactCount;
CPU.Tact += m_contention[frameTact];
frameTact += m_contention[frameTact];
frameTact++;
frameTact %= FrameTactCount;
CPU.Tact += m_contention[frameTact];
frameTact += m_contention[frameTact];
frameTact++;
frameTact %= FrameTactCount;
}
}
protected override void OnTimingChanged()
{
base.OnTimingChanged();
m_contention = UlaSpectrum48.CreateContentionTable(
SpectrumRenderer.Params,
new int[] { 6, 5, 4, 3, 2, 1, 0, 0, });
}
private int[] m_contention;
#endregion
//protected override void EndFrame()
//{
// base.EndFrame();
// if (IsKeyPressed(System.Windows.Forms.Keys.F1))
// {
// c_ulaBorder4T = true;
// c_ulaBorder4Tstage = 0;
// OnTimingChanged();
// }
// if (IsKeyPressed(System.Windows.Forms.Keys.F2))
// {
// c_ulaBorder4T = true;
// c_ulaBorder4Tstage = 1;
// OnTimingChanged();
// }
// if (IsKeyPressed(System.Windows.Forms.Keys.F3))
// {
// c_ulaBorder4T = true;
// c_ulaBorder4Tstage = 2;
// OnTimingChanged();
// }
// if (IsKeyPressed(System.Windows.Forms.Keys.F4))
// {
// c_ulaBorder4T = true;
// c_ulaBorder4Tstage = 3;
// OnTimingChanged();
// }
// if (IsKeyPressed(System.Windows.Forms.Keys.F5))
// {
// c_ulaBorder4T = false;
// OnTimingChanged();
// }
//}
//private static bool IsKeyPressed(System.Windows.Forms.Keys key)
//{
// return (GetKeyState((int)key) & 0xFF00) != 0;
//}
//[System.Runtime.InteropServices.DllImport("user32")]
//private static extern short GetKeyState(int vKey);
}
public class UlaSpectrum128 : UlaSpectrum128_Early
{
public UlaSpectrum128()
{
Name = "ZX Spectrum 128 [late model]";
}
public override bool IsEarlyTimings
{
get { return false; }
}
protected override SpectrumRendererParams CreateSpectrumRendererParams()
{
var timing = base.CreateSpectrumRendererParams();
timing.c_ulaFirstPaperTact += 1;
timing.c_ulaBorder4Tstage = (timing.c_ulaBorder4Tstage + 1) & 3;
return timing;
}
}
}
У меня ощущение, что опять весь алгоритм придется переписывать :(
Кстати, Shock на ZXMAK2 в режиме ZX128 не работает. Сбрасывается при загрузке цветных полос.
weiv,
понятно. но в ZXMAK2 я не нашел отключение быстрой загрузки с ленты.
Странно, что в режиме ZX48 работает.
- - - Добавлено - - -
В общем, загрузил я Shock в ZXMAK2 ZX128. Надо было просто войти в Basic 48 - и оттуда загрузить. В общем, с таймингами ZX128 в ZXMAK2 отлично выглядит, без глюка в правом нижнем углу.
Только не получается что-то портировать алгоритм на verilog.
В начале сообщения как раз и предлагается грузить демку после USR 0 в режиме 128к. (Проблемы с SHOCK при быстрой загрузке с ленты только у Спектакулятора, в режиме 48к и с отключенным старт/стопом ленты - слетевшие из-за быстрой загрузки тайминги не выравниваются даже после остановки ленты. Но это мелочи).
zebest,
А как этот Song In Lines выглядет на Speccy2010 в режиме ZX128?
О! пофиксил проблему в Shock в правом нижнем углу в режиме ZX128! Остался лишь маленький еле заметный глюк в правом верхнем углу.
zebest,
не, тут дело не в медленной странице. Ты постоянно забываешь, что проблема у меня была из-за цикла рефреша, которую я уже давно пофиксил.
Тут в чем-то другом.
Судя по всему, contendent алгоритм для ZX48 и ZX128 идинаковый. Вон даже в ZXMAK2 он идентичен за исключением проверки на верхние 16кб. И в ZXMAK2 SIL4 выглядет отлично.
Отсюда вывод, что алгоритм contendent в Speccy2010 не совсем правильный не только для ZX128 но и ZX48.
Я пофиксил угол в Shock, но в ZX48 вылезли глюки. Я пока сделал проверку и включаю разные алгоритмы, но это костыль. Так быть не должно.
Надо разобраться в алгоритме ZXMAK2, но я пока не уловил смыл полностью.
- - - Добавлено - - -
zebest, мне не нравится в алгоритме Speccy2010 обратная петля ввиде ulaWaitCancel. На мой взгляд, это костыль.