Mostly libmui changes

+ Updated libmui
+ Typehead in the standard file dialog
+ More documentation in the header file
+ Made regexp optional, added a new way to specify suffix list

Signed-off-by: Michel Pollet <buserror@gmail.com>
This commit is contained in:
Michel Pollet 2024-02-04 09:09:28 +00:00
parent 6c5a52bd15
commit ad86adfea4
No known key found for this signature in database
24 changed files with 410 additions and 109 deletions

View File

@ -91,11 +91,12 @@ VPATH += test
# Base test without the UI, for performance testing
$(BIN)/mii_test : $(TEST_OBJ)
$(BIN)/mii_test : $(OBJ)/mii_test.o $(OBJ)/mii_mish.o
$(OBJ)/mii_test.o : CFLAGS += -O0 -Og
$(OBJ)/mii_test.o : CFLAGS := -O0 -Og ${filter-out -O%, $(CFLAGS)}
$(OBJ)/mii_cpu_test.o : CFLAGS += -O0 -Og
$(OBJ)/mii_cpu_test.o : CFLAGS := -O0 -Og ${filter-out -O%, $(CFLAGS)}
$(BIN)/mii_cpu_test : $(OBJ)/mii_cpu_test.o $(TEST_OBJ)
# Assembler for the 6502
$(BIN)/mii_asm : $(OBJ)/mii_asm.o $(TEST_OBJ)
ifeq ($(V),1)
@ -105,7 +106,7 @@ Q := @
endif
$(OBJ)/%.o : %.c | $(OBJ)
@echo " CC " ${filter -O%, $(CPPFLAGS) $(CFLAGS)} " $<"
@echo " CC" ${filter -O%, $(CPPFLAGS) $(CFLAGS)} "$<"
$(Q)$(CC) -MMD $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
$(BIN)/% : | $(BIN)

View File

@ -72,7 +72,7 @@ $(LIB)/ui_tests.so : $(OBJ)/ui_tests.o $(LIB)/libmui.a | $(O)
$(BIN)/mui_playground : $(OBJ)/mui_playground.o $(LIB)/libmui.a
$(OBJ)/%.o : %.c | $(OBJ)
@echo " CC " ${filter -O%, $(CPPFLAGS) $(CFLAGS)} " $<"
@echo " CC" ${filter -O%, $(CPPFLAGS) $(CFLAGS)} "$<"
$(Q)$(CC) -MMD $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
$(BIN)/% : | $(BIN)

View File

@ -151,7 +151,8 @@ void cg_matrix_multiply(struct cg_matrix_t * m, struct cg_matrix_t * m1, struct
t.tx += m1->ty * m2->c;
t.ty += m1->tx * m2->b;
}
memcpy(m, &t, sizeof(struct cg_matrix_t));
*m = t;
// memcpy(m, &t, sizeof(struct cg_matrix_t));
}
void cg_matrix_invert(struct cg_matrix_t * m)

View File

