Replace macOS journal implementation with the reimplementation
|
|
@ -53,53 +53,7 @@ unix:!macx {
|
|||
|
||||
# OS X
|
||||
macx {
|
||||
# Directly copied from Linux, assuming this works but unsure
|
||||
|
||||
SOURCES += \
|
||||
mac/main.c \
|
||||
mac/niko.c \
|
||||
mac/journal.c \
|
||||
mac/image/niko1.c \
|
||||
mac/image/niko2.c \
|
||||
mac/image/niko3.c \
|
||||
mac/image/default.c \
|
||||
mac/image/c1.c \
|
||||
mac/image/c2.c \
|
||||
mac/image/c3.c \
|
||||
mac/image/c4.c \
|
||||
mac/image/c5.c \
|
||||
mac/image/c6.c \
|
||||
mac/image/c7.c \
|
||||
mac/image/s1.c \
|
||||
mac/image/s2.c \
|
||||
mac/image/s3.c \
|
||||
mac/image/s4.c \
|
||||
mac/image/t1.c \
|
||||
mac/image/t2.c \
|
||||
mac/image/t3.c \
|
||||
mac/image/t4.c \
|
||||
mac/image/t5.c \
|
||||
mac/image/t6.c \
|
||||
mac/image/t7.c \
|
||||
mac/image/t8.c \
|
||||
mac/image/t9.c \
|
||||
mac/image/t10.c \
|
||||
mac/image/t11.c \
|
||||
mac/image/t12.c \
|
||||
mac/image/t13.c \
|
||||
mac/image/t14.c \
|
||||
mac/image/t15.c \
|
||||
mac/image/t16.c \
|
||||
mac/image/final.c \
|
||||
mac/image/save.c
|
||||
|
||||
HEADERS += \
|
||||
mac/display.h \
|
||||
mac/image.h
|
||||
|
||||
QMAKE_CFLAGS += -pthread
|
||||
|
||||
LIBS += -pthread -lxcb -lxcb-util -lxcb-image -lxcb-shape -lxcb-icccm -lxcb-ewmh
|
||||
}
|
||||
|
||||
# Windows
|
||||
|
|
|
|||
40
journal/mac/README.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
OneShot Journal
|
||||
===============
|
||||
|
||||
This is a Linux- and macOS-compatible reimplementation of the Author's Journal, a element in the game [OneShot](http://oneshot-game.com).
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
This journal requires Python 3.x and PyQt5 to run. On macOS or Debian/Ubuntu-based systems, install via one of the following commands:
|
||||
|
||||
brew install pyqt5 # macOS (Homebrew)
|
||||
port install pyqt5 # macOS (MacPorts)
|
||||
sudo apt-get install python3-pyqt5 # Ubuntu/Debian
|
||||
|
||||
This will install PyQt5 and all necessary files. Next, extract the images from the original OneShot journal program using the instructions in the following section, then use the following command to start the journal:
|
||||
|
||||
python3 journal.py
|
||||
|
||||
Start OneShot and play normally.
|
||||
|
||||
Building the app bundle
|
||||
-----------------------
|
||||
|
||||
To create the macOS app bundle, PyInstaller is required. Install via one of the following commands:
|
||||
|
||||
brew install pyinstaller # macOS (Homebrew)
|
||||
port install pyinstaller # macOS (MacPorts)
|
||||
|
||||
*Note: If you plan to use Python 3.6, at the time of this writing, the stable release (3.2.1) of PyInstaller only supports up to Python 3.5, however the [development build](http://www.pyinstaller.org/downloads.html) implements Python 3.6 support.*
|
||||
|
||||
Now that everything is installed, let's create our app bundle:
|
||||
|
||||
pyinstaller journal.spec --onefile --windowed
|
||||
|
||||
This should collect all the required runtime files and create the bundle in `dist/_______.app`.
|
||||
|
||||
Extracting the images
|
||||
---------------------
|
||||
|
||||
First, aquire a copy of the Windows-version journal executable. Next, download [ResourcesExtract](http://www.nirsoft.net/utils/resources_extract.html) and run it, either via Wine or from a Windows install. Set the filename to the journal executable and the destination to the images directory in your local copy of this repo. Set the program to extract only bitmaps, then press Start. Once extraction completes run the included Python script `renameandconvert.py` (requires ImageMagick), which will create the required PNGs.
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
#ifndef DISPLAY_H
|
||||
#define DISPLAY_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xcb_ewmh.h>
|
||||
|
||||
struct Display {
|
||||
xcb_connection_t *c;
|
||||
xcb_screen_t *screen;
|
||||
};
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#define STRING(x) sizeof(x) - 1, (x)
|
||||
#define ARRAY(x) sizeof(x), (x)
|
||||
|
||||
#endif // DISPLAY_H
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
#ifndef EMBED_H
|
||||
#define EMBED_H
|
||||
|
||||
#include <xcb/xcb_image.h>
|
||||
#include <xcb/shape.h>
|
||||
#include <X11/extensions/shape.h>
|
||||
|
||||
static inline xcb_pixmap_t create_mask(xcb_connection_t *c,
|
||||
xcb_window_t win,
|
||||
unsigned char *bits,
|
||||
uint32_t width,
|
||||
uint32_t height)
|
||||
{
|
||||
return xcb_create_pixmap_from_bitmap_data(c, win, bits, width, height, 1, 0, 0, NULL);
|
||||
}
|
||||
|
||||
static inline xcb_pixmap_t create_image(xcb_connection_t *c,
|
||||
xcb_window_t win,
|
||||
unsigned char *bytes,
|
||||
uint32_t width,
|
||||
uint32_t height)
|
||||
{
|
||||
xcb_image_t *image = xcb_image_create_native(
|
||||
c, width, height, XCB_IMAGE_FORMAT_Z_PIXMAP, 24, NULL, width * height * 4, bytes);
|
||||
xcb_pixmap_t pixmap = xcb_generate_id(c);
|
||||
xcb_create_pixmap(c, 24, pixmap, win, width, height);
|
||||
xcb_gcontext_t gc = xcb_generate_id(c);
|
||||
xcb_create_gc(c, gc, pixmap, 0, NULL);
|
||||
xcb_image_put(c, pixmap, gc, image, 0, 0, 0);
|
||||
xcb_image_destroy(image);
|
||||
xcb_free_gc(c, gc);
|
||||
return pixmap;
|
||||
|
||||
}
|
||||
|
||||
static inline void set_shape(xcb_connection_t *c, xcb_window_t win, xcb_pixmap_t mask)
|
||||
{
|
||||
xcb_shape_mask(c, ShapeSet, ShapeBounding, win, 0, 0, mask);
|
||||
}
|
||||
|
||||
#define NIKO_WIDTH 48
|
||||
#define NIKO_HEIGHT 64
|
||||
extern unsigned char niko1_mask[];
|
||||
extern unsigned char niko1_rgb[];
|
||||
extern unsigned char niko2_mask[];
|
||||
extern unsigned char niko2_rgb[];
|
||||
extern unsigned char niko3_mask[];
|
||||
extern unsigned char niko3_rgb[];
|
||||
|
||||
#define JOURNAL_WIDTH 800
|
||||
#define JOURNAL_HEIGHT 600
|
||||
extern unsigned char default_mask[];
|
||||
extern unsigned char default_rgb[];
|
||||
extern unsigned char c1_mask[];
|
||||
extern unsigned char c1_rgb[];
|
||||
extern unsigned char c2_mask[];
|
||||
extern unsigned char c2_rgb[];
|
||||
extern unsigned char c3_mask[];
|
||||
extern unsigned char c3_rgb[];
|
||||
extern unsigned char c4_mask[];
|
||||
extern unsigned char c4_rgb[];
|
||||
extern unsigned char c5_mask[];
|
||||
extern unsigned char c5_rgb[];
|
||||
extern unsigned char c6_mask[];
|
||||
extern unsigned char c6_rgb[];
|
||||
extern unsigned char c7_mask[];
|
||||
extern unsigned char c7_rgb[];
|
||||
extern unsigned char s1_mask[];
|
||||
extern unsigned char s1_rgb[];
|
||||
extern unsigned char s2_mask[];
|
||||
extern unsigned char s2_rgb[];
|
||||
extern unsigned char s3_mask[];
|
||||
extern unsigned char s3_rgb[];
|
||||
extern unsigned char s4_mask[];
|
||||
extern unsigned char s4_rgb[];
|
||||
extern unsigned char t1_mask[];
|
||||
extern unsigned char t1_rgb[];
|
||||
extern unsigned char t2_mask[];
|
||||
extern unsigned char t2_rgb[];
|
||||
extern unsigned char t3_mask[];
|
||||
extern unsigned char t3_rgb[];
|
||||
extern unsigned char t4_mask[];
|
||||
extern unsigned char t4_rgb[];
|
||||
extern unsigned char t5_mask[];
|
||||
extern unsigned char t5_rgb[];
|
||||
extern unsigned char t6_mask[];
|
||||
extern unsigned char t6_rgb[];
|
||||
extern unsigned char t7_mask[];
|
||||
extern unsigned char t7_rgb[];
|
||||
extern unsigned char t8_mask[];
|
||||
extern unsigned char t8_rgb[];
|
||||
extern unsigned char t9_mask[];
|
||||
extern unsigned char t9_rgb[];
|
||||
extern unsigned char t10_mask[];
|
||||
extern unsigned char t10_rgb[];
|
||||
extern unsigned char t11_mask[];
|
||||
extern unsigned char t11_rgb[];
|
||||
extern unsigned char t12_mask[];
|
||||
extern unsigned char t12_rgb[];
|
||||
extern unsigned char t13_mask[];
|
||||
extern unsigned char t13_rgb[];
|
||||
extern unsigned char t14_mask[];
|
||||
extern unsigned char t14_rgb[];
|
||||
extern unsigned char t15_mask[];
|
||||
extern unsigned char t15_rgb[];
|
||||
extern unsigned char t16_mask[];
|
||||
extern unsigned char t16_rgb[];
|
||||
extern unsigned char final_mask[];
|
||||
extern unsigned char final_rgb[];
|
||||
extern unsigned char save_mask[];
|
||||
extern unsigned char save_rgb[];
|
||||
|
||||
#endif // EMBED_H
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/bash
|
||||
if [ $# -lt 1 ]; then
|
||||
echo "usage: pixmapper.sh <image>"
|
||||
exit 1
|
||||
fi
|
||||
basename="$(basename "$1" | tr '[:upper:]' '[:lower:]')"
|
||||
name="${basename%.*}"
|
||||
cfile="$name.c"
|
||||
convert "$1" -alpha on -transparent '#00ff00' -alpha extract -negate xbm:- | sed "/^#define/d;s/-_bits/${name}_mask/g;s/^static char/unsigned char/" > "$cfile"
|
||||
echo "unsigned char ${name}_rgb[] = {" >> "$cfile"
|
||||
convert "$1" -alpha on -transparent '#00ff00' -depth 8 bgra:- | xxd -i >> "$cfile"
|
||||
echo "};" >> "$cfile"
|
||||
|
Before Width: | Height: | Size: 183 KiB After Width: | Height: | Size: 183 KiB |
|
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 234 KiB |
|
Before Width: | Height: | Size: 288 KiB After Width: | Height: | Size: 288 KiB |
|
Before Width: | Height: | Size: 218 KiB After Width: | Height: | Size: 218 KiB |
|
Before Width: | Height: | Size: 267 KiB After Width: | Height: | Size: 267 KiB |
|
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 216 KiB |
|
Before Width: | Height: | Size: 289 KiB After Width: | Height: | Size: 289 KiB |
|
Before Width: | Height: | Size: 430 B After Width: | Height: | Size: 430 B |
|
Before Width: | Height: | Size: 269 KiB After Width: | Height: | Size: 269 KiB |
|
Before Width: | Height: | Size: 519 B After Width: | Height: | Size: 519 B |
|
Before Width: | Height: | Size: 510 B After Width: | Height: | Size: 510 B |
|
Before Width: | Height: | Size: 520 B After Width: | Height: | Size: 520 B |
|
Before Width: | Height: | Size: 265 KiB After Width: | Height: | Size: 265 KiB |
|
Before Width: | Height: | Size: 250 KiB After Width: | Height: | Size: 250 KiB |
|
Before Width: | Height: | Size: 227 KiB After Width: | Height: | Size: 227 KiB |
|
Before Width: | Height: | Size: 360 KiB After Width: | Height: | Size: 360 KiB |
|
Before Width: | Height: | Size: 548 KiB After Width: | Height: | Size: 548 KiB |
|
Before Width: | Height: | Size: 250 KiB After Width: | Height: | Size: 250 KiB |
|
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 248 KiB |
|
Before Width: | Height: | Size: 246 KiB After Width: | Height: | Size: 246 KiB |
|
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 206 KiB After Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 224 KiB |
|
Before Width: | Height: | Size: 258 KiB After Width: | Height: | Size: 258 KiB |
|
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 224 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 326 KiB After Width: | Height: | Size: 326 KiB |
|
Before Width: | Height: | Size: 174 KiB After Width: | Height: | Size: 174 KiB |
|
Before Width: | Height: | Size: 252 KiB After Width: | Height: | Size: 252 KiB |
|
Before Width: | Height: | Size: 207 KiB After Width: | Height: | Size: 207 KiB |
|
|
@ -1,235 +0,0 @@
|
|||
#include <xcb/xcb_ewmh.h>
|
||||
#include <xcb/xcb_icccm.h>
|
||||
#include <pthread.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "display.h"
|
||||
#include "image.h"
|
||||
|
||||
#define PIPE_DIR "/tmp"
|
||||
#define PIPE_NAME "oneshot-pipe"
|
||||
#define PIPE_PATH PIPE_DIR "/" PIPE_NAME
|
||||
#define MESSAGE_BUF_SIZE 256
|
||||
|
||||
#define PAGES \
|
||||
PAGE(default) \
|
||||
PAGE(c1) \
|
||||
PAGE(c2) \
|
||||
PAGE(c3) \
|
||||
PAGE(c4) \
|
||||
PAGE(c5) \
|
||||
PAGE(c6) \
|
||||
PAGE(c7) \
|
||||
PAGE(s1) \
|
||||
PAGE(s2) \
|
||||
PAGE(s3) \
|
||||
PAGE(s4) \
|
||||
PAGE(t1) \
|
||||
PAGE(t2) \
|
||||
PAGE(t3) \
|
||||
PAGE(t4) \
|
||||
PAGE(t5) \
|
||||
PAGE(t6) \
|
||||
PAGE(t7) \
|
||||
PAGE(t8) \
|
||||
PAGE(t9) \
|
||||
PAGE(t10) \
|
||||
PAGE(t11) \
|
||||
PAGE(t12) \
|
||||
PAGE(t13) \
|
||||
PAGE(t14) \
|
||||
PAGE(t15) \
|
||||
PAGE(t16) \
|
||||
PAGE(final) \
|
||||
PAGE(save)
|
||||
|
||||
struct ThreadData {
|
||||
struct Display *dpy;
|
||||
xcb_window_t window;
|
||||
xcb_gcontext_t gc;
|
||||
xcb_pixmap_t *masks;
|
||||
xcb_pixmap_t *images;
|
||||
volatile int page;
|
||||
};
|
||||
|
||||
void set_page(struct ThreadData *threaddata, const char *name)
|
||||
{
|
||||
int page = 0;
|
||||
#define PAGE(x) if (strncmp(name, #x, MESSAGE_BUF_SIZE) == 0) { goto end; } else { ++page; }
|
||||
PAGES
|
||||
#undef PAGE
|
||||
|
||||
end:
|
||||
threaddata->page = page;
|
||||
xcb_shape_mask(threaddata->dpy->c, ShapeSet, ShapeBounding,
|
||||
threaddata->window, 0, 0, threaddata->masks[page]);
|
||||
xcb_copy_area(threaddata->dpy->c,
|
||||
threaddata->images[page],
|
||||
threaddata->window,
|
||||
threaddata->gc,
|
||||
0, 0, 0, 0, JOURNAL_WIDTH, JOURNAL_HEIGHT);
|
||||
xcb_flush(threaddata->dpy->c);
|
||||
}
|
||||
|
||||
static void *ipc_thread(void *data)
|
||||
{
|
||||
struct ThreadData *threaddata = (struct ThreadData*)data;
|
||||
|
||||
for (;;) {
|
||||
// Try to open pipe
|
||||
int pipe = open(PIPE_PATH, O_RDONLY);
|
||||
if (pipe == -1) {
|
||||
// Use the default image for now
|
||||
set_page(threaddata, "default");
|
||||
// Wait until the pipe appears to try again
|
||||
int inotify = inotify_init();
|
||||
inotify_add_watch(inotify, PIPE_DIR, IN_CREATE);
|
||||
char inotify_buf[sizeof(struct inotify_event) + NAME_MAX + 1];
|
||||
for (;;) {
|
||||
ssize_t result = read(inotify, inotify_buf, sizeof(inotify_buf));
|
||||
if (result > 0) {
|
||||
struct inotify_event *e = (struct inotify_event*)inotify_buf;
|
||||
if (strcmp(e->name, PIPE_NAME) == 0)
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(inotify);
|
||||
} else {
|
||||
// Message loop
|
||||
char message[MESSAGE_BUF_SIZE];
|
||||
for (;;) {
|
||||
ssize_t len = read(pipe, message, sizeof(message));
|
||||
if (len > 0) {
|
||||
set_page(threaddata, message);
|
||||
} else if (len == 0) {
|
||||
exit(0); // empty string
|
||||
} else {
|
||||
// End of the line
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(pipe);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int do_journal(struct Display *dpy)
|
||||
{
|
||||
// Connect EWMH
|
||||
xcb_ewmh_connection_t ewmh;
|
||||
xcb_ewmh_init_atoms_replies(&ewmh, xcb_ewmh_init_atoms(dpy->c, &ewmh), NULL);
|
||||
|
||||
// Request some atoms
|
||||
xcb_intern_atom_cookie_t WM_DELETE_WINDOW_cookie = xcb_intern_atom(dpy->c, false, STRING("WM_DELETE_WINDOW"));
|
||||
xcb_intern_atom_cookie_t _NET_WM_PING_cookie = xcb_intern_atom(dpy->c, false, STRING("_NET_WM_PING"));
|
||||
xcb_intern_atom_cookie_t WM_PROTOCOLS_cookie = xcb_intern_atom(dpy->c, false, STRING("WM_PROTOCOLS"));
|
||||
xcb_atom_t WM_DELETE_WINDOW = xcb_intern_atom_reply(dpy->c, WM_DELETE_WINDOW_cookie, NULL)->atom;
|
||||
xcb_atom_t _NET_WM_PING = xcb_intern_atom_reply(dpy->c, _NET_WM_PING_cookie, NULL)->atom;
|
||||
xcb_atom_t WM_PROTOCOLS = xcb_intern_atom_reply(dpy->c, WM_PROTOCOLS_cookie, NULL)->atom;
|
||||
|
||||
// Create window
|
||||
uint32_t values[] = {
|
||||
XCB_EVENT_MASK_EXPOSURE, // event mask
|
||||
};
|
||||
xcb_window_t window = xcb_generate_id(dpy->c);
|
||||
xcb_create_window(dpy->c, XCB_COPY_FROM_PARENT, window, dpy->screen->root,
|
||||
0, 0, JOURNAL_WIDTH, JOURNAL_HEIGHT,
|
||||
0, XCB_WINDOW_CLASS_INPUT_OUTPUT, dpy->screen->root_visual,
|
||||
XCB_CW_EVENT_MASK, &values);
|
||||
|
||||
xcb_atom_t protocols[] = {
|
||||
WM_DELETE_WINDOW,
|
||||
_NET_WM_PING,
|
||||
};
|
||||
xcb_icccm_set_wm_protocols(dpy->c, window, WM_PROTOCOLS, ARRAY(protocols));
|
||||
|
||||
xcb_icccm_set_wm_name(dpy->c, window, XCB_ATOM_STRING, 8, STRING(""));
|
||||
xcb_icccm_set_wm_class(dpy->c, window, ARRAY("_______\0OneshotJournal"));
|
||||
xcb_ewmh_set_wm_window_type(&ewmh, window, 1, &ewmh._NET_WM_WINDOW_TYPE_NORMAL);
|
||||
|
||||
xcb_size_hints_t size_hints;
|
||||
xcb_icccm_size_hints_set_min_size(&size_hints, JOURNAL_WIDTH, JOURNAL_HEIGHT);
|
||||
xcb_icccm_size_hints_set_max_size(&size_hints, JOURNAL_WIDTH, JOURNAL_HEIGHT);
|
||||
xcb_icccm_set_wm_size_hints(dpy->c, window, XCB_ATOM_WM_NORMAL_HINTS, &size_hints);
|
||||
|
||||
// Create pixmaps
|
||||
xcb_pixmap_t masks[] = {
|
||||
#define PAGE(x) create_mask(dpy->c, window, x##_mask, JOURNAL_WIDTH, JOURNAL_HEIGHT),
|
||||
PAGES
|
||||
#undef PAGE
|
||||
};
|
||||
xcb_pixmap_t images[] = {
|
||||
#define PAGE(x) create_image(dpy->c, window, x##_rgb, JOURNAL_WIDTH, JOURNAL_HEIGHT),
|
||||
PAGES
|
||||
#undef PAGE
|
||||
};
|
||||
|
||||
// Create graphics context
|
||||
xcb_gcontext_t gc = xcb_generate_id(dpy->c);
|
||||
xcb_create_gc(dpy->c, gc, window, 0, NULL);
|
||||
|
||||
// Start IPC thread
|
||||
struct ThreadData threaddata = {
|
||||
dpy,
|
||||
window,
|
||||
gc,
|
||||
masks,
|
||||
images,
|
||||
0,
|
||||
};
|
||||
pthread_t thread;
|
||||
if (pthread_create(&thread, NULL, ipc_thread, &threaddata) != 0)
|
||||
return 1;
|
||||
|
||||
// Map!
|
||||
xcb_map_window(dpy->c, window);
|
||||
xcb_flush(dpy->c);
|
||||
|
||||
// Handle events
|
||||
xcb_generic_event_t *e;
|
||||
while ((e = xcb_wait_for_event(dpy->c))) {
|
||||
switch (e->response_type & ~0x80) {
|
||||
case XCB_EXPOSE: {
|
||||
xcb_expose_event_t *ee = (xcb_expose_event_t*)e;
|
||||
xcb_copy_area(dpy->c, images[threaddata.page],
|
||||
window, gc,
|
||||
ee->x, ee->y, ee->x, ee->y,
|
||||
ee->width, ee->height);
|
||||
xcb_flush(dpy->c);
|
||||
} break;
|
||||
case XCB_CLIENT_MESSAGE: {
|
||||
xcb_client_message_event_t *ce = (xcb_client_message_event_t*)e;
|
||||
if (ce->type == WM_PROTOCOLS && ce->format == 32) {
|
||||
xcb_atom_t atom = ce->data.data32[0];
|
||||
if (atom == WM_DELETE_WINDOW) {
|
||||
goto end;
|
||||
} else if (atom == _NET_WM_PING) {
|
||||
ce->window = dpy->screen->root;
|
||||
xcb_send_event(dpy->c, false, dpy->screen->root,
|
||||
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
|
||||
(const char*)e);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
free(e);
|
||||
}
|
||||
|
||||
end:
|
||||
xcb_free_gc(dpy->c, gc);
|
||||
for (size_t i = 0; i < ARRAY_SIZE(masks); ++i) {
|
||||
xcb_free_pixmap(dpy->c, masks[i]);
|
||||
xcb_free_pixmap(dpy->c, images[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
37
journal/mac/journal.spec
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# -*- mode: python -*-
|
||||
|
||||
block_cipher = None
|
||||
|
||||
a = Analysis(['journal.py'],
|
||||
pathex=['.'],
|
||||
binaries=[],
|
||||
datas=[('images', 'images')],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher)
|
||||
pyz = PYZ(a.pure, a.zipped_data,
|
||||
cipher=block_cipher)
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
exclude_binaries=True,
|
||||
name='_______',
|
||||
debug=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=False )
|
||||
coll = COLLECT(exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
name='_______')
|
||||
app = BUNDLE(coll,
|
||||
name='_______.app',
|
||||
icon='assets/icon_journal.icns',
|
||||
bundle_identifier="APPL"
|
||||
)
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
#include "display.h"
|
||||
|
||||
extern int do_niko(struct Display *dpy, int x, int y);
|
||||
extern int do_journal(struct Display *dpy);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// Connect
|
||||
struct Display dpy;
|
||||
dpy.c = xcb_connect(NULL, NULL);
|
||||
dpy.screen = xcb_setup_roots_iterator(xcb_get_setup(dpy.c)).data;
|
||||
|
||||
int result;
|
||||
if (argc == 3) {
|
||||
// argc == 3, assume niko
|
||||
int x = atoi(argv[1]);
|
||||
int y = atoi(argv[2]);
|
||||
result = do_niko(&dpy, x, y);
|
||||
} else {
|
||||
// argc == 3, assume journal
|
||||
result = do_journal(&dpy);
|
||||
}
|
||||
|
||||
xcb_disconnect(dpy.c);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
#include <sys/time.h>
|
||||
|
||||
#include "display.h"
|
||||
#include "image.h"
|
||||
|
||||
static uint64_t getticks()
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return (uint64_t)tv.tv_sec * 1000 + (uint64_t)tv.tv_usec / 1000;
|
||||
}
|
||||
|
||||
static void draw_niko(xcb_connection_t *c,
|
||||
xcb_window_t win,
|
||||
xcb_gcontext_t gc,
|
||||
xcb_pixmap_t masks[3],
|
||||
xcb_pixmap_t images[3],
|
||||
int x, int y, int w, int h,
|
||||
int offset)
|
||||
{
|
||||
int frame;
|
||||
if (offset % 32 >= 16) {
|
||||
frame = 1;
|
||||
} else {
|
||||
if ((offset / 32) % 2)
|
||||
frame = 0;
|
||||
else
|
||||
frame = 2;
|
||||
}
|
||||
xcb_shape_mask(c, ShapeSet, ShapeBounding, win, 0, 0, masks[frame]);
|
||||
xcb_copy_area(c, images[frame], win, gc, x, y, x, y, w, h);
|
||||
|
||||
}
|
||||
|
||||
int do_niko(struct Display *dpy, int x, int y)
|
||||
{
|
||||
// Create window
|
||||
uint32_t values[] = {
|
||||
true, // override_redirect
|
||||
XCB_EVENT_MASK_EXPOSURE, // event mask
|
||||
};
|
||||
xcb_window_t window = xcb_generate_id(dpy->c);
|
||||
xcb_create_window(dpy->c, XCB_COPY_FROM_PARENT, window, dpy->screen->root,
|
||||
x, y, NIKO_WIDTH, NIKO_HEIGHT,
|
||||
0, XCB_WINDOW_CLASS_INPUT_OUTPUT, dpy->screen->root_visual,
|
||||
XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, &values);
|
||||
|
||||
// Stick window on top
|
||||
xcb_stack_mode_t stack = XCB_STACK_MODE_ABOVE;
|
||||
xcb_configure_window(dpy->c, window, XCB_CONFIG_WINDOW_STACK_MODE, &stack);
|
||||
|
||||
// Create pixmaps
|
||||
xcb_pixmap_t niko_masks[] = {
|
||||
create_mask(dpy->c, window, niko1_mask, NIKO_WIDTH, NIKO_HEIGHT),
|
||||
create_mask(dpy->c, window, niko2_mask, NIKO_WIDTH, NIKO_HEIGHT),
|
||||
create_mask(dpy->c, window, niko3_mask, NIKO_WIDTH, NIKO_HEIGHT),
|
||||
};
|
||||
xcb_pixmap_t niko_images[] = {
|
||||
create_image(dpy->c, window, niko1_rgb, NIKO_WIDTH, NIKO_HEIGHT),
|
||||
create_image(dpy->c, window, niko2_rgb, NIKO_WIDTH, NIKO_HEIGHT),
|
||||
create_image(dpy->c, window, niko3_rgb, NIKO_WIDTH, NIKO_HEIGHT),
|
||||
};
|
||||
|
||||
// Create graphics context
|
||||
xcb_gcontext_t gc = xcb_generate_id(dpy->c);
|
||||
xcb_create_gc(dpy->c, gc, window, 0, NULL);
|
||||
|
||||
// Map!
|
||||
xcb_map_window(dpy->c, window);
|
||||
xcb_flush(dpy->c);
|
||||
|
||||
// Niko movement info
|
||||
int niko_offset = 0;
|
||||
|
||||
uint64_t ticks = getticks();
|
||||
for (;;) {
|
||||
// Handle events
|
||||
for (;;) {
|
||||
xcb_generic_event_t *e = xcb_poll_for_event(dpy->c);
|
||||
if (e) {
|
||||
switch (e->response_type) {
|
||||
case XCB_EXPOSE: {
|
||||
xcb_expose_event_t *ee = (xcb_expose_event_t*)e;
|
||||
draw_niko(dpy->c, window, gc, niko_masks, niko_images,
|
||||
ee->x, ee->y, ee->width, ee->height, niko_offset);
|
||||
xcb_flush(dpy->c);
|
||||
} break;
|
||||
}
|
||||
free(e);
|
||||
} else if (getticks() - ticks >= 1000 / 60) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Move niko
|
||||
niko_offset += 2;
|
||||
int new_y = y + niko_offset;
|
||||
if (new_y > dpy->screen->height_in_pixels)
|
||||
break;
|
||||
xcb_configure_window(dpy->c, window, XCB_CONFIG_WINDOW_Y, &new_y);
|
||||
draw_niko(dpy->c, window, gc, niko_masks, niko_images, 0, 0, NIKO_WIDTH, NIKO_HEIGHT, niko_offset);
|
||||
xcb_flush(dpy->c);
|
||||
ticks = getticks();
|
||||
}
|
||||
|
||||
// Free up stuff
|
||||
xcb_free_gc(dpy->c, gc);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
xcb_free_pixmap(dpy->c, niko_masks[i]);
|
||||
xcb_free_pixmap(dpy->c, niko_images[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
"""
|
||||
This is a setup.py script generated by py2applet
|
||||
|
||||
Usage:
|
||||
python3 setup-unix-remake.py py2app
|
||||
"""
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
APP = ['journal.py']
|
||||
APP_NAME = "_______"
|
||||
DATA_FILES = ["images"]
|
||||
OPTIONS = {
|
||||
'argv_emulation': True,
|
||||
# 'plist': {
|
||||
# 'CFBundleName': APP_NAME,
|
||||
# 'CFBundleDisplayName': APP_NAME,
|
||||
# 'CFBundleGetInfoString': "You only have one shot.",
|
||||
# 'CFBundleIdentifier': 'com.oneshot-game.hunternet93.journal-remake',
|
||||
# 'CFBundleVersion': '1.0',
|
||||
# 'CFBundleShortVersionString': '1.0',
|
||||
# 'LSApplicationCategoryType': 'public.app-category.games',
|
||||
# 'LSMinimumSystemVersion': '10.7',
|
||||
# 'NSHumanReadableCopyright': u"Copyright © 2017, hunternet93 and Vinyl Darkscratch, MIT License. https://github.com/hunternet93/OneShot-Journal"
|
||||
# }
|
||||
}
|
||||
|
||||
setup(
|
||||
name=APP_NAME,
|
||||
app=APP,
|
||||
data_files=DATA_FILES,
|
||||
options={'py2app': OPTIONS},
|
||||
setup_requires=['py2app'],
|
||||
)
|
||||
89
journal/unix-remake/.gitignore
vendored
|
|
@ -1,89 +0,0 @@
|
|||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
.hypothesis/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# IPython Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
|
||||
# dotenv
|
||||
.env
|
||||
|
||||
# virtualenv
|
||||
venv/
|
||||
ENV/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
OneShot Journal
|
||||
===============
|
||||
|
||||
This is a Linux-compatible reimplementation of the Author's Journal, a element in the game [OneShot](http://oneshot-game.com).
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
This journal requires PyQt5 to run. On Debian/Ubuntu-based systems, install via the following command:
|
||||
|
||||
sudo apt-get install python3-pyqt5
|
||||
|
||||
This will install PyQt5 and all necessary files. Next, extract the images from the original OneShot journal program using the instructions in the following section, then use the following command to start the journal:
|
||||
|
||||
python3 journal.py
|
||||
|
||||
Start OneShot and play normally.
|
||||
|
||||
Extracting the images
|
||||
---------------------
|
||||
|
||||
First, aquire a copy of the Windows-version journal executable. Next, download [ResourcesExtract](http://www.nirsoft.net/utils/resources_extract.html) and run it, either via Wine or from a Windows install. Set the filename to the journal executable and the destination to the images directory in your local copy of this repo. Set the program to extract only bitmaps, then press Start. Once extraction completes run the included Python script `renameandconvert.py` (requires ImageMagick), which will create the required PNGs.
|
||||
|
Before Width: | Height: | Size: 183 KiB |
|
Before Width: | Height: | Size: 234 KiB |
|
Before Width: | Height: | Size: 288 KiB |
|
Before Width: | Height: | Size: 218 KiB |
|
Before Width: | Height: | Size: 267 KiB |
|
Before Width: | Height: | Size: 216 KiB |
|
Before Width: | Height: | Size: 289 KiB |
|
Before Width: | Height: | Size: 430 B |
|
Before Width: | Height: | Size: 269 KiB |
|
Before Width: | Height: | Size: 519 B |
|
Before Width: | Height: | Size: 510 B |
|
Before Width: | Height: | Size: 520 B |
|
Before Width: | Height: | Size: 265 KiB |
|
Before Width: | Height: | Size: 250 KiB |
|
Before Width: | Height: | Size: 227 KiB |
|
Before Width: | Height: | Size: 360 KiB |
|
Before Width: | Height: | Size: 548 KiB |
|
Before Width: | Height: | Size: 250 KiB |
|
Before Width: | Height: | Size: 248 KiB |
|
Before Width: | Height: | Size: 246 KiB |
|
Before Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 224 KiB |
|
Before Width: | Height: | Size: 258 KiB |
|
Before Width: | Height: | Size: 224 KiB |
|
Before Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 326 KiB |
|
Before Width: | Height: | Size: 174 KiB |
|
Before Width: | Height: | Size: 252 KiB |
|
Before Width: | Height: | Size: 207 KiB |