A jak mi/nam zdradzisz jak się robi taką konfigurację, to w pewnej nieodległej przyszłości mógłbym ja lub ktoś to ma akurat więcej czasu, taki konfig wykonać.
Jasne, konfiguracja jak i cala emulacja portow io jest robiona za pomoca kompilowanego skryptu, ktory mozna samemu napisac. W tej chwili kod do konfigu spectrum wyglada mniej wiecej tak:
#include "TheProfiler"
forward public ULAWrite(Address, Data);
forward public ULARead(Address, Data);
forward public PrinterWrite(Address, Data);
public InitScript()
{
SetDeviceName("ZX Spectrum 48k","1.0","Union Systems","Copyright 2016 Union Systems");
SetDeviceCPU("Z80", 3500000, DEVICE_GENERIC);
AddMemoryBlock("KERNEL ROM", 0x0000,0x4000, MEMORY_READONLY, 0, "", "Sinclair/48.rom");
AddMemoryBlock("Video RAM", 0x4000,0x1800, MEMORY_READWRITE, 0, "", "");
AddMemoryBlock("Video Attributes RAM", 0x5800,0x300, MEMORY_READWRITE, 0, "", "");
AddMemoryBlock("Base RAM", 0x5b00,0xa500, MEMORY_READWRITE, 0, "", "");
AddMemoryBlock("IO Ports", 0x00,0x100, IOMEMORY_READWRITE, 0, "", "");
AddIODriver(0x00fe,0x00fe, "ULARead", "ULAWrite");
AddIODriver(0x00fb,0x00fb, "", "PrinterWrite");
}
public FinishScript()
{
}
public AboutScript()
{
printf("ZX Spectrum 48k device configuration v 1.0. Copyright 2016 Union Systems.");
printf("Developed by Piotr Drapich.");
}
// ULA emulation
public ULAWrite(Address, Data)
{
//TODO
}
public ULARead(Address, Data)
{
//TODO
return Data;
}
// printer emulation
public PrinterWrite(Address, Data)
{
static textbuf[255];
static textbufptr=0;
if (Data==13)
{
textbuf[textbufptr]=0;
printf(textbuf);
textbufptr=0;
return;
}
textbuf[textbufptr]=Data;
textbufptr++;
}
Przy ladowaniu urzadzenia jest wywolywany InitScript, potem AboutScript, przy zamknieciu FinishScript.
Inne funkcje skryptu sa callbackami, podawanymi jako parametry np przy definiowaniu bloku pamieci czy portow io i wywolywanymi przy zapisie/odczycie do danego obszaru pamieci.
Np dodanie obslugi portu drukarki jest zdefiniowane w AddIODriver(0x00fb,0x00fb, "", "PrinterWrite");
Prototyp tej funkcji to AddIODriver(StartIOAddress,EndIOAddress, IOReadCallBack[], IOWriteCallBack[]);
Dodaje ona read albo write callback dla zakresu portow, zdefiniowanych przez StartIOAddress I EndIOAddress.
Przy profilowaniu programu, w momencie wykonania np out (#fb),a zostanie wywolany callback PrinterWrite z zawartoscia rejestru a jako Data, adresem #fb jako Address.
PrinterWrite jest prosta funkcja buforujaca znaki az do otrzymania LineFeed, wtedy zebrany tekst jest wyswietlany za pomoca printf w oknie konsoli programu (to na dole po lewej stronie na screenshocie
Analogiczne callbacki mozna dodac do kazdego bloku pamieci. Np. dodajac taki callback do bloku pamieci video ramu mozna za pomoca udostepnianego interfeju wyswietlac interpretacje zawartosci tej pamieci w oknie user view monitora pamieci. Dodajac obsluge pozostalych portow i pare innych rzeczy mozna stworzyc prosty emulator wybranego urzadzenia.
btw: W programie powyzszy kod jest dostepny tylko skompilowany w formie binarnej, ale jest mozliwosc pisania i kompilowania wlasnych skryptow.