Allow the SDL port to use custom palettes imported from Cocoa

This commit is contained in:
Lior Halphon 2022-07-17 15:48:41 +03:00
parent 9a966a5581
commit cbf1a5481f
14 changed files with 189 additions and 37 deletions

View File

@ -206,7 +206,7 @@ endif
cocoa: $(BIN)/SameBoy.app
quicklook: $(BIN)/SameBoy.qlgenerator
sdl: $(SDL_TARGET) $(BIN)/SDL/dmg_boot.bin $(BIN)/SDL/mgb_boot.bin $(BIN)/SDL/cgb0_boot.bin $(BIN)/SDL/cgb_boot.bin $(BIN)/SDL/agb_boot.bin $(BIN)/SDL/sgb_boot.bin $(BIN)/SDL/sgb2_boot.bin $(BIN)/SDL/LICENSE $(BIN)/SDL/registers.sym $(BIN)/SDL/background.bmp $(BIN)/SDL/Shaders
sdl: $(SDL_TARGET) $(BIN)/SDL/dmg_boot.bin $(BIN)/SDL/mgb_boot.bin $(BIN)/SDL/cgb0_boot.bin $(BIN)/SDL/cgb_boot.bin $(BIN)/SDL/agb_boot.bin $(BIN)/SDL/sgb_boot.bin $(BIN)/SDL/sgb2_boot.bin $(BIN)/SDL/LICENSE $(BIN)/SDL/registers.sym $(BIN)/SDL/background.bmp $(BIN)/SDL/Shaders $(BIN)/SDL/Palettes
bootroms: $(BIN)/BootROMs/agb_boot.bin $(BIN)/BootROMs/cgb_boot.bin $(BIN)/BootROMs/cgb0_boot.bin $(BIN)/BootROMs/dmg_boot.bin $(BIN)/BootROMs/mgb_boot.bin $(BIN)/BootROMs/sgb_boot.bin $(BIN)/BootROMs/sgb2_boot.bin
tester: $(TESTER_TARGET) $(BIN)/tester/dmg_boot.bin $(BIN)/tester/cgb_boot.bin $(BIN)/tester/agb_boot.bin $(BIN)/tester/sgb_boot.bin $(BIN)/tester/sgb2_boot.bin
all: cocoa sdl tester libretro
@ -424,6 +424,10 @@ $(BIN)/SDL/background.bmp: SDL/background.bmp
$(BIN)/SDL/Shaders: Shaders
-@$(MKDIR) -p $@
cp -rf Shaders/*.fsh $@
$(BIN)/SDL/Palettes: Misc/Palettes
-@$(MKDIR) -p $@
cp -rf Misc/Palettes/*.sbp $@
# Boot ROMs

BIN
Misc/Palettes/Desert.sbp Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
LPBS&6UiS˜‰®ה¦»מ©־ץ}ש^¬ױL<D7B1>לH+

BIN
Misc/Palettes/Fog.sbp Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Misc/Palettes/Seaweed.sbp Normal file

Binary file not shown.

BIN
Misc/Palettes/Twilight.sbp Normal file

Binary file not shown.

View File

@ -98,6 +98,7 @@ typedef struct {
/* v0.15.2 */
bool allow_background_controllers;
bool gui_pallete_enabled; // Change the GUI palette only once the user changed the DMG palette
char dmg_palette_name[25];
};
} configuration_t;

131
SDL/gui.c
View File

