Support Write Protect in Disk2 load dialog, etc

Also fixes a crashing bug in cg.c, and various other bits.
This commit is contained in:
Michel Pollet 2024-02-14 09:12:29 +00:00
parent 01619cfe53
commit 5650323d05
No known key found for this signature in database
21 changed files with 444 additions and 51 deletions

View File

@ -1,5 +1,8 @@
/* this file is auto-generated by icon-convert-tcc.c */
static const unsigned long mii_icon64[] = {
#define MII_ICON64_SIZE 4098
extern const unsigned long mii_icon64[MII_ICON64_SIZE];
#ifdef MII_ICON64_DEFINE
const unsigned long mii_icon64[MII_ICON64_SIZE] = {
64,64,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
@ -578,3 +581,4 @@ static const unsigned long mii_icon64[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
#endif

View File

@ -59,6 +59,7 @@ $(LIB)/ui_tests.so : $(OBJ)/mii_mui_slots.o
$(LIB)/ui_tests.so : $(OBJ)/mii_mui_loadbin.o
$(LIB)/ui_tests.so : $(OBJ)/mii_mui_1mb.o
$(LIB)/ui_tests.so : $(OBJ)/mii_mui_2dsk.o
$(LIB)/ui_tests.so : $(OBJ)/mii_mui_about.o
# use a .temp file, otherwise the playground tries to reload before the file
# is fully written, and it fails.

View File

@ -1009,6 +1009,7 @@ static struct cg_rle_t * cg_rle_intersection(struct cg_rle_t * a, struct cg_rle_
struct cg_span_t * a_end = a_spans + a->spans.size;
struct cg_span_t * b_spans = b->spans.data;
struct cg_span_t * b_end = b_spans + b->spans.size;
int overflow = 0;
while((a_spans < a_end) && (b_spans < b_end))
{
if(b_spans->y > a_spans->y)
@ -1040,6 +1041,24 @@ static struct cg_rle_t * cg_rle_intersection(struct cg_rle_t * a, struct cg_rle_
if(len)
{
struct cg_span_t * span = result->spans.data + result->spans.size;
if (result->spans.size >= result->spans.capacity)
{
/* This is a workaround, I've had a case where the size
overflows by quite a bit. See note at the end of this
function. In any case this doesn't hurt, and it prevents
a crash in this situation.
Not familiar enough with the codebase to know if this
is a bug or not. */
#if 0
printf("cg_array_ensure detected overflow!!\na:%d b:%d r:%d/%d (len %d)\n",
a->spans.size, b->spans.size,
result->spans.size,
result->spans.capacity, len);
#endif
cg_array_ensure(result->spans, result->spans.size + 1);
span = result->spans.data + result->spans.size;
overflow = 1;
}
span->x = x;
span->len = len;
span->y = a_spans->y;
@ -1079,7 +1098,15 @@ static struct cg_rle_t * cg_rle_intersection(struct cg_rle_t * a, struct cg_rle_
result->y = y1;
result->w = x2 - x1;
result->h = y2 - y1 + 1;
if (overflow) {
/* I have a case which displays this
cg_rle_intersection detected overflow!!
a:960 b:524 r:1098/4096
printf("cg_rle_intersection detected overflow!!\n\ta:%d b:%d r:%d/%d\n",
a->spans.size, b->spans.size,
result->spans.size, result->spans.capacity);
*/
}
return result;
}

View File

@ -458,7 +458,7 @@ mui_font_textbox(
mui_color_t color,
uint16_t flags );
DECLARE_C_ARRAY(stb_ttc_g*, mui_glyph_array, 8, int x, y, w; );
DECLARE_C_ARRAY(unsigned int, mui_glyph_array, 8, int x, y, w; );
DECLARE_C_ARRAY(mui_glyph_array_t, mui_glyph_line_array, 8);
/*
@ -522,6 +522,15 @@ typedef struct mui_window_t {
/*
* Window related
*/
/*
* This is the main function to create a window. The
* * 'wdef' is the window definition (or NULL for a default window).
* see mui_wdef_p for the callback definition.
* * 'layer' layer to put it in (default to zero for normal windows)
* * 'instance_size' zero (for default) or the size of the window instance
* object that is returned, you can therefore have your own custom field
* attached to a window.
*/
mui_window_t *
mui_window_create(
struct mui_t * ui,

View File

@ -127,7 +127,9 @@ mui_check_rad_draw(
}
mui_font_textbox(main, dr,
title, c->title, 0,
mui_control_color[0].text,
c->state == MUI_CONTROL_STATE_DISABLED ?
mui_control_color[c->state].text :
mui_control_color[0].text,
MUI_TEXT_ALIGN_MIDDLE);
mui_drawable_clip_pop(dr);
}

View File

@ -64,7 +64,7 @@ mui_font_from_mem(
f->size = size;
stb_ttc_LoadFont(&f->ttc, font_data, font_size);
TAILQ_INSERT_TAIL(&ui->fonts, f, self);
printf("%s: Loaded font %s:%d\n", __func__, name, size);
// printf("%s: Loaded font %s:%d\n", __func__, name, size);
return f;
}
@ -73,7 +73,7 @@ void
mui_font_init(
mui_t *ui)
{
printf("%s: Loading fonts\n", __func__);
// printf("%s: Loading fonts\n", __func__);
mui_font_from_mem(ui, "main", 28,
mui_main_font_data, mui_main_font_size);
mui_font_from_mem(ui, "icon_large", 96,
@ -241,7 +241,7 @@ mui_font_measure(
break;
}
line->w += gc->advance;
mui_glyph_array_push(line, gc);
mui_glyph_array_push(line, gc->index);
};
} while (text[ch] && ch < text_len);
int bh = 0;
@ -308,7 +308,8 @@ mui_font_measure_draw(
mui_glyph_array_t * line = &lines->e[li];
int xpos = 0;//where.x / scale;
for (int ci = 0; ci < (int)line->count; ci++) {
stb_ttc_g *gc = line->e[ci];
unsigned int cache_index = line->e[ci];
stb_ttc_g *gc = &ttc->glyph[cache_index];
// int pxpos = gc->x0 + ((xpos + gc->lsb) * scale);
int pxpos = gc->x0 + ((xpos + 0) * scale);

View File

@ -240,7 +240,6 @@ _mui_stdfile_window_action(
for (int i = 0; i < (int)std->pop_path.count; i++)
free(std->pop_path.e[i]);
std->pop_path.count = 0;
} break;
}
return 0;

View File

@ -11,6 +11,7 @@
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <execinfo.h>
#include "mui_priv.h"
#include "cg.h"
@ -127,7 +128,6 @@ mui_window_create(
TAILQ_INIT(&w->zombies);
STAILQ_INIT(&w->actions);
pixman_region32_init(&w->inval);
TAILQ_INSERT_HEAD(&ui->windows, w, self);
mui_window_select(w); // place it in it's own layer
mui_font_t * main = mui_font_find(ui, "main");
@ -351,8 +351,8 @@ mui_window_inval(
pixman_region32_reset(&win->inval, (pixman_box32_t*)&frame);
forward = frame;
mui_window_t * w;
TAILQ_FOREACH(w, &win->ui->windows, self) {
mui_window_t * w, *save;
TAILQ_FOREACH_SAFE(w, &win->ui->windows, self, save) {
if (w == win || !c2_rect_intersect_rect(&w->frame, &forward))
continue;
pixman_region32_union_rect(&w->inval, &w->inval,
@ -381,8 +381,8 @@ mui_window_front(
{
if (!ui)
return NULL;
mui_window_t * w;
TAILQ_FOREACH_REVERSE(w, &ui->windows, windows, self) {
mui_window_t * w, *save;
TAILQ_FOREACH_REVERSE_SAFE(w, &ui->windows, windows, self, save) {
if (w->flags.hidden)
continue;
if (w->flags.layer < MUI_WINDOW_MENUBAR_LAYER)

View File

@ -41,6 +41,7 @@ typedef struct stb_ttc_measure {
* scales in one cache.
*/
typedef struct stb_ttc_g {
unsigned int index; // index in global table
unsigned int intscale; // for comparison purpose
float scale;
unsigned int glyph;
@ -296,6 +297,7 @@ stb_ttc__ScaledGlyphGetCache(
.glyph = glyph,
.index = ttc->g_count
};
gc.index = ttc->g_count;
ttc->g_count++;
unsigned int hash = glyph + (glyph * gc.intscale);

View File

@ -176,6 +176,7 @@ _init(
// mii_mui_load_1mbrom(g->ui, &g_machine_conf.slot[0].conf.rom1mb);
// mii_mui_load_2dsk(g->ui,
// &g_machine_conf.slot[0].conf.disk2, MII_2DSK_DISKII);
mii_mui_about(g->ui);
#if 0
mui_alert(ui, C2_PT(0,0),
"Testing one Two",
@ -183,7 +184,7 @@ _init(
"This operation cannot be cancelled.",
MUI_ALERT_WARN);
#endif
#if 1
#if 0
mui_stdfile_get(ui,
C2_PT(0, 0),
"Select image for SmartPort card",
@ -233,4 +234,4 @@ mui_plug_t mui_plug = {
.dispose = _dispose,
.draw = _draw,
.event = _event,
};
};

View File

@ -239,12 +239,31 @@ _mii_disk2_command(
if (param)
*(int *)param = 2;
break;
case MII_SLOT_DRIVE_LOAD ... MII_SLOT_DRIVE_LOAD + 2 - 1:
case MII_SLOT_DRIVE_WP ... MII_SLOT_DRIVE_WP + 2 - 1: {
int drive = cmd - MII_SLOT_DRIVE_WP;
int *wp = param;
if (wp) {
printf("Drive %d WP: 0x%x set %s\n", drive,
c->floppy[drive].write_protected,
*wp ? "ON" : "OFF");
c->floppy[drive].write_protected =
(c->floppy[drive].write_protected &
~(MII_FLOPPY_WP_MANUAL))|
(*wp ? MII_FLOPPY_WP_MANUAL : 0);
}
} break;
case MII_SLOT_DRIVE_LOAD ... MII_SLOT_DRIVE_LOAD + 2 - 1: {
int drive = cmd - MII_SLOT_DRIVE_LOAD;
const char *filename = param;
const char *pathname = param;
mii_dd_file_t *file = NULL;
if (filename && *filename) {
file = mii_dd_file_load(&mii->dd, filename, O_RDWR);
if (pathname && *pathname) {
if (c->drive[drive].file &&
!strcmp(c->drive[drive].file->pathname, pathname)) {
printf("%s D%d Same file, not reloading\n",
__func__, drive);
return 0;
}
file = mii_dd_file_load(&mii->dd, pathname, O_RDWR);
if (!file)
return -1;
}
@ -252,7 +271,7 @@ _mii_disk2_command(
mii_floppy_init(&c->floppy[drive]);
mii_dd_drive_load(&c->drive[drive], file);
mii_floppy_load(&c->floppy[drive], file);
break;
} break;
}
return 0;
}

View File

@ -16,6 +16,10 @@
// track containing random bits
#define MII_FLOPPY_RANDOM_TRACK_ID 35
/*
* Reasons for write protect. Ie checkbox in the UI, or file format
* doesn't support writes, or the file has no write permissions.
*/
enum {
MII_FLOPPY_WP_MANUAL = (1 << 0), // write protect by the user
MII_FLOPPY_WP_RO_FILE = (1 << 1), // file is read only

View File

@ -77,6 +77,7 @@ mii_slot_drv_find(
enum {
MII_SLOT_DRIVE_COUNT = 0x01,
MII_SLOT_DRIVE_LOAD = 0x20, // + drive index 0...n
MII_SLOT_DRIVE_WP = 0x30, // + drive index 0...n
MII_SLOT_SSC_SET_TTY = 0x10, // param is a pathname, or NULL for a pty
};

View File

@ -25,9 +25,10 @@
#include "mii_thread.h"
#include "mii_mui.h"
#include "mii-icon-64.h"
#include "minipt.h"
#include "miigl_counter.h"
#define MII_ICON64_DEFINE
#include "mii-icon-64.h"
/*
* Note: This *assumes* that the GL implementation has support for non-power-of-2
@ -348,7 +349,10 @@ mii_x11_init(
}
{
Atom net_wm_icon_atom = XInternAtom(ui->dpy, "_NET_WM_ICON", False);
XChangeProperty(ui->dpy, ui->win, net_wm_icon_atom, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)mii_icon64, sizeof(mii_icon64) / sizeof(mii_icon64[0]));
XChangeProperty(ui->dpy, ui->win, net_wm_icon_atom, XA_CARDINAL,
32, PropModeReplace,
(unsigned char *)mii_icon64,
sizeof(mii_icon64) / sizeof(mii_icon64[0]));
XFlush(ui->dpy);
}
XMapWindow(ui->dpy, ui->win);
@ -808,12 +812,15 @@ mii_ui_reconfigure_slot(
(void*)config->slot[i].conf.smartport.drive[1].disk);
} break;
case MII_SLOT_DRIVER_DISK2: {
mii_slot_command(mii, slot,
MII_SLOT_DRIVE_LOAD,
(void*)config->slot[i].conf.disk2.drive[0].disk);
mii_slot_command(mii, slot,
MII_SLOT_DRIVE_LOAD + 1,
(void*)config->slot[i].conf.disk2.drive[1].disk);
for (int di = 0; di < 2; di++) {
mii_slot_command(mii, slot,
MII_SLOT_DRIVE_LOAD + di,
(void*)config->slot[i].conf.disk2.drive[di].disk);
int wp = config->slot[i].conf.disk2.drive[di].wp;
mii_slot_command(mii, slot,
MII_SLOT_DRIVE_WP + di,
(void*)&wp);
}
} break;
case MII_SLOT_DRIVER_ROM1MB: {
mii_slot_command(mii, slot,

56
ui_gl/mii_loadbin.c Normal file
View File

@ -0,0 +1,56 @@
/*
* mii_loadbin.c
*
* Copyright (C) 2023 Michel Pollet <buserror@gmail.com>
*
* SPDX-License-Identifier: MIT
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/inotify.h>
#include <pthread.h>
#include "mii.h"
#include "mii_bank.h"
#include "mii_mui_settings.h"
typedef struct mii_loadbin_t {
mii_t * mii;
pthread_t thread;
mii_loadbin_conf_t conf;
} mii_loadbin_t;
static mii_loadbin_t * _mii_loadbin = NULL;
static void *
mii_thread_loadbin(
void *arg)
{
return NULL;
}
mii_loadbin_t *
mii_loadbin_start(
struct mii_t *mii,
struct mii_loadbin_conf_t *conf)
{
mii_loadbin_t * res = NULL;
if (_mii_loadbin) {
return _mii_loadbin;
}
_mii_loadbin = res = calloc(1, sizeof(*res));
res->mii = mii;
res->conf = *conf;
pthread_create(&res->thread, NULL, mii_thread_loadbin, res);
return res;
}

View File

@ -247,9 +247,7 @@ mii_mui_load_1mbrom(
c2_rect_offset(&wpos,
(ui->screen_size.x / 2) - (c2_rect_width(&wpos) / 2),
(ui->screen_size.y * 0.4) - (c2_rect_height(&wpos) / 2));
w = mui_window_create(mui,
wpos,
NULL, MUI_WINDOW_LAYER_MODAL,
w = mui_window_create(mui, wpos, NULL, MUI_WINDOW_LAYER_MODAL,
"1MB ROM Card File",
sizeof(mii_mui_1mb_t));
mui_window_set_id(w, MII_1MB_WINDOW_ID);

View File

@ -5,7 +5,7 @@
*
* SPDX-License-Identifier: MIT
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -22,6 +22,8 @@ enum {
MII_2DSK_CANCEL = FCC('c','a','n','c'),
MII_2DSK_SELECT1 = FCC('s','e','l','1'),
MII_2DSK_SELECT2 = FCC('s','e','l','2'),
MII_2DSK_WP1 = FCC('w','p','1',' '),
MII_2DSK_WP2 = FCC('w','p','2',' '),
};
typedef struct mii_mui_2dsk_t {
@ -30,39 +32,177 @@ typedef struct mii_mui_2dsk_t {
mui_control_t * load;
uint32_t selecting;
struct {
mui_control_t *icon, *fname, *button;
mui_control_t *icon, *fname, *button, *wp, *warning;
} drive[2];
mii_2dsk_conf_t * dst;
mii_2dsk_conf_t config;
} mii_mui_2dsk_t;
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
typedef struct mii_floppy_check_t {
char * error;
char * warning;
int file_ro;
int file_ro_format;
} mii_floppy_check_t;
#define NIB_SIZE 232960;
#define DSK_SIZE 143360;
// TODO move that to some common place
void
_size_string(
size_t s,
char *out,
int out_size,
uint16_t flags);
static int
_mii_floppy_check_file(
const char * path,
mii_floppy_check_t * out)
{
char *filename = basename((char*)path);
out->file_ro = 0;
out->file_ro_format = 0;
out->error = NULL;
out->warning = NULL;
struct stat st;
if (stat(path, &st) < 0) {
asprintf(&out->error, "'%s': %s", filename, strerror(errno));
return -1;
}
// has to have one
char * suffix = strrchr(path, '.');
if (!suffix) {
asprintf(&out->error, "'%s' has no extension.", filename);
return -1;
}
int want_size = 0;
int iswoz = 0;
if (!strcasecmp(suffix, ".nib")) {
out->file_ro_format = 1;
} else if (!strcasecmp(suffix, ".dsk")) {
out->file_ro_format = 1;
} else if (!strcasecmp(suffix, ".woz") ||
!strcasecmp(suffix, ".woz1") ||
!strcasecmp(suffix, ".woz2")) {
out->file_ro = 0;
out->file_ro_format = 0;
iswoz = 1;
} else {
asprintf(&out->error, "'%s' has an unknown extension.", filename);
return -1;
}
if (out->error)
return -1;
if (want_size && st.st_size != want_size) {
char stt[64];
long delta = want_size - st.st_size;
_size_string(delta < 0 ? -delta : delta, stt, sizeof(stt)-2, 1);
strcpy(stt + strlen(stt), "B");
asprintf(&out->error,
"File '%s' is the wrong size, %s too %s.",
filename,
stt, delta < 0 ? "big" : "small");
return -1;
}
if (out->error)
return -1;
int fd = open(path, O_RDWR, 0);
if (fd < 0) {
fd = open(path, O_RDONLY, 0);
if (fd < 0) {
asprintf(&out->error, "'%s': %s", filename, strerror(errno));
return -1;
} else
out->file_ro = 1;
}
if (iswoz) {
// check the woz header
uint8_t header[4];
if (read(fd, header, sizeof(header)) != sizeof(header)) {
asprintf(&out->error,
"'%s': could not check WOZ header. Invalid file?",
filename);
close(fd);
return -1;
}
if (memcmp(header, "WOZ1", 4) != 0 && memcmp(header, "WOZ2", 4) != 0) {
asprintf(&out->error,
"'%s' is not detected as a valid WOZ file.",
filename);
close(fd);
return -1;
}
}
close(fd);
if (out->file_ro_format && !out->warning) {
asprintf(&out->warning, "%s format is Read Only.", suffix);
}
if (out->file_ro && !out->warning) {
asprintf(&out->warning, "File lacks write permissions.");
}
return 0;
}
static void
mii_mui_2dsk_load_conf(
mii_mui_2dsk_t * m,
mii_2dsk_conf_t * config)
{
int ok = 0;
int ok = 1;
for (int i = 0; i < 2; i++) {
if (config->drive[i].disk[0]) {
ok = 1;
mii_floppy_check_t check = {};
if (_mii_floppy_check_file(config->drive[i].disk, &check) < 0) {
mui_alert(m->win.ui, C2_PT(0,0),
"Invalid Disk Image",
check.error, MUI_ALERT_FLAG_OK);
free(check.error);
ok = 0;
}
config->drive[i].ro_file = check.file_ro;
config->drive[i].ro_format = check.file_ro_format;
mui_control_set_state(m->drive[i].fname, MUI_CONTROL_STATE_NORMAL);
char *dup = strdup(config->drive[i].disk);
mui_control_set_title(m->drive[i].fname, basename(dup));
free(dup);
mui_control_set_state(m->drive[i].icon, MUI_CONTROL_STATE_NORMAL);
mui_control_set_title(m->drive[i].button, "Eject");
if (check.warning) {
mui_control_set_title(m->drive[i].warning, check.warning);
mui_control_set_state(m->drive[i].wp, MUI_CONTROL_STATE_DISABLED);
free(check.warning);
} else {
mui_control_set_title(m->drive[i].warning, "");
mui_control_set_state(m->drive[i].wp, MUI_CONTROL_STATE_NORMAL);
}
} else {
config->drive[i].ro_file = config->drive[i].ro_format = 0;
mui_control_set_state(m->drive[i].fname, MUI_CONTROL_STATE_DISABLED);
mui_control_set_title(m->drive[i].fname, "Click \"Select\" to pick a file");
mui_control_set_state(m->drive[i].icon, MUI_CONTROL_STATE_DISABLED);
mui_control_set_title(m->drive[i].button, "Select…");
mui_control_set_state(m->drive[i].wp, MUI_CONTROL_STATE_NORMAL);
mui_control_set_title(m->drive[i].warning, "");
}
mui_control_set_value(m->drive[i].wp,
(config->drive[i].wp || config->drive[i].ro_file ||
config->drive[i].ro_format) ? 1 : 0);
}
if (ok)
mui_control_set_state(m->load, MUI_CONTROL_STATE_NORMAL);
// else
// mui_control_set_state(m->load, MUI_CONTROL_STATE_DISABLED);
else
mui_control_set_state(m->load, MUI_CONTROL_STATE_DISABLED);
}
static int
@ -80,8 +220,9 @@ _mii_2dsk_stdfile_cb(
printf("%s select %s\n", __func__, path);
strncpy(m->config.drive[idx].disk, path,
sizeof(m->config.drive[idx].disk)-1);
mii_mui_2dsk_load_conf(m, &m->config);
free(path);
mui_window_dispose(w);
mii_mui_2dsk_load_conf(m, &m->config);
} break;
case MUI_STDF_ACTION_CANCEL:
printf("%s cancel\n", __func__);
@ -148,6 +289,11 @@ _mii_2dsk_action_cb(
mui_window_set_action(w, _mii_2dsk_stdfile_cb, m);
}
} break;
case MII_2DSK_WP1:
case MII_2DSK_WP2: {
int idx = uid == MII_2DSK_WP1 ? 0 : 1;
m->config.drive[idx].wp = mui_control_get_value(c);
} break;
}
break;
}
@ -169,18 +315,19 @@ mii_mui_load_2dsk(
return w;
}
c2_pt_t where = {};
c2_rect_t wpos = C2_RECT_WH(where.x, where.y, 640, 275);
if (where.x == 0 && where.y == 0)
c2_rect_offset(&wpos,
(ui->screen_size.x / 2) - (c2_rect_width(&wpos) / 2),
(ui->screen_size.y * 0.4) - (c2_rect_height(&wpos) / 2));
char label[128];
sprintf(label, "Select Files for %s 1&2 (Slot %d)",
c2_rect_t wpos = C2_RECT_WH(where.x, where.y, 640, 355);
c2_rect_offset(&wpos,
(ui->screen_size.x / 2) - (c2_rect_width(&wpos) / 2),
(ui->screen_size.y * 0.45) - (c2_rect_height(&wpos) / 2));
char *label;
asprintf(&label, "Select Files for %s 1&2 (Slot %d)",
drive_kind == MII_2DSK_SMARTPORT ? "SmartPort" : "Disk II",
config->slot_id + 1);
w = mui_window_create(mui,
wpos, NULL, 0, label,
w = mui_window_create(mui, wpos, NULL, MUI_WINDOW_LAYER_MODAL,
label,
sizeof(mii_mui_2dsk_t));
free(label);
mui_window_set_id(w, MII_2DSK_WINDOW_ID);
mii_mui_2dsk_t * m = (mii_mui_2dsk_t*)w;
m->drive_kind = drive_kind;
@ -235,9 +382,21 @@ mii_mui_load_2dsk(
MII_2DSK_SELECT1 : MII_2DSK_SELECT2);
c->key_equ = MUI_KEY_EQU(MUI_MODIFIER_ALT, '1' + i);
c2_rect_bottom_of(&cp, cp.b, margin * 0.2);
c2_rect_bottom_of(&cf, cp.b, margin * 0.4);
cf.l = cp.l + (margin * 0.7);
cf.r = cf.l + 200;
m->drive[i].wp = c = mui_button_new(w,
cf, MUI_BUTTON_STYLE_CHECKBOX,
"Write Protect",
i == 0 ? MII_2DSK_WP1 : MII_2DSK_WP2);
c2_rect_right_of(&cf, cf.r, margin * 0.5);
cf.r = c2_rect_width(&w->frame) - margin * 1.2;
m->drive[i].warning = c = mui_textbox_new(w, cf,
"", NULL,
MUI_TEXT_ALIGN_MIDDLE|MUI_TEXT_ALIGN_RIGHT);
c2_rect_bottom_of(&cp, cp.b + (base_size * 2), margin * 0.2);
}
c2_rect_bottom_of(&cp, cp.t, margin * 0.8);
c2_rect_top_of(&cp, cp.t, margin * 3.5);
cp.l = margin * 4;
cp.r = c2_rect_width(&w->frame) - margin * 4;
c = mui_separator_new(w, cp);
@ -251,6 +410,7 @@ mii_mui_load_2dsk(
m->dst = config;
m->config = *config;
mii_mui_2dsk_load_conf(m, config);
return w;
}

90
ui_gl/mii_mui_about.c Normal file
View File

@ -0,0 +1,90 @@
/*
* mui_mui_about.c
*
* Copyright (C) 2023 Michel Pollet <buserror@gmail.com>
*
* SPDX-License-Identifier: MIT
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mui.h"
#include "mii-icon-64.h"
enum {
MII_ABOUT_WINDOW_ID = FCC('a','b','o','t'),
MII_ABOUT_OK = FCC('O','K','!',' '),
};
typedef struct mii_mui_about_t {
mui_window_t win;
} mii_mui_about_t;
static int
_mii_about_action_cb(
mui_control_t * c,
void * cb_param, // mii_mui_about_t
uint32_t what,
void * param) // not used
{
printf("%s %4.4s\n", __func__, (char*)&what);
mii_mui_about_t * m = cb_param;
uint32_t uid = mui_control_get_uid(c);
switch (what) {
case MUI_CONTROL_ACTION_SELECT:
printf("%s control %4.4s\n", __func__, (char*)&uid);
switch (uid) {
case MII_ABOUT_OK: {
// save the config
mui_window_dispose(&m->win);
} break;
}
break;
}
return 0;
}
struct mui_window_t *
mii_mui_about(
struct mui_t *mui )
{
mui_t *ui = mui;
float base_size = mui_font_find(ui, "main")->size;
float margin = base_size * 0.7;
mui_window_t *w = mui_window_get_by_id(mui, MII_ABOUT_WINDOW_ID);
if (w) {
mui_window_select(w);
return w;
}
c2_pt_t where = {};
c2_rect_t wpos = C2_RECT_WH(where.x, where.y, 560, 240);
if (where.x == 0 && where.y == 0)
c2_rect_offset(&wpos,
(ui->screen_size.x / 2) - (c2_rect_width(&wpos) / 2),
(ui->screen_size.y * 0.4) - (c2_rect_height(&wpos) / 2));
w = mui_window_create(mui, wpos, NULL, MUI_WINDOW_LAYER_MODAL,
"About the MII " MUI_GLYPH_IIE " Emulator",
sizeof(mii_mui_about_t));
mui_window_set_id(w, MII_ABOUT_WINDOW_ID);
mii_mui_about_t * m = (mii_mui_about_t*)w;
mui_control_t * c = NULL;
c2_rect_t cf;
cf = C2_RECT_WH(0, 0, base_size * 4, base_size * 1.4);
c2_rect_left_of(&cf, c2_rect_width(&w->content), margin);
c2_rect_top_of(&cf, c2_rect_height(&w->content), margin);
c = mui_button_new(w,
cf, MUI_BUTTON_STYLE_DEFAULT,
"OK", MII_ABOUT_OK);
c->key_equ = MUI_KEY_EQU(0, 13);
return w;
}

View File

@ -252,10 +252,14 @@ mii_emu_save(
config->slot[i].conf.disk2.drive[0].disk);
sprintf(label, "%lu", config->slot[i].conf.disk2.drive[0].flags);
mii_config_set(cf, section, "flags0", label);
mii_config_set(cf, section, "wp0",
config->slot[i].conf.disk2.drive[0].wp ? "1" : "0");
mii_config_set(cf, section, "image1",
config->slot[i].conf.disk2.drive[1].disk);
sprintf(label, "%lu", config->slot[i].conf.disk2.drive[1].flags);
mii_config_set(cf, section, "flags1", label);
mii_config_set(cf, section, "wp1",
config->slot[i].conf.disk2.drive[1].wp ? "1" : "0");
break;
case MII_SLOT_DRIVER_SUPERSERIAL:
mii_config_set(cf, section, "device",
@ -384,4 +388,4 @@ mii_emu_load(
}
}
return 0;
}
}

View File

@ -141,6 +141,9 @@ struct mui_window_t *
mii_mui_load_1mbrom(
struct mui_t *mui,
mii_1mb_conf_t *config);
struct mui_window_t *
mii_mui_about(
struct mui_t *mui );
enum mii_mui_2dsk_e {
MII_2DSK_DISKII = 0,

View File

@ -57,7 +57,11 @@ int main() {
}
fprintf(f, "/* this file is auto-generated by icon-convert-tcc.c */\n");
// fprintf(f, "#include <stdint.h>\n");
fprintf(f, "static const unsigned long mii_icon%d[] = {\n", w);
fprintf(f, "#define MII_ICON%d_SIZE %d\n", w, (w * h + 2));
fprintf(f, "extern const unsigned long mii_icon%d[MII_ICON%d_SIZE];\n", w, w);
fprintf(f, "#ifdef MII_ICON%d_DEFINE\n", w);
fprintf(f, "const unsigned long mii_icon%d[MII_ICON%d_SIZE] = {\n",
w, w);
fprintf(f, "\t%d,%d,\n", w, h);
for (int y = 0; y < h; y++) {
fprintf(f, "\t");
@ -74,6 +78,7 @@ int main() {
fprintf(f, "\n");
}
fprintf(f, "};\n");
fprintf(f, "#endif\n");
fclose(f);
free(pixels);
}