Updates for a future Mac build

This commit is contained in:
Vinyl Darkscratch 2016-12-12 22:59:07 -08:00
parent 941b611ba0
commit 0b7fdbf8e1
14 changed files with 698 additions and 94 deletions

6
.gitignore vendored
View File

@ -1,8 +1,10 @@
*.o *.o
*.pro.* *.pro.*
*.cmake
*.bak *.bak
*.xxd *.xxd
*.exe *.exe
*.app
*.bmp *.bmp
Makefile* Makefile*
@ -16,3 +18,7 @@ Makefile*
object_script.* object_script.*
rpgscript.bat rpgscript.bat
.qmake.stash
CMakeCache.txt
CMakeFiles/

View File

@ -6,8 +6,8 @@ Project(mkxp)
option(SHARED_FLUID "Dynamically link fluidsynth at build time" OFF) option(SHARED_FLUID "Dynamically link fluidsynth at build time" OFF)
option(WORKDIR_CURRENT "Keep current directory on startup" OFF) option(WORKDIR_CURRENT "Keep current directory on startup" OFF)
option(FORCE32 "Force 32bit compile on 64bit OS" OFF) option(FORCE32 "Force 32bit compile on 64bit OS" OFF)
set(BINDING "MRI" CACHE STRING "The Binding Type (MRI, MRUBY, NULL)") set(BINDING "MRI" CACHE STRING "The Binding Type (MRI, NULL)")
set(EXTERNAL_LIB_PATH "" CACHE PATH "External precompiled lib prefix") set(EXTERNAL_LIB_PATH "/usr/local/opt/ruby21" CACHE PATH "External precompiled lib prefix")
## Misc setup ## ## Misc setup ##
@ -151,7 +151,7 @@ set(MAIN_HEADERS
src/alstream.h src/alstream.h
src/audiostream.h src/audiostream.h
src/rgssad.h src/rgssad.h
src/windowvx.h src/window.h
src/tilemapvx.h src/tilemapvx.h
src/tileatlasvx.h src/tileatlasvx.h
src/sharedmidistate.h src/sharedmidistate.h
@ -197,7 +197,7 @@ set(MAIN_SOURCE
src/rgssad.cpp src/rgssad.cpp
src/bundledfont.cpp src/bundledfont.cpp
src/vorbissource.cpp src/vorbissource.cpp
src/windowvx.cpp src/window.cpp
src/tilemapvx.cpp src/tilemapvx.cpp
src/tileatlasvx.cpp src/tileatlasvx.cpp
src/autotilesvx.cpp src/autotilesvx.cpp
@ -318,8 +318,8 @@ if (BINDING STREQUAL "MRI")
binding-mri/audio-binding.cpp binding-mri/audio-binding.cpp
binding-mri/module_rpg.cpp binding-mri/module_rpg.cpp
binding-mri/filesystem-binding.cpp binding-mri/filesystem-binding.cpp
binding-mri/windowvx-binding.cpp binding-mri/window-binding.cpp
binding-mri/tilemapvx-binding.cpp binding-mri/tilemap-binding.cpp
) )
elseif(BINDING STREQUAL "MRUBY") elseif(BINDING STREQUAL "MRUBY")
message(FATAL_ERROR "Mruby support in CMake needs to be finished") message(FATAL_ERROR "Mruby support in CMake needs to be finished")

View File

