ref: 71da5810d8ddba2808f34d24452e1bb794904298
parent: 3dec17c5b514ccb560db9e17756a52ec4570879d
author: Jacob Moody <moody@posixcafe.org>
date: Sat Dec 9 19:54:33 EST 2023
implement 9front platform & backend
--- a/mkfile
+++ b/mkfile
@@ -1,6 +1,6 @@
</$objtype/mkfile
-CFLAGS=-Fpw -I/sys/include/npe -I/sys/include/npe/SDL2 -D__plan9__ -D__${objtype}__
+CFLAGS=-Fpw -I/sys/include/npe -I/sys/include/npe/SDL2 -D__plan9__ -D__${objtype}__ -DFIX_BUGS
BIN=/$objtype/bin/games
TARG=cstory
@@ -173,3 +173,7 @@
$O.bin2h assets/resources/$stem $target
src/Resource.$O: $ASSETS
+
+install:V: $BIN/$TARG
+ mkdir -p /sys/games/lib/cstory
+ dircp game_english /sys/games/lib/cstory/
--- a/src/Backends/Platform/9front.cpp
+++ b/src/Backends/Platform/9front.cpp
@@ -5,17 +5,187 @@
#include "../../Attributes.h"
+#include <thread.h>
+#include <draw.h>
+#include <memdraw.h>
+#include <keyboard.h>
+#include <mouse.h>
+
+static int keyboard_state[BACKEND_KEYBOARD_TOTAL];
+static Mousectl *mctl;
+Channel *drawreq; /* Chan(Memimage*) */
+
+int Mark_Rune(int *kbd, Rune r)
+{
+ if(r >= 'a' && r <= 'z'){
+ r -= 'a';
+ return kbd[BACKEND_KEYBOARD_A + r] = 1;
+ }
+ if(r >= '0' && r <= '9'){
+ r -= '0';
+ return kbd[BACKEND_KEYBOARD_0 + r] = 1;
+ }
+
+ switch(r){
+ case KF|1:
+ case KF|2:
+ case KF|3:
+ case KF|4:
+ case KF|5:
+ case KF|6:
+ case KF|7:
+ case KF|8:
+ case KF|9:
+ case KF|10:
+ case KF|11:
+ case KF|12:
+ r -= (KF|1);
+ return kbd[BACKEND_KEYBOARD_F1 + r] = 1;
+
+ case Kleft:
+ return kbd[BACKEND_KEYBOARD_LEFT] = 1;
+ case Kright:
+ return kbd[BACKEND_KEYBOARD_RIGHT] = 1;
+ case Kup:
+ return kbd[BACKEND_KEYBOARD_UP] = 1;
+ case Kdown:
+ return kbd[BACKEND_KEYBOARD_DOWN] = 1;
+ case Kesc:
+ return kbd[BACKEND_KEYBOARD_ESCAPE] = 1;
+ case '`':
+ return kbd[BACKEND_KEYBOARD_BACK_QUOTE] = 1;
+ case '\t':
+ return kbd[BACKEND_KEYBOARD_TAB] = 1;
+ case Kshift:
+ return kbd[BACKEND_KEYBOARD_LEFT_SHIFT] = 1;
+ case Kctl:
+ return kbd[BACKEND_KEYBOARD_LEFT_CTRL] = 1;
+ case ' ':
+ return kbd[BACKEND_KEYBOARD_SPACE] = 1;
+ case '\n':
+ return kbd[BACKEND_KEYBOARD_ENTER] = 1;
+ case Kbs:
+ return kbd[BACKEND_KEYBOARD_BACKSPACE] = 1;
+ case '-':
+ return kbd[BACKEND_KEYBOARD_MINUS] = 1;
+ case '=':
+ return kbd[BACKEND_KEYBOARD_EQUALS] = 1;
+ case '[':
+ return kbd[BACKEND_KEYBOARD_LEFT_BRACKET] = 1;
+ case ']':
+ return kbd[BACKEND_KEYBOARD_RIGHT_BRACKET] = 1;
+ case '\\':
+ return kbd[BACKEND_KEYBOARD_BACK_SLASH] = 1;
+ case ';':
+ return kbd[BACKEND_KEYBOARD_SEMICOLON] = 1;
+ case '\'':
+ return kbd[BACKEND_KEYBOARD_APOSTROPHE] = 1;
+ case ',':
+ return kbd[BACKEND_KEYBOARD_COMMA] = 1;
+ case '.':
+ return kbd[BACKEND_KEYBOARD_PERIOD] = 1;
+ case '/':
+ return kbd[BACKEND_KEYBOARD_FORWARD_SLASH] = 1;
+ }
+ return 0;
+
+ /* Sorry!
+ BACKEND_KEYBOARD_CAPS_LOCK,
+ BACKEND_KEYBOARD_LEFT_ALT,
+ BACKEND_KEYBOARD_RIGHT_ALT,
+ BACKEND_KEYBOARD_RIGHT_CTRL,
+ BACKEND_KEYBOARD_RIGHT_SHIFT,
+ */
+}
+
+void Key_Proc(void*)
+{
+ char buf[128], *s;
+ int kbfd, n;
+ Rune r;
+
+ kbfd = open("/dev/kbd", OREAD);
+ if(kbfd < 0)
+ sysfatal("open: %r");
+ for(;;){
+ n = read(kbfd, buf, sizeof buf-1);
+ if(n <= 0)
+ return;
+ buf[n-1] = 0;
+ for(s = buf; s < buf+n; s++){
+ if(*s != 'k' && *s != 'K'){
+ for(; *s != '\0'; s++)
+ ;
+ continue;
+ }
+
+ memset(keyboard_state, 0, sizeof keyboard_state);
+ for(s++; *s && s < buf+n;){
+ s += chartorune(&r, s);
+ Mark_Rune(keyboard_state, r);
+ }
+ }
+ }
+}
+
+void Backend_Proc(void*)
+{
+ enum { Aresize, Amouse, Adraw, Aend };
+ Mouse m;
+ Memimage *b;
+ Memimage *memscreen = nil;
+
+ Alt a[] = {
+ [Amouse] { nil, &m, CHANRCV },
+ [Aresize] { nil, nil, CHANRCV },
+ [Adraw] { drawreq, &b, CHANRCV },
+ [Aend] { nil, nil, CHANEND },
+ };
+ a[Amouse].c = mctl->c;
+ a[Aresize].c = mctl->resizec;
+
+ goto Resize;
+ for(;;){
+ switch(alt(a)){
+ case Aresize:
+ getwindow(display, Refnone);
+ Resize:
+ free(memscreen);
+ memscreen = allocmemimage(screen->r, screen->chan);
+ if(memscreen == nil)
+ sysfatal("allocmemimage: %r");
+ break;
+ case Adraw:
+ memimagedraw(memscreen, memscreen->r, b, ZP, nil, ZP, S);
+ loadimage(screen, screen->r, memscreen->data->bdata, Dx(screen->r)*Dy(screen->r)*(screen->depth/8));
+ flushimage(display, 1);
+ break;
+ }
+ }
+}
+
int Backend_Init(void (*drag_and_drop_callback)(const char *path), void (*window_focus_callback)(int focus))
{
(void)drag_and_drop_callback;
(void)window_focus_callback;
+ int pid;
+ memimageinit();
+ if(initdraw(nil, nil, "cstory") < 0)
+ sysfatal("initdraw: %r");
+ drawreq = chancreate(sizeof(Channel*), 1);
+ mctl = initmouse(nil, screen);
+ if(mctl == nil)
+ sysfatal("initmouse: %r");
+
+ proccreate(Key_Proc, nil, 8192);
+ proccreate(Backend_Proc, nil, 8192);
+
return 1;
}
void Backend_Deinit(void)
{
-
}
void Backend_PostWindowCreation(void)
@@ -25,10 +195,10 @@
int Backend_GetPaths(char **module_path, char **data_path)
{
- (void)module_path;
- (void)data_path;
+ *module_path = "/sys/games/lib/cstory";
+ *data_path = "/sys/games/lib/cstory/data";
- return 0;
+ return 1;
}
void Backend_HideMouse(void)
@@ -51,48 +221,53 @@
}
void Backend_EnableDragAndDrop(void)
-{
-
+{
}
+
int Backend_SystemTask(int active)
{
- (void)active;
-
return 1;
}
-void Backend_GetKeyboardState(int *keyboard_state)
+void Backend_GetKeyboardState(int *out)
{
- (void)keyboard_state;
+ memcpy(out, keyboard_state, sizeof keyboard_state);
}
void Backend_ShowMessageBox(const char *title, const char *message)
{
- (void)title;
- (void)message;
+ Backend_PrintInfo("ShowMessageBox - '%s' - '%s'\n", title, message);
}
ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintError(const char *format, ...)
{
- (void)format;
+ va_list argumentList;
+ va_start(argumentList, format);
+ fputs("ERROR: ", stderr);
+ vfprintf(stderr, format, argumentList);
+ fputc('\n', stderr);
+ va_end(argumentList);
}
ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintInfo(const char *format, ...)
{
- (void)format;
+ va_list argumentList;
+ va_start(argumentList, format);
+ fputs("INFO: ", stdout);
+ vfprintf(stdout, format, argumentList);
+ fputc('\n', stdout);
+ va_end(argumentList);
}
+#define Nmsec 1000000ULL
+
unsigned long Backend_GetTicks(void)
{
- static unsigned long fake_ticks = 0;
-
- fake_ticks += 1000 / 50;
-
- return fake_ticks;
+ return npe_nanosec() / Nmsec;
}
void Backend_Delay(unsigned int ticks)
{
- (void)ticks;
+ npe_nsleep((uvlong)ticks * Nmsec);
}
--- a/src/Backends/Rendering/Window/Software/9front.cpp
+++ b/src/Backends/Rendering/Window/Software/9front.cpp
@@ -5,9 +5,13 @@
#include <stddef.h>
#include <stdlib.h>
+#include <thread.h>
+#include <draw.h>
+#include <memdraw.h>
-static unsigned char *framebuffer;
-static size_t framebuffer_pitch;
+static Memimage *buffer[2];
+static int curbuffer = 0;
+extern Channel *drawreq;
int WindowBackend_Software_CreateWindow(const char *window_title, size_t screen_width, size_t screen_height, int fullscreen)
{
@@ -14,37 +18,41 @@
(void)window_title;
(void)fullscreen;
- framebuffer = (unsigned char*)malloc(screen_width * screen_height * 3);
-
- if (framebuffer != NULL)
- {
- framebuffer_pitch = screen_width * 3;
-
- return 1;
- }
-
- return 0;
+ buffer[0] = allocmemimage(Rect(0, 0, screen_width, screen_height), BGR24);
+ buffer[1] = allocmemimage(Rect(0, 0, screen_width, screen_height), BGR24);
+ if(buffer[0] == nil || buffer[1] == nil)
+ sysfatal("allocmemimage: %r");
+ return 1;
}
void WindowBackend_Software_DestroyWindow(void)
{
- free(framebuffer);
}
unsigned char* WindowBackend_Software_GetFramebuffer(size_t *pitch)
{
- *pitch = framebuffer_pitch;
+ Memimage *b;
+ b = buffer[curbuffer];
+ curbuffer = !curbuffer;
+ *pitch = Dx(b->r)*(b->depth/8);
- return framebuffer;
+ return b->data->bdata;
}
void WindowBackend_Software_Display(void)
{
-
+ /*
+ * If we're not ready for another frame
+ * drop it. Prevents performance problems
+ * resulting in slowdown of game logic.
+ */
+ nbsend(drawreq, &buffer[curbuffer]);
}
-void WindowBackend_Software_HandleWindowResize(size_t width, size_t height)
+void WindowBackend_Software_HandleWindowResize(size_t w, size_t h)
{
- (void)width;
- (void)height;
+ freememimage(buffer[0]);
+ freememimage(buffer[1]);
+ buffer[0] = allocmemimage(Rect(0, 0, w, h), BGR24);
+ buffer[1] = allocmemimage(Rect(0, 0, w, h), BGR24);
}