shithub: cstory

Download patch

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);
 }