@ -5,6 +5,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include "utils.h"
#include "gui.h"
#include "font.h"
@ -21,6 +22,9 @@ enum pending_command pending_command;
unsigned command_parameter;
char *dropped_state_file = NULL;
static char **custom_palettes;
static unsigned n_custom_palettes;
#ifdef __APPLE__
#define MODIFIER_NAME " " CMD_STRING
@ -561,6 +565,9 @@ const char *current_color_temperature(unsigned index)
const char *current_palette(unsigned index)
{
if (configuration.dmg_palette == 4) {
return configuration.dmg_palette_name;
}
return (const char *[]){"Greyscale", "Lime (Game Boy)", "Olive (Pocket)", "Teal (Light)"}
[configuration.dmg_palette];
}
@ -653,25 +660,45 @@ static void increase_color_temperature(unsigned index)
}
}
const GB_palette_t *current_dmg_palette(void)
{
typedef struct __attribute__ ((packed)) {
uint32_t magic;
uint8_t flags;
struct GB_color_s colors[5];
int32_t brightness_bias;
uint32_t hue_bias;
uint32_t hue_bias_strength;
} theme_t;
static theme_t theme;
if (configuration.dmg_palette == 4) {
char *path = resource_path("Palettes");
sprintf(path + strlen(path), "/%s.sbp", configuration.dmg_palette_name);
FILE *file = fopen(path, "rb");
if (!file) return &GB_PALETTE_GREY;
memset(&theme, 0, sizeof(theme));
fread(&theme, sizeof(theme), 1, file);
fclose(file);
#ifdef GB_BIG_ENDIAN
theme.magic = __builtin_bswap32(theme.magic);
#endif
if (theme.magic != 'SBPL') return &GB_PALETTE_GREY;
return (GB_palette_t *)&theme.colors;
}
switch (configuration.dmg_palette) {
case 1: return &GB_PALETTE_DMG;
case 2: return &GB_PALETTE_MGB;
case 3: return &GB_PALETTE_GBL;
default: return &GB_PALETTE_GREY;
}
}
static void update_gui_palette(void)
{
const GB_palette_t *palette;
switch (configuration.dmg_palette) {
case 1:
palette = &GB_PALETTE_DMG;
break;
case 2:
palette = &GB_PALETTE_MGB;
break;
case 3:
palette = &GB_PALETTE_GBL;
break;
default:
palette = &GB_PALETTE_GREY;
}
const GB_palette_t *palette = current_dmg_palette();
SDL_Color colors[4];
for (unsigned i = 4; i--; ) {
@ -695,7 +722,26 @@ static void update_gui_palette(void)
static void cycle_palette(unsigned index)
{
if (configuration.dmg_palette == 3) {
configuration.dmg_palette = 0;
if (n_custom_palettes == 0) {
configuration.dmg_palette = 0;
}
else {
configuration.dmg_palette = 4;
strcpy(configuration.dmg_palette_name, custom_palettes[0]);
}
}
else if (configuration.dmg_palette == 4) {
for (unsigned i = 0; i < n_custom_palettes; i++) {
if (strcmp(custom_palettes[i], configuration.dmg_palette_name) == 0) {
if (i == n_custom_palettes - 1) {
configuration.dmg_palette = 0;
}
else {
strcpy(configuration.dmg_palette_name, custom_palettes[i + 1]);
}
break;
}
}
}
else {
configuration.dmg_palette++;
@ -707,7 +753,26 @@ static void cycle_palette(unsigned index)
static void cycle_palette_backwards(unsigned index)
{
if (configuration.dmg_palette == 0) {
configuration.dmg_palette = 3;
if (n_custom_palettes == 0) {
configuration.dmg_palette = 3;
}
else {
configuration.dmg_palette = 4;
strcpy(configuration.dmg_palette_name, custom_palettes[n_custom_palettes - 1]);
}
}
else if (configuration.dmg_palette == 4) {
for (unsigned i = 0; i < n_custom_palettes; i++) {
if (strcmp(custom_palettes[i], configuration.dmg_palette_name) == 0) {
if (i == 0) {
configuration.dmg_palette = 3;
}
else {
strcpy(configuration.dmg_palette_name, custom_palettes[i - 1]);
}
break;
}
}
}
else {
configuration.dmg_palette--;
@ -1896,3 +1961,31 @@ void run_gui(bool is_running)
}
}
}
static void __attribute__ ((constructor)) list_custom_palettes(void)
{
char *path = resource_path("Palettes");
if (!path) return;
if (strlen(path) > 1024 - 30) {
// path too long to safely concat filenames
return;
}
DIR *dir = opendir(path);
if (!dir) return;
struct dirent *ent;
while ((ent = readdir(dir))) {
unsigned length = strlen(ent->d_name);
if (length < 5 || length > 28) {
continue;
}
if (strcmp(ent->d_name + length - 4, ".sbp")) continue;
ent->d_name[length - 4] = 0;
custom_palettes = realloc(custom_palettes,
sizeof(custom_palettes[0]) * (n_custom_palettes + 1));
custom_palettes[n_custom_palettes++] = strdup(ent->d_name);
}
closedir(dir);
}

View File

@ -64,5 +64,6 @@ extern const char *osd_text;
extern unsigned osd_countdown;
extern unsigned osd_text_lines;
void convert_mouse_coordinates(signed *x, signed *y);
const GB_palette_t *current_dmg_palette(void);
#endif

View File

@ -161,22 +161,7 @@ static const char *end_capturing_logs(bool show_popup, bool should_exit, uint32_
static void update_palette(void)
{
switch (configuration.dmg_palette) {
case 1:
GB_set_palette(&gb, &GB_PALETTE_DMG);
break;
case 2:
GB_set_palette(&gb, &GB_PALETTE_MGB);
break;
case 3:
GB_set_palette(&gb, &GB_PALETTE_GBL);
break;
default:
GB_set_palette(&gb, &GB_PALETTE_GREY);
}
GB_set_palette(&gb, current_dmg_palette());
}
static void screen_size_changed(void)
@ -866,7 +851,7 @@ int main(int argc, char **argv)
configuration.highpass_mode %= GB_HIGHPASS_MAX;
configuration.model %= MODEL_MAX;
configuration.sgb_revision %= SGB_MAX;
configuration.dmg_palette %= 4;
configuration.dmg_palette %= 5;
if (configuration.dmg_palette) {
configuration.gui_pallete_enabled = true;
}
@ -876,6 +861,7 @@ int main(int argc, char **argv)
configuration.bootrom_path[sizeof(configuration.bootrom_path) - 1] = 0;
configuration.cgb_revision %= GB_MODEL_CGB_E - GB_MODEL_CGB_0 + 1;
configuration.audio_driver[15] = 0;
configuration.dmg_palette_name[24] = 0;
}
if (configuration.model >= MODEL_MAX) {

51
Windows/dirent.c Executable file
View File

@ -0,0 +1,51 @@
#include <windows.h>
#include <stdio.h>
#include <winnls.h>
#include <io.h>
#include "dirent.h"
DIR *opendir(const char *filename)
{
wchar_t w_filename[MAX_PATH + 3] = {0,};
unsigned length = MultiByteToWideChar(CP_UTF8, 0, filename, -1, w_filename, MAX_PATH);
if (length) {
w_filename[length - 1] = L'/';
w_filename[length] = L'*';
w_filename[length + 1] = 0;
}
DIR *ret = malloc(sizeof(*ret));
ret->handle = FindFirstFileW(w_filename, &ret->entry);
if (ret->handle == INVALID_HANDLE_VALUE) {
free(ret);
return NULL;
}
return ret;
}
int closedir(DIR *dir)
{
if (dir->handle != INVALID_HANDLE_VALUE) {
FindClose(dir->handle);
}
free(dir);
return 0;
}
struct dirent *readdir(DIR *dir)
{
if (dir->handle == INVALID_HANDLE_VALUE) {
return NULL;
}
WideCharToMultiByte(CP_UTF8, 0, dir->entry.cFileName, -1,
dir->out_entry.d_name, sizeof(dir->out_entry.d_name),
NULL, NULL);
if (!FindNextFileW(dir->handle, &dir->entry)) {
FindClose(dir->handle);
dir->handle = INVALID_HANDLE_VALUE;
}
return &dir->out_entry;
}

15
Windows/dirent.h Executable file
View File

@ -0,0 +1,15 @@
#include <windows.h>
struct dirent {
char d_name[MAX_PATH + 1];
};
typedef struct {
HANDLE handle;
WIN32_FIND_DATAW entry;
struct dirent out_entry;
} DIR;
DIR *opendir(const char *filename);
int closedir(DIR *dir);
struct dirent *readdir(DIR *dir);