точнее эмулируют именно 48ую модель.
вообще именно SNA - неудачный формат. при сохранении PC пишется в стек,
а если стек в данных (что частенько встречается в программах) они будут запороты
Вид для печати
можешь попробовать создать нужный тебе SNA файл - первые 27 + 49152 байта как из 48-го снапшота - затем добавляешь 2 байта PC, 1 байт Состояние порта #7FFD и 1 байт Выбор ПЗУ TR-DOS (0 - неактивно, 1 - активно)
итого должен получиться файл по размеру обычного SNA-48 плюс 4 байта.
вот
А зачем они это сделали? понимаю, что вопрос к разработчикам..
- - - Добавлено - - -
Но ведь загружаяе 48(не имея доп банок памяти в файле), можно ведь оставить заглушку(бит) в нуле! это у всех эмулей?
- - - Добавлено - - -
Что-то тут не так
- - - Добавлено - - -
или функция прерывания что-то делает стандартная? дак тем более у меня 128 бэйсик пзу тогда тоже делает... нипаняяяятна
- - - Добавлено - - -
Я подозреваю, что где-то я в сохранении сна косяк допустил
- - - Добавлено - - -
Это конечно не критично, но даже сна48 должен сохранять возможность переключения банок, даже если это ни к чему не приведёт
- - - Добавлено - - -
Это конечно не критично, но даже сна48 должен сохранять возможность переключения банок, даже если это ни к чему не приведёт
Оно так всё и есть, по размеру всё сохраняется... ну сам вот посмотри
Код:#include <ZX_SNA_Saver.h>
#include <fstream.h>
bool ZX_SNA_Saver::SaveSna(GensCompiler & compiler, AnsiString filename)
{
ByteVector ram;
unsigned int start = compiler.GetStartAddress();
FillStandartRAM(ram, start);
//Определим 128k или 48k
bool is128 = false;
for (int i = 0; i < 8; i++)
if (i != 2) is128 |= compiler.BynaryCodeSize(i) > 0;
//банк 5
if (compiler.BynaryCodeSize(5) > 0)
{
for (unsigned int i = 0; i < compiler.BynaryCodeSize(5); i++)
{
if (i < 0xC000)
ram[i] = compiler.GetCodeByte(5,i);
else
{
ShowMessage("Внимание! Данные в банке 5 вышли за пределы #FFFF и будут обрезаны.");
break;
}
}
if (compiler.BynaryCodeSize(5) + 0x4000 > start - 2)
ShowMessage("Внимание! Начало основного кода перекрывает данные в банке 5.");
}
//банк 2
if (start <= 0x4000)
ShowMessage("Внимание! Область стека перекрывает ПЗУ.");
for (unsigned int i = 0; i < compiler.BynaryCodeSize(2); i++)
{
if (start + i <= 0xFFFF)
ram[start + i - 0x4000] = compiler.GetCodeByte(2,i);
else
{
ShowMessage("Внимание! Основной код вышел за пределы #FFFF и будет обрезан.");
break;
}
}
//банк 0
if (compiler.BynaryCodeSize(0) > 0)
{
if (start + compiler.BynaryCodeSize(2) >= 0xC000)
ShowMessage("Внимание! Данные в банке 0 перекрывают основной код.");
for (unsigned int i = 0; i < compiler.BynaryCodeSize(0); i++)
{
if (i < 0x4000)
ram[i + 0xC000 - 0x4000] = compiler.GetCodeByte(0,i);
else
{
ShowMessage("Внимание! Данные в банке 0 вышли за пределы #FFFF и будет обрезан.");
break;
}
}
}
ByteVector sna;
FillHeader(sna, start);
if (!is128)
{
//Запишем в стек адрес старта
ram[start - 2 - 16384] = start % 256;
ram[start - 1 - 16384] = start / 256;
}
for (int i = 0; i < 0xC000; i++) sna.push_back(ram[i]);
//Если 128k
if (is128)
{
sna.push_back(start % 256); //Регистровая пара PC
sna.push_back(start / 256);
sna.push_back(16); //Состояние порта #7FFD
sna.push_back(0); //ПЗУ TR-DOS (0 - неактивно, 1 - активно)
// Банки 1 3 4 6 7
this->Addpage(compiler, sna, 1);
this->Addpage(compiler, sna, 3);
this->Addpage(compiler, sna, 4);
this->Addpage(compiler, sna, 6);
this->Addpage(compiler, sna, 7);
}
//Сохраним снимок
ofstream file;
file.open(filename.c_str(), ios::out | ios::binary);
for (unsigned int i = 0; i < sna.size(); i++)
{
file.write(&sna[i], 1);
}
file.close();
return true;
}
void ZX_SNA_Saver::FillHeader(ByteVector & mas, unsigned int start)
{
//Заполним заголовок sna(27 байт)
mas.push_back(63); //регистр I
mas.push_back(0); //HL'
mas.push_back(0);
mas.push_back(0); //DE'
mas.push_back(0);
mas.push_back(32); //BC'
mas.push_back(23);
mas.push_back(68); //AF'
mas.push_back(0);
mas.push_back(168); //HL
mas.push_back(16);
mas.push_back(185); //DE
mas.push_back(92);
mas.push_back(0); //BC
mas.push_back(0);
mas.push_back(58); //IY
mas.push_back(92);
mas.push_back(0); //IX
mas.push_back(0);
mas.push_back(6); //Флаги прерываний
mas.push_back(0); //Регистр регенерации динамической памяти R
mas.push_back(116); //AF
mas.push_back(0);
mas.push_back((start - 2) % 256); //SP
mas.push_back((start - 2) / 256);
mas.push_back(1); //Режим прерываний
mas.push_back(7); //Цвет бордюра
}
void ZX_SNA_Saver::FillStandartRAM(ByteVector & ram, unsigned int start)
{
ram.insert(ram.end(), 6144, 0); //Данные экрана
ram.insert(ram.end(), 768, 56); //Данные атрибутов
//23296
//ram.insert(ram.end(), 256, 0); //Буфер принтера(или если 128, доп область переменных)
ram.insert(ram.end(), 89, 0); //Буфер принтера(или если 128, доп область переменных)
ram.push_back(16); // копия порта
ram.insert(ram.end(), 166, 0); //Буфер принтера(или если 128, доп область переменных)
//23388 = копия порта
//Системные переменные
//KSTATE
ram.push_back(255);
ram.insert(ram.end(), 3, 0);
ram.push_back(255);
ram.insert(ram.end(), 3, 0);
ram.push_back(0); //LAST_K
ram.push_back(35); //REPDEL
ram.push_back(5); //PEPPER
ram.insert(ram.end(), 5, 0); //DEFADD..TVDATA
//STRMS
ram.push_back(1); //-3
ram.push_back(0);
ram.push_back(6); //-2
ram.push_back(0);
ram.push_back(11); //-1
ram.push_back(0);
ram.push_back(1); //0
ram.push_back(0);
ram.push_back(1); //1
ram.push_back(0);
ram.push_back(6); //2
ram.push_back(0);
ram.push_back(16); //3
ram.push_back(0);
ram.insert(ram.end(), 24, 0); //4 и далее
ram.push_back(0); //CHARS
ram.push_back(60);
ram.push_back(64); //RASP
ram.insert(ram.end(), 3, 0); //PIP,ERR NR,FLAGS
ram.push_back(33); //TV FLAG
ram.push_back(80); //ERR SP
ram.push_back(255);
ram.insert(ram.end(), 9, 0); //LIST SP..SUBPPC
ram.push_back(56); //BORDCR
ram.insert(ram.end(), 2, 0); //Е_РРС
ram.push_back(203); //VARS
ram.push_back(92);
ram.insert(ram.end(), 2, 0); //DEST
ram.push_back(182); //CHANS
ram.push_back(92);
ram.push_back(182); //CURCHL
ram.push_back(92);
ram.push_back(203); //PROG
ram.push_back(92);
ram.insert(ram.end(), 2, 0); //NXTLIN
ram.push_back(202); //DATADD
ram.push_back(92);
ram.push_back(204); //E_LINE
ram.push_back(92);
ram.push_back(204); //K_CUR
ram.push_back(92);
ram.insert(ram.end(), 4, 0); //СН_АDD,X_PTR
ram.push_back(206); //WORKSP
ram.push_back(92);
ram.push_back(206); //STKBOT
ram.push_back(92);
ram.push_back(206); //STKEND
ram.push_back(92);
ram.push_back(0); //BREG
ram.push_back(146); //MEM
ram.push_back(92);
ram.push_back(16); //FLAGS2
ram.push_back(2); //DF_SZ
ram.insert(ram.end(), 12, 0); //S_TOP..SEED
ram.push_back(109); //FRAMES
ram.push_back(2);
ram.push_back(0);
ram.push_back(88); //UDG
ram.push_back(255);
ram.insert(ram.end(), 2, 0); //COORDS
ram.push_back(33); //P_POSN
ram.push_back(0); //PR_CC
ram.push_back(91); //NOT_USED
ram.push_back(5); //ЕСНО_Е
ram.push_back(23);
ram.push_back(0); //DF_CC
ram.push_back(64);
ram.push_back(252); //DFCCL
ram.push_back(80);
ram.push_back(33); //S_POSN
ram.push_back(24);
ram.push_back(5); //SPONSL
ram.push_back(23);
ram.push_back(1); //SCR_CT
ram.push_back(56); //ATTR_P
ram.push_back(0); //MASK_P
ram.push_back(56); //ATTR_T
ram.push_back(0); //MASK_T
ram.push_back(0); //P_FLAG
ram.insert(ram.end(), 30, 0); //МЕМВОТ
ram.insert(ram.end(), 2, 0); //NMIADD
//RAMTOP
ram.push_back((start - 1) % 256);
ram.push_back((start - 1) / 256);
ram.insert(ram.end(), 2, 255); //P_RAMT
//Карта микродрайва + CHANS
ram.push_back(244);
ram.push_back(9);
ram.push_back(168);
ram.push_back(16);
ram.push_back(75);
ram.push_back(244);
ram.push_back(9);
ram.push_back(196);
ram.push_back(21);
ram.push_back(83);
ram.push_back(129);
ram.push_back(15);
ram.push_back(196);
ram.push_back(21);
ram.push_back(82);
ram.push_back(244);
ram.push_back(9);
ram.push_back(196);
ram.push_back(21);
ram.push_back(80);
ram.push_back(128);
ram.push_back(128);
ram.push_back(13);
ram.push_back(128);
//заполним нулями
ram.insert(ram.end(), 41778, 0);
}
void ZX_SNA_Saver::Addpage(GensCompiler & compiler, ByteVector & sna, int page)
{
if (compiler.BynaryCodeSize(page) > 16384 )
ShowMessage("Внимание! Код в банке "+IntToStr(page)+" привысил размер #4000 и будет обрезан.");
for (unsigned int i = 0; i < 16384; i++)
{
if (i < compiler.BynaryCodeSize(page))
sna.push_back(compiler.GetCodeByte(page,i));
else
sna.push_back(0);
}
}
Но ведь эмули со временем начали понимать формат 128. Заглушку оставили(бит порта)?
- - - Добавлено - - -
или на "старое"было плевать? А можно ведь сделать игру, которая вмещается в 48, но использует 128 формат(переключение экранов)
- - - Добавлено - - -
Вообще я жду ответ на вопрос: Эмуляторы , видя 48 снапшот, ставят бит заглушки?
Не. Они переключаются на 48 модель.
Ну, значит костыль, в ненужной банке, вопрос исчерпан(нверное)
А вообще хорошо бы было, если бы создатели эмулей, при приёме в своё лоно 48к, не ставили заглушку
Хрессу вот ваще никогда машину не переключает. Значит все-таки разные эмуляторы бывают, а не только спекулятор :)