1
0
mirror of https://github.com/samstyle/Xpeccy.git synced 2025-04-19 00:04:05 +03:00

Custom ZX Spectrum palettes support

This commit is contained in:
dotkoval 2025-02-25 19:17:23 +01:00
parent 3c47a7c3e6
commit dbfe9b2eca
15 changed files with 243 additions and 5 deletions

18
conf/palettes/atm.txt Normal file
View File

@ -0,0 +1,18 @@
; ATM-Turbo palette?
#000000 ; Black
#0000aa ; Blue
#aa0000 ; Red
#aa00aa ; Magenta
#00aa00 ; Green
#00aaaa ; Cyan
#aaaa00 ; Yellow
#aaaaaa ; White
#000000 ; Bright Black
#0000ff ; Bright Blue
#ff0000 ; Bright Red
#ff00ff ; Bright Magenta
#00ff00 ; Bright Green
#00ffff ; Bright Cyan
#ffff00 ; Bright Yellow
#ffffff ; Bright White

18
conf/palettes/next.txt Normal file
View File

@ -0,0 +1,18 @@
; ZX Spectrum Next FPGA core HDMI palette
#000000 ; Black
#0000b0 ; Blue
#b00000 ; Red
#b000b0 ; Magenta
#00b000 ; Green
#00b0b0 ; Cyan
#b0b000 ; Yellow
#b0b0b0 ; White
#000000 ; Bright Black
#0000ff ; Bright Blue
#ff0000 ; Bright Red
#ff00ff ; Bright Magenta
#00ff00 ; Bright Green
#00ffff ; Bright Cyan
#ffff00 ; Bright Yellow
#ffffff ; Bright White

18
conf/palettes/pulsar.txt Normal file
View File

@ -0,0 +1,18 @@
; Well-known Pulsar palette
#000000 ; Black
#0000cd ; Blue
#cd0000 ; Red
#cd00cd ; Magenta
#00cd00 ; Green
#00cdcd ; Cyan
#cdcd00 ; Yellow
#cdcdcd ; White
#000000 ; Bright Black
#0000ff ; Bright Blue
#ff0000 ; Bright Red
#ff00ff ; Bright Magenta
#00ff00 ; Bright Green
#00ffff ; Bright Cyan
#ffff00 ; Bright Yellow
#ffffff ; Bright White

18
conf/palettes/schafft.txt Normal file
View File

@ -0,0 +1,18 @@
; Art-palette by Schafft
#000000 ; Black
#1c0077 ; Blue
#a2232a ; Red
#8417a8 ; Magenta
#7b8707 ; Green
#2d91c3 ; Cyan
#daa73e ; Yellow
#bababa ; White
#000000 ; Bright Black
#2100a5 ; Bright Blue
#e02c35 ; Bright Red
#b71be8 ; Bright Magenta
#a7ba08 ; Bright Green
#42c2ff ; Bright Cyan
#ffd66d ; Bright Yellow
#fcfcfc ; Bright White

View File

@ -0,0 +1,18 @@
; Palette used by Spectaculator emulator
#000000 ; Black
#0000ce ; Blue
#ce0000 ; Red
#ce00ce ; Magenta
#00cb00 ; Green
#00cbce ; Cyan
#cecb00 ; Yellow
#cecbce ; White
#000000 ; Bright Black
#0000ff ; Bright Blue
#ff0000 ; Bright Red
#ff00ff ; Bright Magenta
#00fb00 ; Bright Green
#00fbff ; Bright Cyan
#fffb00 ; Bright Yellow
#fffbff ; Bright White

19
conf/palettes/wiki1.txt Normal file
View File

@ -0,0 +1,19 @@
; Wiki-Palette #1
; https://en.wikipedia.org/wiki/ZX_Spectrum_graphic_modes#Colour_palette
#000000 ; Black
#0100ce ; Blue
#cf0100 ; Red
#cf01ce ; Magenta
#00cf15 ; Green
#01cfcf ; Cyan
#cfcf15 ; Yellow
#cfcfcf ; White
#000000 ; Bright Black
#0200fd ; Bright Blue
#ff0201 ; Bright Red
#ff02fd ; Bright Magenta
#00ff1c ; Bright Green
#02ffff ; Bright Cyan
#ffff1d ; Bright Yellow
#ffffff ; Bright White

19
conf/palettes/wiki2.txt Normal file
View File

@ -0,0 +1,19 @@
; Wiki-Palette #2
; https://en.wikipedia.org/wiki/List_of_8-bit_computer_hardware_graphics#ZX_Spectrum
#000000 ; Black
#001dc8 ; Blue
#d8240f ; Red
#d530c9 ; Magenta
#00c721 ; Green
#00c9cb ; Cyan
#ceca27 ; Yellow
#cbcbcb ; White
#000000 ; Bright Black
#0027fb ; Bright Blue
#ff3016 ; Bright Red
#ff3ffc ; Bright Magenta
#00f92c ; Bright Green
#00fcfe ; Bright Cyan
#fffd33 ; Bright Yellow
#ffffff ; Bright White

