mirror of
https://github.com/buserror/mii_emu.git
synced 2025-04-08 13:38:52 +00:00
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:
parent
01619cfe53
commit
5650323d05
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
};
|
||||
};
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
56
ui_gl/mii_loadbin.c
Normal 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;
|
||||
}
|
@ -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);
|
||||
|
@ -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
90
ui_gl/mii_mui_about.c
Normal 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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user