ref: cec6a8217fa2ae90a72226959e215b663c88bc41
parent: fd304c53cc45dc05b3f95c20a466e20a7e1c9194
author: sirjofri <sirjofri@sirjofri.de>
date: Fri May 10 09:06:51 EDT 2024
adds mkfile and plan9.c (intermediate commit) many things work, but some things don't. Needs menu.
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,102 @@
+</$objtype/mkfile
+
+CFLAGS=$CFLAGS -p -I/sys/include/npe -D__plan9__ -D__${objtype}__ -DNO_TGMATH_H -I. -D__plan9_keep_main__
+
+TARG=\
+ blackbox\
+ bridges\
+ cube\
+ dominosa\
+ fifteen\
+ filling\
+ flip\
+ flood\
+ galaxies\
+ guess\
+ inertia\
+ keen\
+ lightup\
+ loopy\
+ magnets\
+ map\
+ mines\
+ mosaic\
+ net\
+ netslide\
+ nullgame\
+ palisade\
+ pattern\
+ pearl\
+ pegs\
+ range\
+ rect\
+ samegame\
+ signpost\
+ singles\
+ sixteen\
+ slant\
+ solo\
+ tents\
+ towers\
+ tracks\
+ twiddle\
+ undead\
+ unequal\
+ unruly\
+ untangle\
+
+OFILES=\
+ combi.$O\
+ divvy.$O\
+ drawing.$O\
+ dsf.$O\
+ findloop.$O\
+ grid.$O\
+ hat.$O\
+ latin.$O\
+ laydomino.$O\
+ loopgen.$O\
+ malloc.$O\
+ matching.$O\
+ midend.$O\
+ misc.$O\
+ penrose-legacy.$O\
+ penrose.$O\
+ plan9.$O\
+ printing.$O\
+ ps.$O\
+ random.$O\
+ sort.$O\
+ spectre.$O\
+ tdq.$O\
+ tree234.$O\
+ version.$O\
+
+HFILES=\
+ grid.h\
+ hat-internal.h\
+ hat-tables.h\
+ hat.h\
+ latin.h\
+ loopgen.h\
+ matching.h\
+ penrose-internal.h\
+ penrose-legacy.h\
+ penrose.h\
+ puzzles.h\
+ spectre-internal.h\
+ spectre-tables-auto.h\
+ spectre-tables-manual.h\
+ spectre.h\
+ tree234.h\
+ version.h
+
+LIB=\
+ auxiliary/hatgen.$O\
+
+BIN=/$objtype/bin/puzzles
+
+</sys/src/cmd/mkmany
+
+auxiliary/hatgen.$O: auxiliary/hatgen.c
+ $CC $CFLAGS -o $target auxiliary/hatgen.c
--- a/penrose-legacy.h
+++ b/penrose-legacy.h
@@ -22,6 +22,10 @@
typedef struct vector vector;
+#ifdef __plan9__
+#pragma incomplete vector
+#endif
+
double penrose_legacy_vx(vector *vs, int i);
double penrose_legacy_vy(vector *vs, int i);
--- /dev/null
+++ b/plan9.c
@@ -1,0 +1,482 @@
+#include <npe.h>
+#include <draw.h>
+#include <event.h>
+
+#undef PI
+#include "puzzles.h"
+
+#ifdef COMBINED
+#error Plan 9 should not be COMBINED
+#endif
+
+struct frontend {
+ Image *image;
+ midend *me;
+ Image *background;
+ Image **colors;
+ int ncolors;
+ Point ZP;
+ int topbarh;
+};
+
+frontend *fe;
+
+void
+frontend_default_colour(frontend *fe, float *output)
+{
+ output[0] = .9;
+ output[1] = .9;
+ output[2] = .9;
+}
+
+void
+get_random_seed(void **randseed, int *randseedsize)
+{
+ long *t = malloc(sizeof(long));
+ assert(t);
+ time(t);
+ *randseed = (void*)t;
+ *randseedsize = sizeof(long);
+}
+
+void
+deactivate_timer(frontend *fe)
+{
+}
+
+void activate_timer(frontend *fe)
+{
+}
+
+void fatal(const char *fmt, ...)
+{
+ va_list ap;
+
+ fprint(2, "fatal error: ");
+
+ va_start(ap, fmt);
+ vfprint(2, fmt, ap);
+ va_end(ap);
+
+ fprint(2, "\n");
+ sysfatal("error");
+}
+
+#ifdef DEBUGGING
+void debug_printf(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vfprint(1, fmt, ap);
+ va_end(ap);
+}
+#endif
+
+void
+usage(void)
+{
+ fprint(2, "usage: %s [-ho] [--options]\n", argv0);
+ exits(nil);
+}
+
+static void p9_draw_text(void *handle, int x, int y, int fonttype, int fontsize, int align, int color, const char *text)
+{
+ frontend *fe = (frontend*)handle;
+ string(fe->image, addpt(fe->ZP, Pt(x, y)), fe->colors[color], ZP, font, text);
+}
+
+static void
+p9_draw_rect(void *handle, int x, int y, int w, int h, int color)
+{
+ frontend *fe = (frontend*)handle;
+ draw(fe->image, rectaddpt(Rect(x, y, x+w, y+h), fe->ZP), fe->colors[color], nil, ZP);
+}
+
+static void
+p9_draw_line(void *handle, int x1, int y1, int x2, int y2, int color)
+{
+ frontend *fe = (frontend*)handle;
+ line(fe->image, addpt(fe->ZP, Pt(x1, y1)), addpt(fe->ZP, Pt(x2, y2)), Endsquare, Endsquare, 1, fe->colors[color], ZP);
+}
+
+static void
+p9_draw_thick_line(void *handle, float thickness, float x1, float y1, float x2, float y2, int color)
+{
+ frontend *fe = (frontend*)handle;
+ line(fe->image, addpt(fe->ZP, Pt(x1, y1)), addpt(fe->ZP, Pt(x2, y2)), Endsquare, Endsquare, thickness, fe->colors[color], ZP);
+}
+
+static void
+p9_draw_poly(void *handle, const int *coords, int npoints, int fillcolor, int outlinecolor)
+{
+ Point *points;
+ frontend *fe = (frontend*)handle;
+
+ points = malloc(npoints * sizeof(Point));
+ for (int i = 0; i < npoints; i++) {
+ points[i].x = coords[i*2+0] + fe->ZP.x;
+ points[i].y = coords[i*2+1] + fe->ZP.y;
+ }
+
+ if (fillcolor > 0)
+ fillpoly(fe->image, points, npoints, 0, fe->colors[fillcolor], fe->ZP);
+ if (outlinecolor > 0)
+ poly(fe->image, points, npoints, Endsquare, Endsquare, 1, fe->colors[outlinecolor], fe->ZP);
+
+ free(points);
+}
+
+static void
+p9_draw_circle(void *handle, int cx, int cy, int radius, int fillcolor, int outlinecolor)
+{
+ frontend *fe = (frontend*)handle;
+ Point c = addpt(fe->ZP, Pt(cx, cy));
+ fillellipse(fe->image, c, radius, radius, fe->colors[fillcolor], ZP);
+ ellipse(fe->image, c, radius, radius, 0, fe->colors[outlinecolor], ZP);
+}
+
+static void
+p9_draw_update(void *handle, int x, int y, int w, int h)
+{
+}
+
+static void
+p9_clip(void *handle, int x, int y, int w, int h)
+{
+}
+
+static void
+p9_unclip(void *handle)
+{
+}
+
+static void
+p9_start_draw(void *handle)
+{
+}
+
+static void
+p9_end_draw(void *handle)
+{
+}
+
+static void
+p9_status_bar(void *handle, const char *text)
+{
+ frontend *fe = (frontend*)handle;
+ draw(fe->image, Rect(fe->ZP.x+10, fe->image->r.max.y-20, fe->image->r.max.x, fe->image->r.max.y), fe->background, nil, ZP);
+ string(fe->image, Pt(fe->ZP.x+10, fe->image->r.max.y-20), display->black, ZP, font, text);
+}
+
+static blitter*
+p9_blitter_new(void *handle, int w, int h)
+{
+ return nil;
+}
+
+static void
+p9_blitter_free(void *handle, blitter *bl)
+{
+}
+
+static void
+p9_blitter_save(void *handle, blitter *bl, int x, int y)
+{
+}
+
+static void
+p9_blitter_load(void *handle, blitter *bl, int x, int y)
+{
+}
+
+static const drawing_api p9_drawing = {
+ p9_draw_text,
+ p9_draw_rect,
+ p9_draw_line,
+ p9_draw_poly,
+ p9_draw_circle,
+ p9_draw_update,
+ p9_clip,
+ p9_unclip,
+ p9_start_draw,
+ p9_end_draw,
+ p9_status_bar,
+ p9_blitter_new,
+ p9_blitter_free,
+ p9_blitter_save,
+ p9_blitter_load,
+ nil, nil, nil, nil, nil, nil, nil, nil, /* {begin,end}_{doc,page,puzzle}, line_width, line_dotted */
+ nil, /* text_fallback */
+#ifdef NO_THICK_LINE
+ nil,
+#else
+ p9_draw_thick_line,
+#endif
+};
+
+static int rgb2col(int r, int g, int b)
+{
+ return (r<<24) | (g<<16) | (b<<8) | 0xFF;
+}
+
+static frontend*
+new_window(void)
+{
+ frontend *fe;
+
+ fe = mallocz(sizeof(frontend), 1);
+ if (!fe)
+ sysfatal("error: out of memory!");
+
+ fe->me = midend_new(fe, &thegame, &p9_drawing, fe);
+
+ return fe;
+}
+
+void
+initfe(frontend *fe)
+{
+ float *colors;
+ int ncolors;
+ int r, g, b;
+ int col;
+ float bgcol[3];
+
+ fe->topbarh = 20;
+ fe->image = screen;
+ fe->ZP = screen->r.min;
+ fe->ZP.y += fe->topbarh;
+
+ frontend_default_colour(fe, bgcol);
+ fe->background = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, rgb2col(bgcol[0]*255., bgcol[1]*255., bgcol[2]*255.));
+
+ colors = midend_colours(fe->me, &ncolors);
+ fe->colors = mallocz(ncolors * sizeof(Image*), 1);
+ for (int i = 0; i < ncolors; i++) {
+ r = colors[i*3+0] * 255.;
+ g = colors[i*3+1] * 255.;
+ b = colors[i*3+2] * 255.;
+ fe->colors[i] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, rgb2col(r, g, b));
+ }
+ free(colors);
+}
+
+void
+resize(void)
+{
+ int x, y;
+ x = screen->r.max.x - screen->r.min.x;
+ y = screen->r.max.y - screen->r.min.y;
+
+ midend_size(fe->me, &x, &y, 1, 1.);
+}
+
+void
+redrawui(void)
+{
+ Point to = fe->ZP;
+ to.x = fe->image->r.max.x;
+ line(fe->image, fe->ZP, to, Endsquare, Endsquare, 0, display->black, ZP);
+}
+
+void
+eresized(int new)
+{
+ if (new && getwindow(display, Refnone) < 0) {
+ sysfatal("can't reattach to window: %r");
+ }
+
+ fe->image = screen;
+ fe->ZP = screen->r.min;
+ fe->ZP.y += fe->topbarh;
+ draw(screen, screen->r, fe->background, nil, ZP);
+ resize();
+ midend_redraw(fe->me);
+ redrawui();
+}
+
+void
+keyboardev(int c, Event *ev)
+{
+ switch (c) {
+ case 'q':
+ case 127: /* DEL */
+ exits(nil);
+ break;
+ default:
+ if (c >= 0 && midend_process_key(fe->me, 0, 0, c) == PKR_QUIT) {
+ exits(nil);
+ }
+ }
+}
+
+void
+printoptions(config_item *c)
+{
+ char *t;
+ char *s = nil, *cnames[16], *ckws[16];
+ int n = 0, m;
+ config_item *cfg = midend_get_config(fe->me, CFG_PREFS, &t);
+
+ print("Options:\n");
+ while (cfg->type != C_END) {
+ switch (cfg->type) {
+ case C_STRING:
+ s = cfg->u.string.sval;
+ break;
+ case C_BOOLEAN:
+ s = cfg->u.boolean.bval ? "1" : "0";
+ break;
+ case C_CHOICES:
+ print(" Choices:\n");
+ n = getfields(cfg->u.choices.choicenames, cnames, 16, 1, ":");
+ m = getfields(cfg->u.choices.choicekws, ckws, 16, 1, ":");
+ assert(n == m && cfg->u.choices.selected < n);
+ s = ckws[cfg->u.choices.selected];
+ break;
+ }
+ print("--%s=%s\n %s\n", cfg->kw, s, cfg->name);
+ if (cfg->type == C_CHOICES) {
+ print(" Choices:\n");
+ for (int i = 0; i < n; i++) {
+ print(" %s: %s\n", ckws[i], cnames[i]);
+ }
+ }
+ cfg++;
+ }
+}
+
+void
+parseoption(config_item *cfg, char *keyval)
+{
+ char *arg[2];
+ int n;
+
+ n = getfields(keyval, arg, 2, 1, "=");
+ if (n != 2)
+ usage(); // exits
+
+ while (cfg && cfg->type != C_END)
+ if (strcmp(cfg->kw, arg[0]) != 0)
+ cfg++;
+
+ if (!cfg || cfg->type == C_END) {
+ fprint(2, "no valid option\n");
+ return;
+ }
+
+ print("%s : %s\n", cfg->kw, cfg->name);
+ return;
+
+ switch (cfg->type) {
+ case C_STRING:
+ cfg->u.string.sval = arg[1];
+ print("is string");
+ break;
+ case C_BOOLEAN:
+ n = atoi(arg[1]);
+ print("is boolean");
+ cfg->u.boolean.bval = n ? 1 : 0;
+ break;
+ case C_CHOICES:
+ // TODO
+ print("is choices");
+ fprint(2, "not implemented yet!\n");
+ break;
+ case C_END:
+ default:
+ print("not found");
+ break;
+ }
+}
+
+void
+hittopbar(int x, int buttons)
+{
+ if (buttons&1) {
+ print("left mouse\n");
+ } else
+ if (buttons&2) {
+ print("middle mouse\n");
+ } else
+ if (buttons&4) {
+ print("right mouse\n");
+ } else /* no button at all */
+ return;
+ print("pos: %d\n", x);
+}
+
+void
+main(int argc, char **argv)
+{
+ Event ev;
+ int e;
+ int x, y;
+ char *s;
+ int doprintoptions = 0;
+ char *wintitle;
+ config_item *cfg;
+ int changedprefs = 0;
+
+ fe = new_window();
+
+ wintitle = nil;
+ cfg = midend_get_config(fe->me, CFG_SETTINGS, &wintitle);
+
+ ARGBEGIN{
+ case 'h':
+ usage();
+ break;
+ case 'o':
+ doprintoptions++;
+ break;
+ case '-':
+ parseoption(cfg, ARGF());
+ changedprefs++;
+ break;
+ }ARGEND;
+
+ if (changedprefs) {
+ s = midend_set_config(fe->me, CFG_SETTINGS, cfg);
+ if (s) {
+ fprint(2, "error: %s\n", s);
+ exits("error");
+ }
+ }
+
+ if (doprintoptions) {
+ printoptions(cfg);
+ exits(nil);
+ }
+
+ if (initdraw(nil, nil, wintitle) < 0) {
+ sysfatal("initdraw failed: %r");
+ }
+
+ initfe(fe);
+ midend_new_game(fe->me);
+ einit(Emouse|Ekeyboard);
+ eresized(0);
+
+ for (;;) {
+ switch (event(&ev)) {
+ case Emouse:
+ x = ev.mouse.xy.x - fe->ZP.x;
+ y = ev.mouse.xy.y - fe->ZP.y;
+ if (y < fe->topbarh) {
+ hittopbar(x, ev.mouse.buttons);
+ }
+ if (ev.mouse.buttons&1) {
+ midend_process_key(fe->me, x, y, LEFT_BUTTON);
+ } else
+ if (ev.mouse.buttons&2) {
+ midend_process_key(fe->me, x, y, MIDDLE_BUTTON);
+ } else
+ if (ev.mouse.buttons&4) {
+ midend_process_key(fe->me, x, y, RIGHT_BUTTON);
+ }
+ case Ekeyboard:
+ keyboardev(ev.kbdc, &ev);
+ }
+ }
+}
--- a/puzzles.h
+++ b/puzzles.h
@@ -5,6 +5,12 @@
#ifndef PUZZLES_PUZZLES_H
#define PUZZLES_PUZZLES_H
+/* this is needed for type signatures, probably due to a bug
+ * related to the const specifier */
+#ifdef __plan9__
+#define const
+#endif
+
#include <stdio.h> /* for FILE */
#include <stdlib.h> /* for size_t */
#include <limits.h> /* for UINT_MAX */
@@ -820,5 +826,22 @@
/* A little bit of help to lazy developers */
#define DEFAULT_STATUSBAR_TEXT "Use status_bar() to fill this in."
+
+#ifdef __plan9__
+#pragma incomplete midend
+#pragma incomplete drawing
+#pragma incomplete DSF
+#pragma incomplete tdq
+#pragma incomplete blitter
+#pragma incomplete frontend
+#pragma incomplete random_state
+#pragma incomplete document
+#pragma incomplete game
+#pragma incomplete game_params
+#pragma incomplete game_ui
+#pragma incomplete game_state
+#pragma incomplete game_drawstate
+#pragma incomplete struct findloopstate
+#endif
#endif /* PUZZLES_PUZZLES_H */
--- a/tree234.h
+++ b/tree234.h
@@ -39,6 +39,10 @@
*/
typedef struct tree234_Tag tree234;
+#ifdef __plan9__
+#pragma incomplete tree234
+#endif
+
typedef int (*cmpfn234)(void *, void *);
typedef void *(*copyfn234)(void *state, void *element);