View File

@ -1095,6 +1095,7 @@ void MainWin::optApply() {
Computer* comp = conf.prof.cur->zx;
fillUserMenu();
updateWindow();
loadPalette(comp, true);
#ifdef USENETWORK
if (srv.serverPort() != conf.port) {
closeServer();
@ -1130,6 +1131,7 @@ void MainWin::bookmarkSelected(QAction* act) {
void MainWin::onPrfChange() {
Computer* comp = conf.prof.cur->zx;
if (comp->firstRun) {
loadPalette(comp);
compReset(comp, RES_DEFAULT);
comp->firstRun = 0;
}

View File

@ -183,10 +183,7 @@ void zx_set_pal(Computer* comp) {
int i;
xColor xcol;
for (i = 0; i < 16; i++) {
xcol.b = (i & 1) ? ((i & 8) ? 0xff : 0xaa) : 0x00;
xcol.r = (i & 2) ? ((i & 8) ? 0xff : 0xaa) : 0x00;
xcol.g = (i & 4) ? ((i & 8) ? 0xff : 0xaa) : 0x00;
vid_set_col(comp->vid, i, xcol);
vid_reset_col(comp->vid, i);
}
}

View File

@ -485,6 +485,17 @@ void vid_set_col(Video* vid, int i, xColor xcol) {
vid->gpal[i & 0xff] = outcol | (outcol << 8) | (outcol << 16) | (0xff << 24);
}
// set base color palette (used for preset loading)
void vid_set_bcol(Video* vid, int i, xColor xcol) {
vid->bpal[i & 0xff] = xcol.r | (xcol.g << 8) | (xcol.b << 16) | (0xff << 24);
}
// set current palette color from preloaded preset
void vid_reset_col(Video* vid, int i) {
vid->pal[i & 0xff] = vid->bpal[i & 0xff];
}
// video drawing
void vidDrawBorder(Video* vid) {

View File

@ -153,6 +153,7 @@ struct Video {
unsigned char paln; // high bits = palete number
uint32_t pal[256]; // ABGR inside int, R = LSB, A = FF
uint32_t gpal[256]; // greyscale copy of pal
uint32_t bpal[256]; // base palette (loaded preset)
int vmode;
cbvid cbDot; // call every dot
@ -366,6 +367,8 @@ void vid_get_screen(Video*, unsigned char*, int, int, int);
void vid_set_grey(int);
xColor vid_get_col(Video*, int);
void vid_set_col(Video*, int, xColor);
void vid_set_bcol(Video*, int, xColor);
void vid_reset_col(Video*, int);
void tslUpdatePorts(Video*);

View File

@ -62,6 +62,8 @@ void conf_init(char* wpath, char* confdir) {
mkdir(conf.path.prfDir.c_str() ,0777);
conf.path.shdDir = conf.path.confDir + "/shaders";
mkdir(conf.path.shdDir.c_str() ,0777);
conf.path.palDir = conf.path.confDir + "/palettes";
mkdir(conf.pat0h.palDir.c_str() ,0777);
conf.path.confFile = conf.path.confDir + "/config.conf";
conf.path.boot = conf.path.confDir + "/boot.$B";
#elif defined(__WIN32)
@ -78,12 +80,14 @@ void conf_init(char* wpath, char* confdir) {
conf.path.romDir = conf.path.confDir + "\\roms";
conf.path.prfDir = conf.path.confDir + "\\profiles";
conf.path.shdDir = conf.path.confDir + "\\shaders";
conf.path.palDir = conf.path.confDir + "\\palettes";
conf.path.confFile = conf.path.confDir + "\\config.conf";
conf.path.boot = conf.path.confDir + "\\boot.$B";
mkdir(conf.path.confDir.c_str());
mkdir(conf.path.romDir.c_str());
mkdir(conf.path.prfDir.c_str());
mkdir(conf.path.shdDir.c_str());
mkdir(conf.path.palDir.c_str());
#endif
conf.scrShot.format = "png";
// Pentagon geometry:
@ -153,6 +157,7 @@ void saveConfig() {
fprintf(cfile, "bordersize = %i\n", int(conf.brdsize * 100));
fprintf(cfile, "noflick = %i\n", noflic);
fprintf(cfile, "shader = %s\n", conf.vid.shader.c_str());
fprintf(cfile, "palette = %s\n", conf.vid.palette.c_str());
fprintf(cfile, "\n[ROMSETS]\n");
foreach(xRomset rms, conf.rsList) {
@ -237,6 +242,62 @@ void copyFile(const char* src, const char* dst) {
}
}
// load preset colors for zx palette
void loadPalette(Computer* comp, bool updateCurrentPallete) {
printf("Loading palette: %s\n", conf.vid.palette.c_str());
int i = 0;
xColor xcol;
QFile file((conf.path.palDir + SLASH + conf.vid.palette).c_str());
printf("Fullpath: %s\n", (conf.path.palDir + SLASH + conf.vid.palette).c_str());
if (file.open(QFile::ReadOnly)) {
while(!file.atEnd() && i<16) {
QString line = file.readLine();
// #RRGGBB string can be at any position
int pos = line.indexOf('#');
if(pos == -1 || (pos + 7) > line.size())
continue;
// extracting 6-chars as for RRGGBB data format
QString hexPart = line.mid(pos + 1, 6);
// converting Hex-data into an integer
bool ok;
uint rgb = hexPart.toUInt(&ok, 16);
if(!ok)
continue;
xcol.r = (rgb >> 16) & 0xFF;
xcol.g = (rgb >> 8) & 0xFF;
xcol.b = rgb & 0xFF;
vid_set_bcol(comp->vid, i, xcol);
if (updateCurrentPallete)
vid_set_col(comp->vid, i, xcol);
printf("Color %2d = #%s\n", i, hexPart.toStdString().c_str());
i++;
}
file.close();
}
// In case of reading colors data failed - fallback to default palette
if (i != 16) {
printf("Wrong number of colors: %d, falling back to default palette\n", i);
for (i = 0; i < 16; i++) {
// TODO: review default color component value (0xaa), consider globaly defined value instead
xcol.b = (i & 1) ? ((i & 8) ? 0xff : 0xaa) : 0x00;
xcol.r = (i & 2) ? ((i & 8) ? 0xff : 0xaa) : 0x00;
xcol.g = (i & 4) ? ((i & 8) ? 0xff : 0xaa) : 0x00;
vid_set_bcol(comp->vid, i, xcol);
if (updateCurrentPallete)
vid_set_col(comp->vid, i, xcol);
}
}
}
// emulator config
void loadConfig() {
@ -425,6 +486,7 @@ void loadConfig() {
if (pnam=="greyscale") vid_set_grey(arg.b);
if (pnam=="scanlines") scanlines = arg.b;
if (pnam=="shader") conf.vid.shader = pval;
if (pnam=="palette") conf.vid.palette = pval;
break;
case SECT_ROMSETS:
pos = pval.find_last_of(":");

View File

@ -249,6 +249,7 @@ int prfSave(std::string);
#define SCR_DISK 6
void conf_init(char*, char* confdir = NULL);
void loadPalette(Computer*, bool updateCurrentPalette = false);
void loadConfig();
void saveConfig();
@ -522,6 +523,7 @@ struct xConfig {
int curfps;
std::string shader;
int shd_support;
std::string palette;
} vid;
struct {
unsigned enabled:1;
@ -569,6 +571,7 @@ struct xConfig {
std::string romDir;
std::string prfDir;
std::string shdDir;
std::string palDir;
std::string font;
std::string boot;
} path;

View File

@ -87,6 +87,21 @@ void fill_shader_list(QComboBox* box) {
#endif
}
void fill_palette_list(QComboBox* box) {
QDir dir(conf.path.palDir.c_str());
QFileInfoList lst = dir.entryInfoList(QStringList() << "*.txt", QDir::Files, QDir::Name);
QFileInfo inf;
box->clear();
box->addItem("default", 0);
foreach(inf, lst) {
box->addItem(inf.fileName(), 1);
}
box->setCurrentIndex(box->findText(conf.vid.palette.c_str()));
if (box->currentIndex() < 0)
box->setCurrentIndex(0);
}
// OBJECT
void dbg_fill_chip_boxes(QComboBox* cbtype, QComboBox* cbstereo) {
@ -161,6 +176,7 @@ SetupWin::SetupWin(QWidget* par):QDialog(par) {
ui.labShader->setVisible(false);
ui.cbShader->setVisible(false);
#endif
fill_palette_list(ui.cbPalPreset);
// sound
i = 0;
while (sndTab[i].name) {
@ -447,7 +463,8 @@ void SetupWin::start() {
ui.ulaPlus->setChecked(comp->vid->ula->enabled);
ui.cbDDp->setChecked(comp->ddpal);
fill_shader_list(ui.cbShader);
// sound
fill_palette_list(ui.cbPalPreset);
// sound
ui.cbGS->setChecked(comp->gs->enable);
ui.gsrbox->setChecked(comp->gs->reset);
@ -647,6 +664,11 @@ void SetupWin::apply() {
} else {
conf.vid.shader = std::string(ui.cbShader->currentText().toLocal8Bit().data());
}
if (getRFIData(ui.cbPalPreset) == 0) {
conf.vid.palette.clear();
} else {
conf.vid.palette = std::string(ui.cbPalPreset->currentText().toLocal8Bit().data());
}
// sound
conf.snd.enabled = ui.senbox->isChecked() ? 1 : 0;

View File

@ -523,6 +523,16 @@
<item row="4" column="1">
<widget class="QComboBox" name="cbShader"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="labPalPreset">
<property name="text">
<string>Palette</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="cbPalPreset"/>
</item>
</layout>
</widget>
</item>