@ -18,8 +18,12 @@ void
mui_init(
mui_t *ui)
{
// do NOT clear we rely on screen_size being set, this is temporary we'll
// eventually use an 'option' struct to pass that sort of data (and the
// colors)
//memset(ui, 0, sizeof(*ui));
ui->clear_color = MUI_COLOR(0xccccccff);
ui->color.clear = MUI_COLOR(0xccccccff);
ui->color.highlight = MUI_COLOR(0xd6fcc0ff);
TAILQ_INIT(&ui->windows);
TAILQ_INIT(&ui->zombies);
TAILQ_INIT(&ui->fonts);
@ -95,9 +99,9 @@ mui_draw(
mui_drawable_clip_push_region(dr, &sect);
pixman_image_fill_boxes(
ui->clear_color.value ? PIXMAN_OP_SRC : PIXMAN_OP_CLEAR,
ui->color.clear.value ? PIXMAN_OP_SRC : PIXMAN_OP_CLEAR,
mui_drawable_get_pixman(dr),
&PIXMAN_COLOR(ui->clear_color), 1, (pixman_box32_t*)&desk);
&PIXMAN_COLOR(ui->color.clear), 1, (pixman_box32_t*)&desk);
pixman_region32_fini(&sect);
pixman_region32_fini(&done);
@ -228,6 +232,28 @@ mui_timer_register(
return 0;
}
mui_time_t
mui_timer_reset(
struct mui_t * ui,
uint8_t id,
mui_timer_p cb,
mui_time_t delay)
{
if (id >= MUI_TIMER_COUNT)
return 0;
if (!(ui->timer.map & (1 << id)) ||
ui->timer.timers[id].cb != cb)
return 0;
mui_time_t res = 0;
uint64_t now = mui_get_time();
if (ui->timer.timers[id].when > now)
res = ui->timer.timers[id].when - now;
ui->timer.timers[id].when = now + delay;
if (delay == 0)
ui->timer.map &= ~(1 << id);
return res;
}
void
mui_timers_run(
mui_t *ui )

View File

@ -216,7 +216,7 @@ typedef bool (*mui_wdef_p)(
struct mui_window_t * win,
uint8_t what,
void * param);
enum {
enum mui_cdef_e {
MUI_CDEF_INIT = 0,
MUI_CDEF_DISPOSE,
MUI_CDEF_DRAW,
@ -308,6 +308,16 @@ DECLARE_C_ARRAY(mui_region_t, mui_clip_stack, 2);
* image, AND also the context for the 'cg' vectorial library.
* Furthermore it keeps track of a stack of clipping rectangles, and is able
* to 'sync' the current clipping area for either (or both) cg and libpixman.
*
* Important note: the cg vectorial library coordinate system is placed on the
* space *between* pixels, ie, if you moveto(1,1) and draw a line down, you
* will light up pixels in columns zero AND one. This differs significantly from
* for example, pixman that is uses pixel coordinates on hard pixels.
* It's worth remembering as if you draw for example around the border of a
* control, it will very likely be 'clipped' somewhat because half the pixels
* are technically outside the control bounding/clipping rectangle.
* You can easily adjust for this by adding 0.5 to the coordinates, if you
* require it.
*/
typedef struct mui_drawable_t {
mui_pixmap_t pix; // *has* to be first in struct
@ -604,7 +614,7 @@ DECLARE_C_ARRAY(mui_menu_item_t, mui_menu_items, 2,
bool read_only; );
IMPLEMENT_C_ARRAY(mui_menu_items);
enum {
enum mui_menubar_action_e {
// parameter is a mui_menu_item_t* for the first item of the menu,
// this is exactly the parameter passed to add_simple()
// you can use this to disable/enable menu items etc
@ -658,14 +668,14 @@ enum mui_control_type_e {
MUI_CONTROL_POPUP,
};
enum {
enum mui_button_style_e {
MUI_BUTTON_STYLE_NORMAL = 0,
MUI_BUTTON_STYLE_DEFAULT = 1,
MUI_BUTTON_STYLE_RADIO,
MUI_BUTTON_STYLE_CHECKBOX,
};
enum {
enum mui_control_state_e {
MUI_CONTROL_STATE_NORMAL = 0,
MUI_CONTROL_STATE_HOVER,
MUI_CONTROL_STATE_CLICKED,
@ -673,7 +683,7 @@ enum {
MUI_CONTROL_STATE_COUNT
};
enum {
enum mui_control_action_e {
MUI_CONTROL_ACTION_NONE = 0,
MUI_CONTROL_ACTION_VALUE_CHANGED = FCC('c','v','a','l'),
MUI_CONTROL_ACTION_CLICKED = FCC('c','l','k','d'),
@ -854,14 +864,42 @@ enum mui_std_action_e {
MUI_STDF_ACTION_SELECT = FCC('s','t','d','s'),
MUI_STDF_ACTION_CANCEL = FCC('s','t','d','c'),
};
enum mui_std_flags_e {
// 'pattern' is a GNU extended regexp applied to filenames.
MUI_STDF_FLAG_REGEXP = (1 << 0),
// don't use the 'pref_directory', load, or same preference files
MUI_STDF_FLAG_NOPREF = (1 << 1),
};
/*
* Standard file dialog related
*
* Presents a standard 'get' file dialog, with optional prompt, regexp and
* start path. The return value is a pointer to a window, you can add your own
* 'action' function to get MUI_STDF_ACTION_* events.
* Once in the action function, you can call mui_stdfile_get_selected_path()
* to get the selected path, and free it when done.
* NOTE: The dialog does not auto-close, your own action function should close
* the dialog using mui_window_dispose().
*
* The dialog will attempt to remember the last directory used *for this
* particular pattern* and will use it as the default start path when called
* again. This is optional, it requires a mui->pref_directory to be set.
* You can also disable this feature by setting the MUI_STDF_FLAG_NOPREF flag.
*
* + 'pattern' is a regular expression to filter the files, or NULL for no
* filter.
* + if 'start_path' is NULL, the $HOME directory is used.
* + 'where' is the location of the dialog, (0,0) will center it.
*/
mui_window_t *
mui_stdfile_get(
struct mui_t * ui,
c2_pt_t where,
const char * prompt,
const char * regexp,
const char * start_path );
const char * pattern,
const char * start_path,
uint16_t flags );
// return the curently selected pathname -- caller must free() it
char *
mui_stdfile_get_selected_path(
@ -870,7 +908,7 @@ mui_stdfile_get_selected_path(
/*
* Alert dialog
*/
enum {
enum mui_alert_flag_e {
MUI_ALERT_FLAG_OK = (1 << 0),
MUI_ALERT_FLAG_CANCEL = (1 << 1),
@ -893,7 +931,7 @@ mui_alert(
const char * message,
uint16_t flags );
enum {
enum mui_time_e {
MUI_TIME_RES = 1,
MUI_TIME_SECOND = 1000000,
MUI_TIME_MS = (MUI_TIME_SECOND/1000),
@ -901,20 +939,22 @@ enum {
mui_time_t
mui_get_time();
#define MUI_TIMER_COUNT 64
typedef struct mui_timer_group_t {
uint64_t map;
struct {
mui_time_t when;
mui_timer_p cb;
void * param;
} timers[64];
} timers[MUI_TIMER_COUNT];
} mui_timer_group_t;
/*
* Register 'cb' to be called after 'delay'. Returns a timer id (0 to 63)
* or 0xff if no timer is available. The timer function cb can return 0 for a one
* shot timer, or another delay that will be added to the current stamp for a further
* call of the timer.
* or 0xff if no timer is available. The timer function cb can return 0 for a
* one shot timer, or another delay that will be added to the current stamp
* for a further call of the timer.
* 'param' will be also passed to the timer callback.
*/
uint8_t
@ -923,10 +963,25 @@ mui_timer_register(
mui_timer_p cb,
void * param,
uint32_t delay);
/*
* Reset timer 'id' if 'cb' matches what was registered. Set a new delay,
* or cancel the timer if delay is 0.
* Returns the time that was left on the timer, or 0 if the timer was
* not found.
*/
mui_time_t
mui_timer_reset(
struct mui_t * ui,
uint8_t id,
mui_timer_p cb,
mui_time_t delay);
typedef struct mui_t {
c2_pt_t screen_size;
mui_color_t clear_color;
struct {
mui_color_t clear;
mui_color_t highlight;
} color;
uint16_t modifier_keys;
int draw_debug;
// this is the sum of all the window's dirty regions, inc moved windows etc

View File

@ -24,6 +24,13 @@ typedef struct mui_listbox_control_t {
mui_ldef_p ldef;
// to handle double-click
mui_time_t last_click;
// typehead search related
struct {
uint8_t enabled;
uint8_t timer;
char buf[32];
uint8_t index;
} typehead;
} mui_listbox_control_t;
extern const mui_control_color_t mui_control_color[MUI_CONTROL_STATE_COUNT];
@ -56,7 +63,7 @@ mui_listbox_draw(
mui_font_t * icons = mui_font_find(win->ui, "icon_small");
mui_font_t * main = mui_font_find(win->ui, "main");
mui_color_t highlight = MUI_COLOR(0xd6fcc0ff);
mui_color_t highlight = win->ui->color.highlight;
for (unsigned int ii = top_element;
ii < lb->elems.count && ii < bottom_element; ii++) {
@ -85,13 +92,70 @@ mui_listbox_draw(
mui_drawable_clip_pop(dr);
}
/* mui_timer used to 'cancel' the typehead if a certain delay has lapsed */
static mui_time_t
mui_listbox_typehead_timer(
struct mui_t * mui,
mui_time_t now,
void * param)
{
mui_listbox_control_t *lb = param;
lb->typehead.enabled = 0;
lb->typehead.timer = 0xff;
lb->typehead.index = 0;
// printf("typehead: cancelled\n");
return 0;
}
static int32_t
mui_listbox_typehead(
mui_listbox_control_t *lb,
mui_event_t * ev)
{
if (ev->key.key < 32 || ev->key.key > 127)
return false;
if (!lb->typehead.enabled) {
lb->typehead.enabled = 1;
lb->typehead.index = 0;
lb->typehead.timer = mui_timer_register(
lb->control.win->ui,
mui_listbox_typehead_timer,
lb, MUI_TIME_MS * 1000);
}
// add character to the current prefix
if (lb->typehead.index < sizeof(lb->typehead.buf) - 1)
lb->typehead.buf[lb->typehead.index++] = ev->key.key;
lb->typehead.buf[lb->typehead.index] = 0;
// printf("typehead: %d '%s'\n", lb->typehead.index, lb->typehead.buf);
// reset cancel timer
mui_timer_reset(lb->control.win->ui,
lb->typehead.timer, mui_listbox_typehead_timer,
MUI_TIME_MS * 1000);
// we do the lookup twice, once with the case sensitive test, and if
// that find something that matches, we're good. If not, try to match
// the prefix in a non-case sensitive way in case the user doesn't know
// what he wants...
for (unsigned int ii = 0; ii < lb->elems.count; ii++) {
mui_listbox_elem_t *e = &lb->elems.e[ii];
if (strncmp(e->elem, lb->typehead.buf, lb->typehead.index) == 0)
return ii - lb->control.value;
}
for (unsigned int ii = 0; ii < lb->elems.count; ii++) {
mui_listbox_elem_t *e = &lb->elems.e[ii];
if (strncasecmp(e->elem, lb->typehead.buf, lb->typehead.index) == 0)
return ii - lb->control.value;
}
// printf("typehead: no match\n");
return 0;
}
static bool
mui_listbox_key(
mui_control_t * c,
mui_event_t * ev)
{
mui_listbox_control_t *lb = (mui_listbox_control_t *)c;
printf("%s key: %d\n", __func__, ev->key.key);
// printf("%s key: %d '%c'\n", __func__, ev->key.key, ev->key.key);
c2_rect_t f = c->frame;
c2_rect_offset(&f, -f.l, -f.t);
uint32_t page_size = (c2_rect_height(&f) / lb->elem_height)-1;
@ -99,6 +163,8 @@ mui_listbox_key(
int delta = 0;
if (ev->modifiers & (MUI_MODIFIER_SUPER | MUI_MODIFIER_CTRL))
return false;
if (isalpha(ev->key.key))
delta = mui_listbox_typehead(lb, ev);
switch (ev->key.key) {
case MUI_KEY_UP: delta = -1; break;
case MUI_KEY_DOWN: delta = 1; break;
@ -121,17 +187,16 @@ mui_listbox_key(
-e.t + (c->value * lb->elem_height));
c2_rect_t w = f;
c2_rect_offset(&w, 0, lb->scroll);
printf(" e:%s f:%s\n", c2_rect_as_str(&e), c2_rect_as_str(&w));
// printf(" e:%s f:%s\n", c2_rect_as_str(&e), c2_rect_as_str(&w));
if (e.b > w.b) {
lb->scroll = (e.b - c2_rect_height(&c->frame));
printf(" over %d\n", lb->scroll);
// printf(" over %d\n", lb->scroll);
}
if (e.t < w.t)
lb->scroll = e.t;
printf(" scroll:%d\n", lb->scroll);
// printf(" scroll:%d\n", lb->scroll);
mui_control_set_value(lb->scrollbar, lb->scroll);
mui_control_inval(c);
// mui_control_inval(lb->scrollbar);
mui_control_action(c, MUI_CONTROL_ACTION_VALUE_CHANGED,
&lb->elems.e[nsel]);
return true;
@ -177,15 +242,7 @@ mui_cdef_event(
}
return true;
} break;
case MUI_EVENT_KEYUP: { // ignore keydowns
if (ev->key.key == 13) {
if (!lb->elems.e[c->value].disabled) {
mui_control_action(c,
MUI_CONTROL_ACTION_SELECT,
&lb->elems.e[c->value]);
}
return true;
}
case MUI_EVENT_KEYUP: {
if (mui_listbox_key(c, ev))
return true;
} break;

View File

@ -12,12 +12,17 @@
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <regex.h>
#include <errno.h>
#include <sys/stat.h>
#include <glob.h>
#include <libgen.h>
#ifdef __linux__
#define MUI_HAS_REGEXP
#endif
#ifdef MUI_HAS_REGEXP
#include <regex.h>
#endif
#include "mui.h"
#include "c2_geometry.h"
@ -27,16 +32,24 @@
DECLARE_C_ARRAY(char*, string_array, 2);
IMPLEMENT_C_ARRAY(string_array);
#define MUI_STDF_MAX_SUFFIX 16
typedef struct mui_stdfile_t {
mui_window_t win;
mui_control_t * ok, *cancel, *home, *root;
mui_control_t * listbox, *popup;
char * pref_file; // pathname we put last path used
char * re_pattern;
struct {
char s[16];
uint32_t hash;
} suffix[MUI_STDF_MAX_SUFFIX];
char * current_path;
char * selected_path;
regex_t re;
string_array_t pop_path;
#ifdef MUI_HAS_REGEXP
regex_t re;
#endif
} mui_stdfile_t;
enum {
@ -66,6 +79,24 @@ _mui_stdfile_sort_cb(
return strcmp(ea->elem, eb->elem);
}
static uint32_t
mui_hash_nocase(
const char * inString )
{
if (!inString)
return 0;
/* Described http://papa.bretmulvey.com/post/124027987928/hash-functions */
const uint32_t p = 16777619;
uint32_t hash = 0x811c9dc5;
while (*inString)
hash = (hash ^ tolower(*inString++)) * p;
hash += hash << 13;
hash ^= hash >> 7;
hash += hash << 3;
hash ^= hash >> 17;
hash += hash << 5;
return hash;
}
static int
_mui_stdfile_populate(
mui_stdfile_t * std,
@ -139,10 +170,35 @@ _mui_stdfile_populate(
stat(full_path, &st);
free(full_path);
mui_listbox_elem_t e = {};
// usr the regex to filter file names
if (std->re_pattern) {
if (!S_ISDIR(st.st_mode) && regexec(&std->re, ent->d_name, 0, NULL, 0))
e.disabled = 1;
// default to disable, unless we find a reason to enable
e.disabled = S_ISDIR(st.st_mode) ? 0 : 1;
// use the regex (if any) to filter file names
if (e.disabled && std->re_pattern) {
#ifdef MUI_HAS_REGEXP
if (regexec(&std->re, ent->d_name, 0, NULL, 0) == 0)
e.disabled = 0;
#endif
}
// handle case when no regexp is set, and no suffixes was set, this
// we enable all the files by default.
if (e.disabled && !std->re_pattern)
e.disabled = std->suffix[0].s[0] ? 1 : 0;
// handle the case we have a list of dot suffixes to filter
if (e.disabled) {
char *suf = strrchr(ent->d_name, '.');
if (std->suffix[0].s[0] && suf) {
suf++;
uint32_t hash = mui_hash_nocase(suf);
for (int i = 0; i < MUI_STDF_MAX_SUFFIX &&
std->suffix[i].s[0]; i++) {
if (hash == std->suffix[i].hash &&
!strcasecmp(suf, std->suffix[i].s)) {
e.disabled = 0;
break;
}
}
}
}
e.elem = strdup(ent->d_name);
if (S_ISDIR(st.st_mode))
@ -268,11 +324,12 @@ _mui_stdfile_control_action(
mui_window_t *
mui_stdfile_get(
struct mui_t * ui,
c2_pt_t where,
const char * prompt,
const char * regexp,
const char * start_path )
struct mui_t * ui,
c2_pt_t where,
const char * prompt,
const char * pattern,
const char * start_path,
uint16_t flags )
{
c2_rect_t wpos = C2_RECT_WH(where.x, where.y, 700, 400);
if (where.x == 0 && where.y == 0)
@ -285,9 +342,10 @@ mui_stdfile_get(
prompt, sizeof(mui_stdfile_t));
mui_window_set_action(w, _mui_stdfile_window_action, NULL);
mui_stdfile_t *std = (mui_stdfile_t *)w;
if (regexp) {
std->re_pattern = strdup(regexp);
int re = regcomp(&std->re, std->re_pattern, REG_EXTENDED);
if (pattern && *pattern && (flags & MUI_STDF_FLAG_REGEXP)) {
#ifdef MUI_HAS_REGEXP
std->re_pattern = strdup(pattern);
int re = regcomp(&std->re, std->re_pattern, REG_EXTENDED|REG_ICASE);
if (re) {
char * msg = NULL;
asprintf(&msg, "%s\n%s", std->re_pattern,
@ -299,6 +357,26 @@ mui_stdfile_get(
free(std->re_pattern);
std->re_pattern = NULL;
}
#else
printf("%s: Regexp not supported\n", __func__);
#endif
} else if (pattern && *pattern) {
char * dup = strdup(pattern);
char * w = dup;
char * suf;
int di = 0;
while ((suf = strsep(&w, ",")) != NULL) {
if (!*suf)
continue;
if (di >= MUI_STDF_MAX_SUFFIX) {
printf("%s Too many suffixes, ignoring: %s\n", __func__, suf);
break;
}
uint32_t hash = mui_hash_nocase(suf);
snprintf(std->suffix[di].s, sizeof(std->suffix[di].s), "%s", suf);
std->suffix[di].hash = hash;
di++;
}
}
mui_control_t * c = NULL;
c2_rect_t cf;
@ -349,7 +427,7 @@ mui_stdfile_get(
mui_control_set_action(c, _mui_stdfile_control_action, std);
}
int dopop = 1; // populate to start_path by default
if (ui->pref_directory) {
if (!(flags & MUI_STDF_FLAG_NOPREF) && ui->pref_directory) {
uint32_t hash = std->re_pattern ? mui_hash(std->re_pattern) : 0;
asprintf(&std->pref_file, "%s/std_path_%04x", ui->pref_directory, hash);
printf("%s pref file: %s\n", __func__, std->pref_file);

View File

@ -187,8 +187,8 @@ _init(
mui_stdfile_get(ui,
C2_PT(0, 0),
"Select image for SmartPort card",
"\\.(hdv|po|2mg)$",
getenv("HOME"));
"hdv,po,2mg",
getenv("HOME"), 0);
#endif
return g;
@ -233,4 +233,4 @@ mui_plug_t mui_plug = {
.dispose = _dispose,
.draw = _draw,
.event = _event,
};
};

View File

@ -322,6 +322,18 @@ mii_access_soft_switches(
*byte = on;
}
} break;
/*
SATHER-SATHER-SATHER-SATHER-SATHER-SATHER-SATHER-SATHER-SATHER-SATHER
Writing to high RAM is enabled when the HRAMWRT' soft switch is reset.
The controlling MPU program must set the PRE-WRITE soft switch before
it can reset HRAMWRT'. PRE-WRITE is set in the by odd read access ub the
C08X range. It is reset by even read access or any write access in the
$C08X range.
HRAMWRT' is reset by odd read access in the $C08X range when PRE-WRITE is
set. It is set by even acce.ss in the $C08X range. Any other type of access
causes HRAMWRT' to hold its current state.
*/
case 0xc080 ... 0xc08f: {
res = true;
uint8_t mode = addr & 0x0f;
@ -329,16 +341,25 @@ mii_access_soft_switches(
static const int read_modes[4] = { 1, 0, 0, 1, };
uint8_t rd = read_modes[mode & 3];
uint8_t wr = write_modes[mode & 3];
if (write) {
SW_SETSTATE(mii, BSRPREWRITE, 0);
} else {
SW_SETSTATE(mii, BSRPREWRITE, mode & 1);
}
// if (SW_GETSTATE(mii, BSRPREWRITE))
// ;
SW_SETSTATE(mii, BSRWRITE, wr);
SW_SETSTATE(mii, BSRREAD, rd);
SW_SETSTATE(mii, BSRPAGE2, !(mode & 0x08));
SW_SETSTATE(mii, BSRPAGE2, !(mode & 0x08)); // A3
mii->mem_dirty = 1;
// mii->trace_cpu = 1;
// mii->state = MII_STOPPED;
if (unlikely(mii->trace_cpu))
printf("%04x: BSR mode addr %04x:%02x read:%s write:%s %s altzp:%02x\n",
mii->cpu.PC, addr,
mode,
printf("%04x: BSR mode %c%04x pre:%d read:%s write:%s %s altzp:%02x\n",
mii->cpu.PC, write ? 'W' : 'R',
addr,
SW_GETSTATE(mii, BSRPREWRITE),
rd ? "BSR" : "ROM",
wr ? "BSR" : "ROM",
SW_GETSTATE(mii, BSRPAGE2) ? "page2" : "page1",

View File

@ -1,3 +1,10 @@
/*
* mui_65c02.c
*
* Copyright (C) 2023 Michel Pollet <buserror@gmail.com>
*
* SPDX-License-Identifier: MIT
*/
#include <stdint.h>
#include <stdio.h>

View File

@ -1,3 +1,11 @@
/*
* mui_65c02.h
*
* Copyright (C) 2023 Michel Pollet <buserror@gmail.com>
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <stdint.h>

View File

@ -1,3 +1,10 @@
/*
* mui_65c02_asm.h
*
* Copyright (C) 2023 Michel Pollet <buserror@gmail.com>
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <stdint.h>

View File

@ -1,3 +1,10 @@
/*
* mii_65c02_disasm.c
*
* Copyright (C) 2023 Michel Pollet <buserror@gmail.com>
*
* SPDX-License-Identifier: MIT
*/
#include <stdio.h>
#include <stdlib.h>

View File

@ -1,3 +1,11 @@
/*
* mii_65c02_disasm.h
*
* Copyright (C) 2023 Michel Pollet <buserror@gmail.com>
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <stdint.h>

View File

@ -1,3 +1,11 @@
/*
* mui_65c02_ops.h
*
* Copyright (C) 2023 Michel Pollet <buserror@gmail.com>
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <stdint.h>

View File

@ -78,10 +78,11 @@ enum {
B_BSRWRITE = (12),
B_BSRREAD = (13),
B_BSRPAGE2 = (14),
B_SWDHIRES = (15),
B_BSRPREWRITE = (15),
B_SWDHIRES = (16),
// this is no 'real' softwitch, but a bit to mention a card has
// it's secondary rom online in pages c800-cfff
B_SLOTAUXROM = (16),
B_SLOTAUXROM = (17),
M_SW80STORE = (1 << B_SW80STORE),
M_SWALTCHARSET = (1 << B_SWALTCHARSET),
@ -98,6 +99,7 @@ enum {
M_BSRWRITE = (1 << B_BSRWRITE),
M_BSRREAD = (1 << B_BSRREAD),
M_BSRPAGE2 = (1 << B_BSRPAGE2),
M_BSRPREWRITE = (1 << B_BSRPREWRITE),
M_SWDHIRES = (1 << B_SWDHIRES),
M_SLOTAUXROM = (1 << B_SLOTAUXROM),
};
@ -121,6 +123,7 @@ static const char __unused__ *mii_sw_names[] = {
"BSRWRITE",
"BSRREAD",
"BSRPAGE2",
"BSRPREWRITE",
"DHIRES",
"AUXROMON",
NULL,

View File

@ -41,7 +41,7 @@ enum {
*/
typedef struct mii_color_t {
uint32_t rgb;
uint8_t l;
uint32_t l : 8, index : 8;
} mii_color_t;
#define HI_LUMA(r,g,b) \
@ -61,22 +61,22 @@ typedef struct mii_color_t {
* Well not really, it is just ONE interpreation of many, we could possibly
* make some sort of color lookup table to allow switching them on the fly?
*/
#define C_BLACK HI_RGB(0x00, 0x00, 0x00) // black
#define C_PURPLE HI_RGB(0xff, 0x44, 0xfd) // purple
#define C_GREEN HI_RGB(0x14, 0xf5, 0x3c) // green
#define C_BLUE HI_RGB(0x14, 0xcf, 0xfd) // blue
#define C_ORANGE HI_RGB(0xff, 0x6a, 0x3c) // orange
#define C_WHITE HI_RGB(0xff, 0xff, 0xff) // white
#define C_MAGENTA HI_RGB(0xe3, 0x1e, 0x60) // magenta
#define C_DARKBLUE HI_RGB(0x60, 0x4e, 0xbd) // dark blue
#define C_DARKGREEN HI_RGB(0x00, 0xa3, 0x60) // dark green
#define C_GRAY1 HI_RGB(0x9c, 0x9c, 0x9c) // gray 1
#define C_GRAY2 HI_RGB(0x9c, 0x9c, 0x9c) // gray 2
#define C_LIGHTBLUE HI_RGB(0xd0, 0xc3, 0xff) // light blue
#define C_BROWN HI_RGB(0x60, 0x72, 0x03) // brown
#define C_PINK HI_RGB(0xff, 0xa0, 0xd0) // pink
#define C_YELLOW HI_RGB(0xd0, 0xdd, 0x8d) // yellow
#define C_AQUA HI_RGB(0x72, 0xff, 0xd0) // aqua
#define C_BLACK HI_RGB(0x00, 0x00, 0x00)
#define C_PURPLE HI_RGB(0xff, 0x44, 0xfd)
#define C_GREEN HI_RGB(0x14, 0xf5, 0x3c)
#define C_BLUE HI_RGB(0x14, 0xcf, 0xfd)
#define C_ORANGE HI_RGB(0xff, 0x6a, 0x3c)
#define C_WHITE HI_RGB(0xff, 0xff, 0xff)
#define C_MAGENTA HI_RGB(0xe3, 0x1e, 0x60)
#define C_DARKBLUE HI_RGB(0x60, 0x4e, 0xbd)
#define C_DARKGREEN HI_RGB(0x00, 0xa3, 0x60)
#define C_GRAY1 HI_RGB(0x9c, 0x9c, 0x9c)
#define C_GRAY2 HI_RGB(0x9c, 0x9c, 0x9c)
#define C_LIGHTBLUE HI_RGB(0xd0, 0xc3, 0xff)
#define C_BROWN HI_RGB(0x60, 0x72, 0x03)
#define C_PINK HI_RGB(0xff, 0xa0, 0xd0)
#define C_YELLOW HI_RGB(0xd0, 0xdd, 0x8d)
#define C_AQUA HI_RGB(0x72, 0xff, 0xd0)
// this is not an official color, just 'my' interpretation of an amber screen
#define C_AMBER HI_RGB(0xfd, 0xcf, 0x14) // amber
@ -126,6 +126,7 @@ static inline uint8_t reverse8(uint8_t b) {
b = (b & 0b10101010) >> 1 | (b & 0b01010101) << 1;
return b;
}
// Used for DHRES decoding
static inline uint8_t reverse4(uint8_t b) {
b = (b & 0b0001) << 3 | (b & 0b0010) << 1 |
(b & 0b0100) >> 1 | (b & 0b1000) >> 3;
@ -461,8 +462,31 @@ mii_video_init(
{
mii->video.timer_id = mii_timer_register(mii,
mii_video_timer_cb, NULL, MII_VIDEO_H_CYCLES, __func__);
// start the DHRES in color
mii_bank_t * main = &mii->bank[MII_BANK_MAIN];
mii_bank_poke(main, SWAN3_REGISTER, 1);
}
/* given a RGB color r,g,b, print a table of 16 RGB colors that are graded
from luminance 0 to 1 in that particular shade of color.
*/
void
mii_video_print_color_table(
uint32_t rgb)
{
uint8_t b = (rgb >> 16) & 0xff;
uint8_t g = (rgb >> 8) & 0xff;
uint8_t r = (rgb >> 0) & 0xff;
uint8_t l = HI_LUMA(r, g, b);
printf("// LUMA %d start color %02x %02x %02x\n{ ", l, r, g, b);
for (int i = 0; i < 16; i++) {
uint8_t ll = (l * i) / 15;
uint8_t rr = (r * ll) / l;
uint8_t gg = (g * ll) / l;
uint8_t bb = (b * ll) / l;
printf("%01x: %02x %02x %02x\n", i, rr, gg, bb);
}
}
static void
@ -471,7 +495,7 @@ _mii_mish_video(
int argc,
const char * argv[])
{
mii_t * mii = param;
// mii_t * mii = param;
if (!argv[1] || !strcmp(argv[1], "list")) {
for (int i = 0; i < 16; i++) {
@ -482,6 +506,11 @@ _mii_mish_video(
}
return;
}
if (!strcmp(argv[1], "gradient")) {
mii_video_print_color_table(lores_colors[0][1].rgb);
return;
}
}
#include "mish.h"

View File

@ -877,7 +877,7 @@ mii_x11_reload_config(
mii_reset(mii, true);
/* start the CPU/emulator thread */
ui->cpu_thread = mii_thread_start(mii);
ui->cpu_thread = mii_threads_start(mii);
}
mii_x11_t g_mii = {};
@ -932,7 +932,7 @@ main(
mii_x11_init(ui);
mui_t * mui = &ui->video.mui; // to move to a function later
mui_init(mui);
mui->clear_color.value = 0;
mui->color.clear.value = 0;
asprintf(&mui->pref_directory, "%s/.local/share/mii", getenv("HOME"));
mii_mui_menus_init((mii_mui_t*)ui);
@ -957,7 +957,7 @@ main(
mii_config_open_slots_dialog(&ui->video);
}
/* start the CPU/emulator thread */
ui->cpu_thread = mii_thread_start(mii);
ui->cpu_thread = mii_threads_start(mii);
while (mii->state != MII_INIT) {
/* Input */

View File

@ -204,7 +204,8 @@ _mii_1mb_action_cb(
C2_PT(0, 0),
"Select a file (Exactly 1MB in size)",
"\\.(po|hdv|bin|rom)$",
getenv("HOME"));
getenv("HOME"),
MUI_STDF_FLAG_REGEXP);
mui_window_set_action(w, _mii_1mb_stdfile_cb, m);
} break;
case MII_1MB_USE_BIN:

View File

@ -143,7 +143,8 @@ _mii_2dsk_action_cb(
m->drive_kind == MII_2DSK_SMARTPORT ?
"\\.(po|hdv|2mg)$" :
"\\.(dsk)$",
getenv("HOME"));
getenv("HOME"),
MUI_STDF_FLAG_REGEXP);
mui_window_set_action(w, _mii_2dsk_stdfile_cb, m);
}
} break;

View File

@ -89,7 +89,8 @@ _mii_loadbin_action_cb(
C2_PT(0, 0),
"Select a .bin file to run",
"\\.(bin|rom)$",
getenv("HOME"));
getenv("HOME"),
MUI_STDF_FLAG_REGEXP);
mui_window_set_action(w, _mii_loadbin_stdfile_cb, m);
} break;
}

View File

@ -17,8 +17,7 @@
#include <stdint.h>
#include "bsd_queue.h"
#include "c_array.h"
#include "mui.h"
#define MII_PATH_SIZE_MAX 256

View File

@ -23,23 +23,6 @@
#include "mii.h"
#include "mii_thread.h"
#include <time.h>
typedef uint64_t mii_time_t;
enum {
MII_TIME_RES = 1,
MII_TIME_SECOND = 1000000,
MII_TIME_MS = (MII_TIME_SECOND/1000),
};
mii_time_t
mii_get_time()
{
struct timespec tim;
clock_gettime(CLOCK_MONOTONIC_RAW, &tim);
uint64_t time = ((uint64_t)tim.tv_sec) * (1000000 / MII_TIME_RES) +
tim.tv_nsec / (1000 * MII_TIME_RES);
return time;
}
static float default_fps = 60;
mii_th_fifo_t signal_fifo;
@ -229,7 +212,7 @@ mii_thread_joystick(
#endif
pthread_t
mii_thread_start(
mii_threads_start(
mii_t *mii)
{
const mii_th_fifo_t zero = {};

View File

@ -11,7 +11,7 @@
#include <stdint.h>
#include "fifo_declare.h"
enum {
enum mii_th_state_e {
SIGNAL_RESET,
SIGNAL_STOP,
SIGNAL_STEP,
@ -19,8 +19,8 @@ enum {
};
typedef struct mii_th_signal_t {
uint8_t cmd;
uint8_t data;
uint8_t cmd;
uint8_t data;
} mii_th_signal_t;
DECLARE_FIFO(mii_th_signal_t, mii_th_fifo, 16);
@ -29,7 +29,7 @@ DEFINE_FIFO(mii_th_signal_t, mii_th_fifo);
struct mii_t;
pthread_t
mii_thread_start(
mii_threads_start(
struct mii_t *mii);
struct mii_th_fifo_t*
mii_thread_get_fifo(