@ -5,12 +5,26 @@
#include <SDL.h> #include <SDL.h>
#if defined __linux //OS-Specific code
#include <fcntl.h> #if defined _WIN32
#include <sys/stat.h> #define OS_W32
#include <sys/types.h> #elif defined __APPLE__ || __linux__
#include <sys/inotify.h> #define LINUX
#include <unistd.h> #ifdef __APPLE__
#define OS_OSX
#else
#define OS_LINUX
#endif
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#ifdef OS_LINUX
#include <sys/inotify.h>
#endif
#include <unistd.h>
#else
#error "Operating system not detected."
#endif #endif
#define BUFFER_SIZE 256 #define BUFFER_SIZE 256
@ -20,20 +34,20 @@ static SDL_mutex *mutex = NULL;
static volatile char message_buffer[BUFFER_SIZE]; static volatile char message_buffer[BUFFER_SIZE];
static volatile bool active = false; static volatile bool active = false;
#if defined __linux #ifdef LINUX
#define PIPE_PATH "/tmp/oneshot-pipe" #define PIPE_PATH "/tmp/oneshot-pipe"
static volatile int message_len = 0; static volatile int message_len = 0;
static volatile int out_pipe = -1; static volatile int out_pipe = -1;
void cleanup_pipe() void cleanup_pipe()
{ {
unlink(PIPE_PATH); unlink(PIPE_PATH);
} }
#endif #endif
int server_thread(void *data) int server_thread(void *data)
{ {
(void)data; (void)data;
#if defined _WIN32 #if defined OS_W32
HANDLE pipe = CreateNamedPipeW(L"\\\\.\\pipe\\oneshot-journal-to-game", HANDLE pipe = CreateNamedPipeW(L"\\\\.\\pipe\\oneshot-journal-to-game",
PIPE_ACCESS_OUTBOUND, PIPE_ACCESS_OUTBOUND,
PIPE_TYPE_BYTE | PIPE_WAIT, PIPE_TYPE_BYTE | PIPE_WAIT,
@ -53,7 +67,7 @@ int server_thread(void *data)
DisconnectNamedPipe(pipe); DisconnectNamedPipe(pipe);
} }
CloseHandle(pipe); CloseHandle(pipe);
#elif defined __linux #else
out_pipe = open(PIPE_PATH, O_WRONLY); out_pipe = open(PIPE_PATH, O_WRONLY);
active = true; active = true;
SDL_LockMutex(mutex); SDL_LockMutex(mutex);
@ -69,7 +83,7 @@ RB_METHOD(journalSet)
RB_UNUSED_PARAM; RB_UNUSED_PARAM;
const char *name; const char *name;
rb_get_args(argc, argv, "z", &name RB_ARG_END); rb_get_args(argc, argv, "z", &name RB_ARG_END);
#if defined _WIN32 #if defined OS_W32
SDL_LockMutex(mutex); SDL_LockMutex(mutex);
strcpy((char*)message_buffer, name); strcpy((char*)message_buffer, name);
SDL_UnlockMutex(mutex); SDL_UnlockMutex(mutex);
@ -90,7 +104,7 @@ RB_METHOD(journalSet)
if (thread == NULL) { if (thread == NULL) {
thread = SDL_CreateThread(server_thread, "journal", NULL); thread = SDL_CreateThread(server_thread, "journal", NULL);
} }
#elif defined __linux #else
// Clean up connection thread // Clean up connection thread
if (thread != NULL && out_pipe != -1) { if (thread != NULL && out_pipe != -1) {
SDL_WaitThread(thread, NULL); SDL_WaitThread(thread, NULL);
@ -115,8 +129,6 @@ RB_METHOD(journalSet)
// We don't have a pipe open, so spawn the connection thread // We don't have a pipe open, so spawn the connection thread
thread = SDL_CreateThread(server_thread, "journal", NULL); thread = SDL_CreateThread(server_thread, "journal", NULL);
} }
#else
#error "not yet implemented"
#endif #endif
return Qnil; return Qnil;
} }
@ -130,7 +142,7 @@ RB_METHOD(journalActive)
void journalBindingInit() void journalBindingInit()
{ {
mutex = SDL_CreateMutex(); mutex = SDL_CreateMutex();
#if defined __linux #ifdef LINUX
mkfifo(PIPE_PATH, 0666); mkfifo(PIPE_PATH, 0666);
atexit(cleanup_pipe); atexit(cleanup_pipe);
#endif #endif

View File

@ -6,6 +6,13 @@
#if defined _WIN32 #if defined _WIN32
#include <shlwapi.h> #include <shlwapi.h>
#elif defined __APPLE__ || __linux__
#define LINUX
#ifdef __APPLE__
#define OS_OSX
#else
#define OS_LINUX
#endif
#endif #endif
#include <SDL.h> #include <SDL.h>
@ -43,7 +50,7 @@ RB_METHOD(nikoStart)
si.cb = sizeof(si); si.cb = sizeof(si);
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
CreateProcessW(path, args, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); CreateProcessW(path, args, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
#elif defined __linux #elif defined LINUX
// Calculate where to stick the window // Calculate where to stick the window
int x, y; // Top-left area of client (hopefully) int x, y; // Top-left area of client (hopefully)
SDL_GetWindowPosition(shState->rtData().window, &x, &y); SDL_GetWindowPosition(shState->rtData().window, &x, &y);

View File

@ -53,6 +53,53 @@ unix:!macx {
# OS X # OS X
macx { 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 # Windows

17
journal/mac/display.h Normal file
View File

@ -0,0 +1,17 @@
#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

113
journal/mac/image.h Normal file
View File

@ -0,0 +1,113 @@
#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
journal/mac/image/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.c

12
journal/mac/image/pixmapper.sh Executable file
View File

@ -0,0 +1,12 @@
#!/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"

235
journal/mac/journal.c Normal file
View File

@ -0,0 +1,235 @@
#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;
}

26
journal/mac/main.c Normal file
View File

@ -0,0 +1,26 @@
#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;
}

114
journal/mac/niko.c Normal file
View File

@ -0,0 +1,114 @@
#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;
}

View File

@ -24,15 +24,6 @@ contains(BINDING, MRI) {
CONFIG += BINDING_MRI CONFIG += BINDING_MRI
} }
contains(BINDING, MRUBY) {
contains(_HAVE_BINDING, YES) {
error("Only one binding may be selected")
}
_HAVE_BINDING = YES
CONFIG += BINDING_MRUBY
}
contains(BINDING, NULL) { contains(BINDING, NULL) {
contains(_HAVE_BINDING, YES) { contains(_HAVE_BINDING, YES) {
error("Only one binding may be selected") error("Only one binding may be selected")
@ -48,9 +39,10 @@ unix {
sdl2 SDL2_image SDL2_ttf SDL_sound physfs sdl2 SDL2_image SDL2_ttf SDL_sound physfs
LIBS += -ldl LIBS += -ldl
macx: { macx: {
CONFIG -= app_bundle #CONFIG -= app_bundle
INCLUDEPATH += $$QMAKE_MAC_SDK_PATH/System/Library/Frameworks/OpenAL.framework/Versions/A/Headers INCLUDEPATH += $$QMAKE_MAC_SDK_PATH/System/Library/Frameworks/OpenAL.framework/Versions/A/Headers
LIBS += -framework OpenAL LIBS += -framework OpenAL
QMAKE_LFLAGS += -L/usr/local/opt/ruby21/lib -L/usr/local/opt/openal-soft/lib
} }
!macx: { !macx: {
PKGCONFIG += openal zlib PKGCONFIG += openal zlib
@ -252,7 +244,7 @@ BINDING_NULL {
BINDING_MRI { BINDING_MRI {
isEmpty(MRIVERSION) { isEmpty(MRIVERSION) {
MRIVERSION = 2.2 MRIVERSION = 2.1
} }
PKGCONFIG += ruby-$$MRIVERSION PKGCONFIG += ruby-$$MRIVERSION

View File

@ -18,16 +18,19 @@
#include <security.h> #include <security.h>
#include <shlobj.h> #include <shlobj.h>
#include <SDL2/SDL_syswm.h> #include <SDL2/SDL_syswm.h>
#elif defined __APPLE__ #elif defined __APPLE__ || __linux__
#ifdef __APPLE__
#define OS_OSX #define OS_OSX
#include <pwd.h> #else
#elif defined __linux__
#define OS_LINUX #define OS_LINUX
#endif
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <pwd.h> #include <pwd.h>
#include <dlfcn.h> #include <dlfcn.h>
#ifdef OS_LINUX
class GtkWidget; class GtkWidget;
typedef enum typedef enum
@ -62,6 +65,7 @@
GTK_RESPONSE_APPLY = -10, GTK_RESPONSE_APPLY = -10,
GTK_RESPONSE_HELP = -11 GTK_RESPONSE_HELP = -11
} GtkResponseType; } GtkResponseType;
#endif
/** /**
* xdg_user_dir_lookup_with_fallback: * xdg_user_dir_lookup_with_fallback:
@ -422,6 +426,25 @@ Oneshot::Oneshot(RGSSThreadData &threadData) :
else else
p->lang = "en"; p->lang = "en";
#ifdef OS_OSX
//Get user's name
struct passwd *pwd = getpwuid(geteuid());
if (pwd)
{
if (pwd->pw_gecos && pwd->pw_gecos[0] && pwd->pw_gecos[0] != ',')
{
//Get the user's full name
int comma = 0;
for (; pwd->pw_gecos[comma] && pwd->pw_gecos[comma] != ','; ++comma) {}
p->userName = std::string(pwd->pw_gecos, comma);
}
else
p->userName = pwd->pw_name;
}
#elif defined OS_LINUX
//Get user's name //Get user's name
struct passwd *pwd = getpwuid(getuid()); struct passwd *pwd = getpwuid(getuid());
if (pwd) if (pwd)
@ -437,13 +460,12 @@ Oneshot::Oneshot(RGSSThreadData &threadData) :
p->userName = pwd->pw_name; p->userName = pwd->pw_name;
} }
#ifdef OS_LINUX #endif
//Get documents path //Get documents path
char *path = xdg_user_dir_lookup_with_fallback("DOCUMENTS", getenv("HOME")); char *path = xdg_user_dir_lookup_with_fallback("DOCUMENTS", getenv("HOME"));
p->docsPath = path; p->docsPath = path;
free(path); free(path);
#elif OS_OSX
#endif
#endif #endif
/********** /**********