main render_wayland.c
   1/*
   2 Copyright 2013 Michael Pavone
   3 This file is part of BlastEm.
   4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
   5*/
   6#include <stdlib.h>
   7#include <stdio.h>
   8#include <string.h>
   9#include <stdint.h>
  10#include <errno.h>
  11#include <math.h>
  12#include <linux/input.h>
  13#include <linux/kd.h>
  14#include <alsa/asoundlib.h>
  15#include <sys/types.h>
  16#include <sys/stat.h>
  17#include <sys/ioctl.h>
  18#include <sys/mman.h>
  19#include <poll.h>
  20#include <fcntl.h>
  21#include <unistd.h>
  22#include <pthread.h>
  23#include <dirent.h>
  24#include <wayland-client.h>
  25#include "xdg-shell-client-protocol.h"
  26#include <sys/syscall.h>
  27#include <time.h>
  28#include "render.h"
  29#include "blastem.h"
  30#include "genesis.h"
  31#include "bindings.h"
  32#include "util.h"
  33#include "paths.h"
  34#include "ppm.h"
  35#include "png.h"
  36#include "config.h"
  37#include "controller_info.h"
  38
  39#define MAX_EVENT_POLL_PER_FRAME 2
  40
  41static int main_width, main_height;
  42static snd_pcm_uframes_t buffer_samples;
  43static unsigned int output_channels, sample_rate;
  44
  45
  46struct audio_source {
  47	int16_t  *front;
  48	int16_t  *back;
  49	double   dt;
  50	uint64_t buffer_fraction;
  51	uint64_t buffer_inc;
  52	uint32_t buffer_pos;
  53	uint32_t read_start;
  54	uint32_t read_end;
  55	uint32_t lowpass_alpha;
  56	uint32_t mask;
  57	float    gain_mult;
  58	int16_t  last_left;
  59	int16_t  last_right;
  60	uint8_t  num_channels;
  61	uint8_t  front_populated;
  62};
  63
  64static audio_source *audio_sources[8];
  65static audio_source *inactive_audio_sources[8];
  66static uint8_t num_audio_sources;
  67static uint8_t num_inactive_audio_sources;
  68
  69typedef int32_t (*mix_func)(audio_source *audio, void *vstream, int len);
  70
  71static int32_t mix_s16(audio_source *audio, void *vstream, int len)
  72{
  73	int samples = len/(sizeof(int16_t)*output_channels);
  74	int16_t *stream = vstream;
  75	int16_t *end = stream + output_channels*samples;
  76	int16_t *src = audio->front;
  77	uint32_t i = audio->read_start;
  78	uint32_t i_end = audio->read_end;
  79	int16_t *cur = stream;
  80	size_t first_add = output_channels > 1 ? 1 : 0, second_add = output_channels > 1 ? output_channels - 1 : 1;
  81	if (audio->num_channels == 1) {
  82		while (cur < end && i != i_end)
  83		{
  84			*cur += src[i];
  85			cur += first_add;
  86			*cur += src[i++];
  87			cur += second_add;
  88			i &= audio->mask;
  89		}
  90	} else {
  91		while (cur < end && i != i_end)
  92		{
  93			*cur += src[i++];
  94			cur += first_add;
  95			*cur += src[i++];
  96			cur += second_add;
  97			i &= audio->mask;
  98		}
  99	}
 100	
 101	if (cur != end) {
 102		printf("Underflow of %d samples, read_start: %d, read_end: %d, mask: %X\n", (int)(end-cur)/2, audio->read_start, audio->read_end, audio->mask);
 103	}
 104	if (cur != end) {
 105		//printf("Underflow of %d samples, read_start: %d, read_end: %d, mask: %X\n", (int)(end-cur)/2, audio->read_start, audio->read_end, audio->mask);
 106		return (cur-end)/2;
 107	} else {
 108		return ((i_end - i) & audio->mask) / audio->num_channels;
 109	}
 110}
 111
 112static int32_t mix_f32(audio_source *audio, void *vstream, int len)
 113{
 114	int samples = len/(sizeof(float)*output_channels);
 115	float *stream = vstream;
 116	float *end = stream + output_channels*samples;
 117	int16_t *src = audio->front;
 118	uint32_t i = audio->read_start;
 119	uint32_t i_end = audio->read_end;
 120	float *cur = stream;
 121	size_t first_add = output_channels > 1 ? 1 : 0, second_add = output_channels > 1 ? output_channels - 1 : 1;
 122	if (audio->num_channels == 1) {
 123		while (cur < end && i != i_end)
 124		{
 125			*cur += ((float)src[i]) / 0x7FFF;
 126			cur += first_add;
 127			*cur += ((float)src[i++]) / 0x7FFF;
 128			cur += second_add;
 129			i &= audio->mask;
 130		}
 131	} else {
 132		while(cur < end && i != i_end)
 133		{
 134			*cur += ((float)src[i++]) / 0x7FFF;
 135			cur += first_add;
 136			*cur += ((float)src[i++]) / 0x7FFF;
 137			cur += second_add;
 138			i &= audio->mask;
 139		}
 140	}
 141	if (cur != end) {
 142		printf("Underflow of %d samples, read_start: %d, read_end: %d, mask: %X\n", (int)(end-cur)/2, audio->read_start, audio->read_end, audio->mask);
 143		return (cur-end)/2;
 144	} else {
 145		return ((i_end - i) & audio->mask) / audio->num_channels;
 146	}
 147}
 148
 149static mix_func mix;
 150
 151static snd_pcm_t *audio_handle;
 152static void render_close_audio()
 153{
 154	if (audio_handle) {
 155		snd_pcm_close(audio_handle);
 156		audio_handle = NULL;
 157	}
 158}
 159
 160static void destroy_wayland(void);
 161
 162#define BUFFER_INC_RES 0x40000000UL
 163
 164void render_audio_adjust_clock(audio_source *src, uint64_t master_clock, uint64_t sample_divider)
 165{
 166	src->buffer_inc = ((BUFFER_INC_RES * (uint64_t)sample_rate) / master_clock) * sample_divider;
 167}
 168
 169audio_source *render_audio_source(uint64_t master_clock, uint64_t sample_divider, uint8_t channels)
 170{
 171	audio_source *ret = NULL;
 172	uint32_t alloc_size = channels * buffer_samples;
 173	if (num_audio_sources < 8) {
 174		ret = malloc(sizeof(audio_source));
 175		ret->back = malloc(alloc_size * sizeof(int16_t));
 176		ret->front = malloc(alloc_size * sizeof(int16_t));
 177		ret->front_populated = 0;
 178		ret->num_channels = channels;
 179		audio_sources[num_audio_sources++] = ret;
 180	}
 181	if (!ret) {
 182		fatal_error("Too many audio sources!");
 183	} else {
 184		render_audio_adjust_clock(ret, master_clock, sample_divider);
 185		double lowpass_cutoff = get_lowpass_cutoff(config);
 186		double rc = (1.0 / lowpass_cutoff) / (2.0 * M_PI);
 187		ret->dt = 1.0 / ((double)master_clock / (double)(sample_divider));
 188		double alpha = ret->dt / (ret->dt + rc);
 189		ret->lowpass_alpha = (int32_t)(((double)0x10000) * alpha);
 190		ret->buffer_pos = 0;
 191		ret->buffer_fraction = 0;
 192		ret->gain_mult = 1.0f;
 193		ret->last_left = ret->last_right = 0;
 194		ret->read_start = 0;
 195		ret->read_end = buffer_samples * channels;
 196		ret->mask = 0xFFFFFFFF;
 197	}
 198	return ret;
 199}
 200
 201static float db_to_mult(float gain)
 202{
 203	return powf(10.0f, gain / 20.0f);
 204}
 205
 206void render_audio_source_gaindb(audio_source *src, float gain)
 207{
 208	src->gain_mult = db_to_mult(gain);
 209}
 210
 211void render_pause_source(audio_source *src)
 212{
 213	for (uint8_t i = 0; i < num_audio_sources; i++)
 214	{
 215		if (audio_sources[i] == src) {
 216			audio_sources[i] = audio_sources[--num_audio_sources];
 217			break;
 218		}
 219	}
 220	inactive_audio_sources[num_inactive_audio_sources++] = src;
 221}
 222
 223void render_resume_source(audio_source *src)
 224{
 225	if (num_audio_sources < 8) {
 226		audio_sources[num_audio_sources++] = src;
 227	}
 228	for (uint8_t i = 0; i < num_inactive_audio_sources; i++)
 229	{
 230		if (inactive_audio_sources[i] == src) {
 231			inactive_audio_sources[i] = inactive_audio_sources[--num_inactive_audio_sources];
 232		}
 233	}
 234}
 235
 236void render_free_source(audio_source *src)
 237{
 238	render_pause_source(src);
 239	
 240	free(src->front);
 241	free(src->back);
 242	free(src);
 243}
 244static void do_audio_ready(audio_source *src)
 245{
 246	if (src->front_populated) {
 247		fatal_error("Audio source filled up a buffer a second time before other sources finished their first\n");
 248	}
 249	int16_t *tmp = src->front;
 250	src->front = src->back;
 251	src->back = tmp;
 252	src->front_populated = 1;
 253	src->buffer_pos = 0;
 254	
 255	for (uint8_t i = 0; i < num_audio_sources; i++)
 256	{
 257		if (!audio_sources[i]->front_populated) {
 258			//at least one audio source is not ready yet.
 259			return;
 260		}
 261	}
 262	
 263	size_t bytes = (mix == mix_s16 ? sizeof(int16_t) : sizeof(float)) * output_channels * buffer_samples;
 264	void *buffer = calloc(1, bytes);
 265	for (uint8_t i = 0; i < num_audio_sources; i++)
 266	{
 267		mix(audio_sources[i], buffer, bytes);
 268		audio_sources[i]->front_populated = 0;
 269	}
 270	int frames = snd_pcm_writei(audio_handle, buffer, buffer_samples);
 271	if (frames < 0) {
 272		frames = snd_pcm_recover(audio_handle, frames, 0);
 273	}
 274	if (frames < 0) {
 275		fprintf(stderr, "Failed to write samples: %s\n", snd_strerror(frames));
 276	}
 277	free(buffer);
 278}
 279
 280static int16_t lowpass_sample(audio_source *src, int16_t last, int16_t current)
 281{
 282	int32_t tmp = current * src->lowpass_alpha + last * (0x10000 - src->lowpass_alpha);
 283	current = tmp >> 16;
 284	return current;
 285}
 286
 287static void interp_sample(audio_source *src, int16_t last, int16_t current)
 288{
 289	int64_t tmp = last * ((src->buffer_fraction << 16) / src->buffer_inc);
 290	tmp += current * (0x10000 - ((src->buffer_fraction << 16) / src->buffer_inc));
 291	src->back[src->buffer_pos++] = tmp >> 16;
 292}
 293
 294void render_put_mono_sample(audio_source *src, int16_t value)
 295{
 296	value = lowpass_sample(src, src->last_left, value);
 297	src->buffer_fraction += src->buffer_inc;
 298	uint32_t base = 0;
 299	while (src->buffer_fraction > BUFFER_INC_RES)
 300	{
 301		src->buffer_fraction -= BUFFER_INC_RES;
 302		interp_sample(src, src->last_left, value);
 303		
 304		if (((src->buffer_pos - base) & src->mask) >= buffer_samples) {
 305			do_audio_ready(src);
 306		}
 307		src->buffer_pos &= src->mask;
 308	}
 309	src->last_left = value;
 310}
 311
 312void render_put_stereo_sample(audio_source *src, int16_t left, int16_t right)
 313{
 314	left = lowpass_sample(src, src->last_left, left);
 315	right = lowpass_sample(src, src->last_right, right);
 316	src->buffer_fraction += src->buffer_inc;
 317	uint32_t base = 0;
 318	while (src->buffer_fraction > BUFFER_INC_RES)
 319	{
 320		src->buffer_fraction -= BUFFER_INC_RES;
 321		
 322		interp_sample(src, src->last_left, left);
 323		interp_sample(src, src->last_right, right);
 324		
 325		if (((src->buffer_pos - base) & src->mask)/2 >= buffer_samples) {
 326			do_audio_ready(src);
 327		}
 328		src->buffer_pos &= src->mask;
 329	}
 330	src->last_left = left;
 331	src->last_right = right;
 332}
 333
 334int render_width()
 335{
 336	return main_width;
 337}
 338
 339int render_height()
 340{
 341	return main_height;
 342}
 343
 344uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b)
 345{
 346	return 0xFF000000 | r << 16 | g << 8 | b;
 347}
 348
 349#define MAX_VIDEO_BUFFER_LINES 590
 350static uint32_t video_buffer[MAX_VIDEO_BUFFER_LINES * LINEBUF_SIZE * 2];
 351
 352static char * caption = NULL;
 353static char * fps_caption = NULL;
 354
 355static void render_quit()
 356{
 357	render_close_audio();
 358	destroy_wayland();
 359}
 360
 361static float config_aspect()
 362{
 363	static float aspect = 0.0f;
 364	if (aspect == 0.0f) {
 365		char *config_aspect = tern_find_path_default(config, "video\0aspect\0", (tern_val){.ptrval = "4:3"}, TVAL_PTR).ptrval;
 366		if (strcmp("stretch", config_aspect)) {
 367			aspect = 4.0f/3.0f;
 368			char *end;
 369			float aspect_numerator = strtof(config_aspect, &end);
 370			if (aspect_numerator > 0.0f && *end == ':') {
 371				float aspect_denominator = strtof(end+1, &end);
 372				if (aspect_denominator > 0.0f && !*end) {
 373					aspect = aspect_numerator / aspect_denominator;
 374				}
 375			}
 376		} else {
 377			aspect = -1.0f;
 378		}
 379	}
 380	return aspect;
 381}
 382
 383static uint8_t scancode_map[128] = {
 384	[KEY_A] = 0x1C,
 385	[KEY_B] = 0x32,
 386	[KEY_C] = 0x21,
 387	[KEY_D] = 0x23,
 388	[KEY_E] = 0x24,
 389	[KEY_F] = 0x2B,
 390	[KEY_G] = 0x34,
 391	[KEY_H] = 0x33,
 392	[KEY_I] = 0x43,
 393	[KEY_J] = 0x3B,
 394	[KEY_K] = 0x42,
 395	[KEY_L] = 0x4B,
 396	[KEY_M] = 0x3A,
 397	[KEY_N] = 0x31,
 398	[KEY_O] = 0x44,
 399	[KEY_P] = 0x4D,
 400	[KEY_Q] = 0x15,
 401	[KEY_R] = 0x2D,
 402	[KEY_S] = 0x1B,
 403	[KEY_T] = 0x2C,
 404	[KEY_U] = 0x3C,
 405	[KEY_V] = 0x2A,
 406	[KEY_W] = 0x1D,
 407	[KEY_X] = 0x22,
 408	[KEY_Y] = 0x35,
 409	[KEY_Z] = 0x1A,
 410	[KEY_1] = 0x16,
 411	[KEY_2] = 0x1E,
 412	[KEY_3] = 0x26,
 413	[KEY_4] = 0x25,
 414	[KEY_5] = 0x2E,
 415	[KEY_6] = 0x36,
 416	[KEY_7] = 0x3D,
 417	[KEY_8] = 0x3E,
 418	[KEY_9] = 0x46,
 419	[KEY_0] = 0x45,
 420	[KEY_ENTER] = 0x5A,
 421	[KEY_ESC] = 0x76,
 422	[KEY_SPACE] = 0x29,
 423	[KEY_TAB] = 0x0D,
 424	[KEY_BACKSPACE] = 0x66,
 425	[KEY_MINUS] = 0x4E,
 426	[KEY_EQUAL] = 0x55,
 427	[KEY_LEFTBRACE] = 0x54,
 428	[KEY_RIGHTBRACE] = 0x5B,
 429	[KEY_BACKSLASH] = 0x5D,
 430	[KEY_SEMICOLON] = 0x4C,
 431	[KEY_APOSTROPHE] = 0x52,
 432	[KEY_GRAVE] = 0x0E,
 433	[KEY_COMMA] = 0x41,
 434	[KEY_DOT] = 0x49,
 435	[KEY_SLASH] = 0x4A,
 436	[KEY_CAPSLOCK] = 0x58,
 437	[KEY_F1] = 0x05,
 438	[KEY_F2] = 0x06,
 439	[KEY_F3] = 0x04,
 440	[KEY_F4] = 0x0C,
 441	[KEY_F5] = 0x03,
 442	[KEY_F6] = 0x0B,
 443	[KEY_F7] = 0x83,
 444	[KEY_F8] = 0x0A,
 445	[KEY_F9] = 0x01,
 446	[KEY_F10] = 0x09,
 447	[KEY_F11] = 0x78,
 448	[KEY_F12] = 0x07,
 449	[KEY_LEFTCTRL] = 0x14,
 450	[KEY_LEFTSHIFT] = 0x12,
 451	[KEY_LEFTALT] = 0x11,
 452	[KEY_RIGHTCTRL] = 0x18,
 453	[KEY_RIGHTSHIFT] = 0x59,
 454	[KEY_RIGHTALT] = 0x17,
 455	[KEY_INSERT] = 0x81,
 456	[KEY_PAUSE] = 0x82,
 457	[KEY_SYSRQ] = 0x84,
 458	[KEY_SCROLLLOCK] = 0x7E,
 459	[KEY_DELETE] = 0x85,
 460	[KEY_LEFT] = 0x86,
 461	[KEY_HOME] = 0x87,
 462	[KEY_END] = 0x88,
 463	[KEY_UP] = 0x89,
 464	[KEY_DOWN] = 0x8A,
 465	[KEY_PAGEUP] = 0x8B,
 466	[KEY_PAGEDOWN] = 0x8C,
 467	[KEY_RIGHT] = 0x8D,
 468	[KEY_NUMLOCK] = 0x77,
 469	[KEY_KPSLASH] = 0x80,
 470	[KEY_KPASTERISK] = 0x7C,
 471	[KEY_KPMINUS] = 0x7B,
 472	[KEY_KPPLUS] = 0x79,
 473	[KEY_KPENTER] = 0x19,
 474	[KEY_KP1] = 0x69,
 475	[KEY_KP2] = 0x72,
 476	[KEY_KP3] = 0x7A,
 477	[KEY_KP4] = 0x6B,
 478	[KEY_KP5] = 0x73,
 479	[KEY_KP6] = 0x74,
 480	[KEY_KP7] = 0x6C,
 481	[KEY_KP8] = 0x75,
 482	[KEY_KP9] = 0x7D,
 483	[KEY_KP0] = 0x70,
 484	[KEY_KPDOT] = 0x71,
 485};
 486
 487#include "special_keys_evdev.h"
 488static uint8_t sym_map[128] = {
 489	[KEY_A] = 'a',
 490	[KEY_B] = 'b',
 491	[KEY_C] = 'c',
 492	[KEY_D] = 'd',
 493	[KEY_E] = 'e',
 494	[KEY_F] = 'f',
 495	[KEY_G] = 'g',
 496	[KEY_H] = 'h',
 497	[KEY_I] = 'i',
 498	[KEY_J] = 'j',
 499	[KEY_K] = 'k',
 500	[KEY_L] = 'l',
 501	[KEY_M] = 'm',
 502	[KEY_N] = 'n',
 503	[KEY_O] = 'o',
 504	[KEY_P] = 'p',
 505	[KEY_Q] = 'q',
 506	[KEY_R] = 'r',
 507	[KEY_S] = 's',
 508	[KEY_T] = 't',
 509	[KEY_U] = 'u',
 510	[KEY_V] = 'v',
 511	[KEY_W] = 'w',
 512	[KEY_X] = 'x',
 513	[KEY_Y] = 'y',
 514	[KEY_Z] = 'z',
 515	[KEY_1] = '1',
 516	[KEY_2] = '2',
 517	[KEY_3] = '3',
 518	[KEY_4] = '4',
 519	[KEY_5] = '5',
 520	[KEY_6] = '6',
 521	[KEY_7] = '7',
 522	[KEY_8] = '8',
 523	[KEY_9] = '9',
 524	[KEY_0] = '0',
 525	[KEY_ENTER] = '\r',
 526	[KEY_SPACE] = ' ',
 527	[KEY_TAB] = '\t',
 528	[KEY_BACKSPACE] = '\b',
 529	[KEY_MINUS] = '-',
 530	[KEY_EQUAL] = '=',
 531	[KEY_LEFTBRACE] = '[',
 532	[KEY_RIGHTBRACE] = ']',
 533	[KEY_BACKSLASH] = '\\',
 534	[KEY_SEMICOLON] = ';',
 535	[KEY_APOSTROPHE] = '\'',
 536	[KEY_GRAVE] = '`',
 537	[KEY_COMMA] = ',',
 538	[KEY_DOT] = '.',
 539	[KEY_SLASH] = '/',
 540	[KEY_ESC] = RENDERKEY_ESC,
 541	[KEY_F1] = RENDERKEY_F1,
 542	[KEY_F2] = RENDERKEY_F2,
 543	[KEY_F3] = RENDERKEY_F3,
 544	[KEY_F4] = RENDERKEY_F4,
 545	[KEY_F5] = RENDERKEY_F5,
 546	[KEY_F6] = RENDERKEY_F6,
 547	[KEY_F7] = RENDERKEY_F7,
 548	[KEY_F8] = RENDERKEY_F8,
 549	[KEY_F9] = RENDERKEY_F9,
 550	[KEY_F10] = RENDERKEY_F10,
 551	[KEY_F11] = RENDERKEY_F11,
 552	[KEY_F12] = RENDERKEY_F12,
 553	[KEY_LEFTCTRL] = RENDERKEY_LCTRL,
 554	[KEY_LEFTSHIFT] = RENDERKEY_LSHIFT,
 555	[KEY_LEFTALT] = RENDERKEY_LALT,
 556	[KEY_RIGHTCTRL] = RENDERKEY_RCTRL,
 557	[KEY_RIGHTSHIFT] = RENDERKEY_RSHIFT,
 558	[KEY_RIGHTALT] = RENDERKEY_RALT,
 559	[KEY_DELETE] = RENDERKEY_DEL,
 560	[KEY_LEFT] = RENDERKEY_LEFT,
 561	[KEY_HOME] = RENDERKEY_HOME,
 562	[KEY_END] = RENDERKEY_END,
 563	[KEY_UP] = RENDERKEY_UP,
 564	[KEY_DOWN] = RENDERKEY_DOWN,
 565	[KEY_PAGEUP] = RENDERKEY_PAGEUP,
 566	[KEY_PAGEDOWN] = RENDERKEY_PAGEDOWN,
 567	[KEY_RIGHT] = RENDERKEY_RIGHT,
 568	[KEY_KPSLASH] = 0x80,
 569	[KEY_KPASTERISK] = 0x7C,
 570	[KEY_KPMINUS] = 0x7B,
 571	[KEY_KPPLUS] = 0x79,
 572	[KEY_KPENTER] = 0x19,
 573	[KEY_KP1] = 0x69,
 574	[KEY_KP2] = 0x72,
 575	[KEY_KP3] = 0x7A,
 576	[KEY_KP4] = 0x6B,
 577	[KEY_KP5] = 0x73,
 578	[KEY_KP6] = 0x74,
 579	[KEY_KP7] = 0x6C,
 580	[KEY_KP8] = 0x75,
 581	[KEY_KP9] = 0x7D,
 582	[KEY_KP0] = 0x70,
 583	[KEY_KPDOT] = 0x71,
 584};
 585
 586char* render_joystick_type_id(int index)
 587{
 588	return strdup("");
 589}
 590
 591static uint32_t overscan_top[NUM_VID_STD] = {2, 21};
 592static uint32_t overscan_bot[NUM_VID_STD] = {1, 17};
 593static uint32_t overscan_left[NUM_VID_STD] = {13, 13};
 594static uint32_t overscan_right[NUM_VID_STD] = {14, 14};
 595static vid_std video_standard = VID_NTSC;
 596
 597typedef enum {
 598	DEV_NONE,
 599	DEV_KEYBOARD,
 600	DEV_MOUSE,
 601	DEV_GAMEPAD
 602} device_type;
 603
 604static int32_t mouse_x, mouse_y, mouse_accum_x, mouse_accum_y;
 605static int32_t handle_event(device_type dtype, int device_index, struct input_event *event)
 606{
 607	switch (event->type) {
 608	case EV_KEY:
 609		//code is key, value is 1 for keydown, 0 for keyup
 610		if (dtype == DEV_KEYBOARD && event->code < 128) {
 611			//keyboard key that we might have a mapping for
 612			if (event->value) {
 613				handle_keydown(sym_map[event->code], scancode_map[event->code]);
 614			} else {
 615				handle_keyup(sym_map[event->code], scancode_map[event->code]);
 616			}
 617		} else if (dtype == DEV_MOUSE && event->code >= BTN_MOUSE && event->code < BTN_JOYSTICK) {
 618			//mosue button
 619			if (event->value) {
 620				handle_mousedown(device_index, event->code - BTN_LEFT);
 621			} else {
 622				handle_mouseup(device_index, event->code - BTN_LEFT);
 623			}
 624		} else if (dtype == DEV_GAMEPAD && event->code >= BTN_GAMEPAD && event->code < BTN_DIGI) {
 625			//gamepad button
 626			if (event->value) {
 627				handle_joydown(device_index, event->code - BTN_SOUTH);
 628			} else {
 629				handle_joyup(device_index, event->code - BTN_SOUTH);
 630			}
 631		}
 632		break;
 633	case EV_REL:
 634		if (dtype == DEV_MOUSE) {
 635			switch(event->code)
 636			{
 637			case REL_X:
 638				mouse_accum_x += event->value;
 639				break;
 640			case REL_Y:
 641				mouse_accum_y += event->value;
 642				break;
 643			}
 644		}
 645		break;
 646	case EV_ABS:
 647		//TODO: Handle joystick axis/hat motion, absolute mouse movement
 648		break;
 649	case EV_SYN:
 650		if (dtype == DEV_MOUSE && (mouse_accum_x || mouse_accum_y)) {
 651			mouse_x += mouse_accum_x;
 652			mouse_y += mouse_accum_y;
 653			if (mouse_x < 0) {
 654				mouse_x = 0;
 655			} else if (mouse_x >= main_width) {
 656				mouse_x = main_width - 1;
 657			}
 658			if (mouse_y < 0) {
 659				mouse_y = 0;
 660			} else if (mouse_y >= main_height) {
 661				mouse_y = main_height - 1;
 662			}
 663			handle_mouse_moved(device_index, mouse_x, mouse_y, mouse_accum_x, mouse_accum_y);
 664			mouse_accum_x = mouse_accum_y = 0;
 665		}
 666		break;
 667	}
 668	return 0;
 669}
 670
 671#define MAX_DEVICES 16
 672static int device_fds[MAX_DEVICES];
 673static device_type device_types[MAX_DEVICES];
 674static int cur_devices;
 675
 676static void drain_events()
 677{
 678	struct input_event events[64];
 679	int index_by_type[3] = {0,0,0};
 680	for (int i = 0; i < cur_devices; i++)
 681	{
 682		int bytes = sizeof(events);
 683		int device_index = index_by_type[device_types[i]-1]++;
 684		while (bytes == sizeof(events))
 685		{
 686			bytes = read(device_fds[i], events, sizeof(events));
 687			if (bytes > 0) {
 688				int num_events = bytes / sizeof(events[0]);
 689				for (int j = 0; j < num_events; j++)
 690				{
 691					handle_event(device_types[i], device_index, events + j);
 692				}
 693			} else if (bytes < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
 694				perror("Failed to read evdev events");
 695			}
 696		}
 697	}
 698}
 699
 700static char *vid_std_names[NUM_VID_STD] = {"ntsc", "pal"};
 701
 702static void init_audio()
 703{
 704	char *device_name = tern_find_path_default(config, "audio\0alsa_device\0", (tern_val){.ptrval="default"}, TVAL_PTR).ptrval;
 705	int res = snd_pcm_open(&audio_handle, device_name, SND_PCM_STREAM_PLAYBACK, 0);
 706	if (res < 0) {
 707		fatal_error("Failed to open ALSA device: %s\n", snd_strerror(res));
 708	}
 709	
 710	snd_pcm_hw_params_t *params;
 711	snd_pcm_hw_params_alloca(&params);
 712	res = snd_pcm_hw_params_any(audio_handle, params);
 713	if (res < 0) {
 714		fatal_error("No playback configurations available: %s\n", snd_strerror(res));
 715	}
 716	res = snd_pcm_hw_params_set_access(audio_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
 717	if (res < 0) {
 718		fatal_error("Failed to set access type: %s\n", snd_strerror(res));
 719	}
 720	res = snd_pcm_hw_params_set_format(audio_handle, params, SND_PCM_FORMAT_S16_LE);
 721	if (res < 0) {
 722		//failed to set, signed 16-bit integer, try floating point
 723		res = snd_pcm_hw_params_set_format(audio_handle, params, SND_PCM_FORMAT_FLOAT_LE);
 724		if (res < 0) {
 725			fatal_error("Failed to set an acceptable format: %s\n", snd_strerror(res));
 726		}
 727		mix = mix_f32;
 728	} else {
 729		mix = mix_s16;
 730	}
 731
 732    char * rate_str = tern_find_path(config, "audio\0rate\0", TVAL_PTR).ptrval;
 733   	sample_rate = rate_str ? atoi(rate_str) : 0;
 734   	if (!sample_rate) {
 735   		sample_rate = 48000;
 736   	}
 737    snd_pcm_hw_params_set_rate_near(audio_handle, params, &sample_rate, NULL);
 738	output_channels = 2;
 739	snd_pcm_hw_params_set_channels_near(audio_handle, params, &output_channels);
 740
 741    char * samples_str = tern_find_path(config, "audio\0buffer\0", TVAL_PTR).ptrval;
 742   	buffer_samples = samples_str ? atoi(samples_str) : 0;
 743   	if (!buffer_samples) {
 744   		buffer_samples = 512;
 745   	}
 746	snd_pcm_hw_params_set_period_size_near(audio_handle, params, &buffer_samples, NULL);
 747	
 748	int dir = 1;
 749	unsigned int periods = 2;
 750	snd_pcm_hw_params_set_periods_near(audio_handle, params, &periods, &dir);
 751
 752	res = snd_pcm_hw_params(audio_handle, params);
 753	if (res < 0) {
 754		fatal_error("Failed to set ALSA hardware params: %s\n", snd_strerror(res));
 755	}
 756	
 757	printf("Initialized audio at frequency %d with a %d sample buffer, ", (int)sample_rate, (int)buffer_samples);
 758	if (mix == mix_s16) {
 759		puts("signed 16-bit int format");
 760	} else {
 761		puts("32-bit float format");
 762	}
 763}
 764
 765struct wayland_buffer {
 766	struct wl_buffer *buffer;
 767	uint32_t *pixels;
 768	uint8_t busy;
 769};
 770
 771static struct wl_display *wl_display_handle;
 772static struct wl_compositor *wl_compositor_handle;
 773static struct wl_shm *wl_shm_handle;
 774static struct wl_seat *wl_seat_handle;
 775static struct wl_keyboard *wl_keyboard_handle;
 776static struct wl_pointer *wl_pointer_handle;
 777static struct xdg_wm_base *xdg_wm_base_handle;
 778static struct wl_surface *wl_surface_handle;
 779static struct xdg_surface *xdg_surface_handle;
 780static struct xdg_toplevel *xdg_toplevel_handle;
 781static struct wl_callback *frame_callback;
 782static struct wayland_buffer wl_buffers[2];
 783static uint8_t wl_cur_buffer;
 784static uint8_t wl_configured;
 785static uint8_t frame_pending;
 786static uint32_t wl_stride;
 787static int32_t wl_pointer_x, wl_pointer_y;
 788static uint32_t *copy_buffer;
 789static uint32_t last_width, last_width_scale, last_height, last_height_scale;
 790static uint32_t max_multiple;
 791
 792static void wl_buffer_release(void *data, struct wl_buffer *buffer)
 793{
 794	((struct wayland_buffer *)data)->busy = 0;
 795}
 796
 797static const struct wl_buffer_listener wl_buffer_listener = {
 798	.release = wl_buffer_release
 799};
 800
 801static void dispatch_wayland_pending(uint32_t timeout)
 802{
 803	if (!wl_display_handle) {
 804		return;
 805	}
 806	while (wl_display_prepare_read(wl_display_handle) != 0)
 807	{
 808		wl_display_dispatch_pending(wl_display_handle);
 809	}
 810	wl_display_flush(wl_display_handle);
 811	struct pollfd pfd = {
 812		.fd = wl_display_get_fd(wl_display_handle),
 813		.events = POLLIN
 814	};
 815	if (poll(&pfd, 1, timeout) > 0 && (pfd.revents & POLLIN)) {
 816		wl_display_read_events(wl_display_handle);
 817	} else {
 818		wl_display_cancel_read(wl_display_handle);
 819	}
 820	wl_display_dispatch_pending(wl_display_handle);
 821}
 822
 823static void frame_done(void *data, struct wl_callback *callback, uint32_t time)
 824{
 825	wl_callback_destroy(callback);
 826	if (callback == frame_callback) {
 827		frame_callback = NULL;
 828		frame_pending = 0;
 829	}
 830}
 831
 832static const struct wl_callback_listener frame_listener = {
 833	.done = frame_done
 834};
 835
 836static int create_shm_file(size_t size)
 837{
 838#ifdef SYS_memfd_create
 839	int fd = syscall(SYS_memfd_create, "blastem-wayland", 0);
 840	if (fd >= 0) {
 841		if (ftruncate(fd, size) == 0) {
 842			return fd;
 843		}
 844		close(fd);
 845	}
 846#endif
 847	char template[] = "/blastem-wayland-XXXXXX";
 848	const char *runtime_dir = getenv("XDG_RUNTIME_DIR");
 849	if (!runtime_dir) {
 850		return -1;
 851	}
 852	char *name = alloc_concat(runtime_dir, template);
 853	fd = mkstemp(name);
 854	if (fd >= 0) {
 855		int flags = fcntl(fd, F_GETFD);
 856		if (flags >= 0) {
 857			fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
 858		}
 859		unlink(name);
 860		if (ftruncate(fd, size) == 0) {
 861			free(name);
 862			return fd;
 863		}
 864		close(fd);
 865	}
 866	free(name);
 867	return -1;
 868}
 869
 870static void create_wayland_buffer(struct wayland_buffer *buf);
 871static void destroy_wayland_buffer(struct wayland_buffer *buf);
 872
 873static void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial)
 874{
 875	xdg_wm_base_pong(xdg_wm_base, serial);
 876}
 877
 878static const struct xdg_wm_base_listener xdg_wm_base_listener = {
 879	.ping = xdg_wm_base_ping
 880};
 881
 882static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial)
 883{
 884	xdg_surface_ack_configure(xdg_surface, serial);
 885	wl_configured = 1;
 886}
 887
 888static const struct xdg_surface_listener xdg_surface_listener = {
 889	.configure = xdg_surface_configure
 890};
 891
 892static void xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states)
 893{
 894	if (width > 0 && height > 0 && (width != main_width || height != main_height)) {
 895		destroy_wayland_buffer(&wl_buffers[0]);
 896		destroy_wayland_buffer(&wl_buffers[1]);
 897		main_width = width;
 898		main_height = height;
 899		wl_stride = main_width * sizeof(uint32_t);
 900		create_wayland_buffer(&wl_buffers[0]);
 901		create_wayland_buffer(&wl_buffers[1]);
 902	}
 903}
 904
 905static void xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
 906{
 907	if (current_system) {
 908		current_system->request_exit(current_system);
 909	} else {
 910		exit(0);
 911	}
 912}
 913
 914static const struct xdg_toplevel_listener xdg_toplevel_listener = {
 915	.configure = xdg_toplevel_configure,
 916	.close = xdg_toplevel_close
 917};
 918
 919static void wl_keyboard_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size)
 920{
 921	close(fd);
 922}
 923
 924static void wl_keyboard_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
 925{
 926}
 927
 928static void wl_keyboard_leave(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface)
 929{
 930}
 931
 932static void wl_keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
 933{
 934	if (key >= 128) {
 935		return;
 936	}
 937	if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
 938		handle_keydown(sym_map[key], scancode_map[key]);
 939	} else {
 940		handle_keyup(sym_map[key], scancode_map[key]);
 941	}
 942}
 943
 944static void wl_keyboard_modifiers(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
 945{
 946}
 947
 948static void wl_keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, int32_t rate, int32_t delay)
 949{
 950}
 951
 952static const struct wl_keyboard_listener wl_keyboard_listener = {
 953	.keymap = wl_keyboard_keymap,
 954	.enter = wl_keyboard_enter,
 955	.leave = wl_keyboard_leave,
 956	.key = wl_keyboard_key,
 957	.modifiers = wl_keyboard_modifiers,
 958	.repeat_info = wl_keyboard_repeat_info
 959};
 960
 961static void wl_pointer_enter(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y)
 962{
 963	wl_pointer_x = wl_fixed_to_int(surface_x);
 964	wl_pointer_y = wl_fixed_to_int(surface_y);
 965	handle_mouse_moved(0, wl_pointer_x, wl_pointer_y, 0, 0);
 966}
 967
 968static void wl_pointer_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface)
 969{
 970}
 971
 972static void wl_pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
 973{
 974	int32_t x = wl_fixed_to_int(surface_x);
 975	int32_t y = wl_fixed_to_int(surface_y);
 976	handle_mouse_moved(0, x, y, x - wl_pointer_x, y - wl_pointer_y);
 977	wl_pointer_x = x;
 978	wl_pointer_y = y;
 979}
 980
 981static void wl_pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
 982{
 983	if (button < BTN_MOUSE || button >= BTN_JOYSTICK) {
 984		return;
 985	}
 986	if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
 987		handle_mousedown(0, button - BTN_LEFT);
 988	} else {
 989		handle_mouseup(0, button - BTN_LEFT);
 990	}
 991}
 992
 993static void wl_pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value)
 994{
 995}
 996
 997static const struct wl_pointer_listener wl_pointer_listener = {
 998	.enter = wl_pointer_enter,
 999	.leave = wl_pointer_leave,
1000	.motion = wl_pointer_motion,
1001	.button = wl_pointer_button,
1002	.axis = wl_pointer_axis
1003};
1004
1005static void seat_capabilities(void *data, struct wl_seat *seat, uint32_t capabilities)
1006{
1007	if ((capabilities & WL_SEAT_CAPABILITY_KEYBOARD) && !wl_keyboard_handle) {
1008		wl_keyboard_handle = wl_seat_get_keyboard(seat);
1009		wl_keyboard_add_listener(wl_keyboard_handle, &wl_keyboard_listener, NULL);
1010	} else if (!(capabilities & WL_SEAT_CAPABILITY_KEYBOARD) && wl_keyboard_handle) {
1011		wl_keyboard_destroy(wl_keyboard_handle);
1012		wl_keyboard_handle = NULL;
1013	}
1014	if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && !wl_pointer_handle) {
1015		wl_pointer_handle = wl_seat_get_pointer(seat);
1016		wl_pointer_add_listener(wl_pointer_handle, &wl_pointer_listener, NULL);
1017	} else if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) && wl_pointer_handle) {
1018		wl_pointer_destroy(wl_pointer_handle);
1019		wl_pointer_handle = NULL;
1020	}
1021}
1022
1023static void seat_name(void *data, struct wl_seat *seat, const char *name)
1024{
1025}
1026
1027static const struct wl_seat_listener wl_seat_listener = {
1028	.capabilities = seat_capabilities,
1029	.name = seat_name
1030};
1031
1032static void registry_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
1033{
1034	if (!strcmp(interface, wl_compositor_interface.name)) {
1035		wl_compositor_handle = wl_registry_bind(registry, name, &wl_compositor_interface, version < 4 ? version : 4);
1036	} else if (!strcmp(interface, wl_shm_interface.name)) {
1037		wl_shm_handle = wl_registry_bind(registry, name, &wl_shm_interface, 1);
1038	} else if (!strcmp(interface, wl_seat_interface.name)) {
1039		wl_seat_handle = wl_registry_bind(registry, name, &wl_seat_interface, 1);
1040		wl_seat_add_listener(wl_seat_handle, &wl_seat_listener, NULL);
1041	} else if (!strcmp(interface, xdg_wm_base_interface.name)) {
1042		xdg_wm_base_handle = wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
1043		xdg_wm_base_add_listener(xdg_wm_base_handle, &xdg_wm_base_listener, NULL);
1044	}
1045}
1046
1047static void registry_global_remove(void *data, struct wl_registry *registry, uint32_t name)
1048{
1049}
1050
1051static const struct wl_registry_listener registry_listener = {
1052	.global = registry_global,
1053	.global_remove = registry_global_remove
1054};
1055
1056static void create_wayland_buffer(struct wayland_buffer *buf)
1057{
1058	size_t size = wl_stride * main_height;
1059	int fd = create_shm_file(size);
1060	if (fd < 0) {
1061		fatal_error("Failed to create Wayland shared memory file\n");
1062	}
1063	buf->pixels = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1064	if (buf->pixels == MAP_FAILED) {
1065		close(fd);
1066		fatal_error("Failed to mmap Wayland shared memory buffer\n");
1067	}
1068	struct wl_shm_pool *pool = wl_shm_create_pool(wl_shm_handle, fd, size);
1069	buf->buffer = wl_shm_pool_create_buffer(pool, 0, main_width, main_height, wl_stride, WL_SHM_FORMAT_XRGB8888);
1070	wl_buffer_add_listener(buf->buffer, &wl_buffer_listener, buf);
1071	wl_shm_pool_destroy(pool);
1072	close(fd);
1073}
1074
1075static void destroy_wayland_buffer(struct wayland_buffer *buf)
1076{
1077	size_t size = wl_stride * main_height;
1078	if (buf->buffer) {
1079		wl_buffer_destroy(buf->buffer);
1080		buf->buffer = NULL;
1081	}
1082	if (buf->pixels) {
1083		munmap(buf->pixels, size);
1084		buf->pixels = NULL;
1085	}
1086	buf->busy = 0;
1087}
1088
1089static void destroy_wayland(void)
1090{
1091	destroy_wayland_buffer(&wl_buffers[0]);
1092	destroy_wayland_buffer(&wl_buffers[1]);
1093	if (xdg_toplevel_handle) {
1094		xdg_toplevel_destroy(xdg_toplevel_handle);
1095		xdg_toplevel_handle = NULL;
1096	}
1097	if (xdg_surface_handle) {
1098		xdg_surface_destroy(xdg_surface_handle);
1099		xdg_surface_handle = NULL;
1100	}
1101	if (frame_callback) {
1102		wl_callback_destroy(frame_callback);
1103		frame_callback = NULL;
1104		frame_pending = 0;
1105	}
1106	if (wl_surface_handle) {
1107		wl_surface_destroy(wl_surface_handle);
1108		wl_surface_handle = NULL;
1109	}
1110	if (wl_keyboard_handle) {
1111		wl_keyboard_destroy(wl_keyboard_handle);
1112		wl_keyboard_handle = NULL;
1113	}
1114	if (wl_pointer_handle) {
1115		wl_pointer_destroy(wl_pointer_handle);
1116		wl_pointer_handle = NULL;
1117	}
1118	if (wl_seat_handle) {
1119		wl_seat_destroy(wl_seat_handle);
1120		wl_seat_handle = NULL;
1121	}
1122	if (xdg_wm_base_handle) {
1123		xdg_wm_base_destroy(xdg_wm_base_handle);
1124		xdg_wm_base_handle = NULL;
1125	}
1126	if (wl_shm_handle) {
1127		wl_shm_destroy(wl_shm_handle);
1128		wl_shm_handle = NULL;
1129	}
1130	if (wl_compositor_handle) {
1131		wl_compositor_destroy(wl_compositor_handle);
1132		wl_compositor_handle = NULL;
1133	}
1134	if (wl_display_handle) {
1135		wl_display_disconnect(wl_display_handle);
1136		wl_display_handle = NULL;
1137	}
1138	wl_configured = 0;
1139}
1140
1141static uint32_t mix_pixel(uint32_t last, uint32_t cur, float ratio)
1142{
1143	float a,b,c,d;
1144	a = (last & 255) * ratio;
1145	b = (last >> 8 & 255) * ratio;
1146	c = (last >> 16 & 255) * ratio;
1147	d = (last >> 24 & 255) * ratio;
1148	ratio = 1.0f - ratio;
1149	a += (cur & 255) * ratio;
1150	b += (cur >> 8 & 255) * ratio;
1151	c += (cur >> 16 & 255) * ratio;
1152	d += (cur >> 24 & 255) * ratio;
1153	return ((int)d) << 24 | ((int)c) << 16 | ((int)b) << 8 | ((int)a);
1154}
1155static void do_buffer_copy(void)
1156{
1157	while (frame_pending && wl_display_handle)
1158	{
1159		wl_display_dispatch(wl_display_handle);
1160	}
1161	struct wayland_buffer *target = &wl_buffers[wl_cur_buffer];
1162	if (target->busy) {
1163		target = &wl_buffers[wl_cur_buffer ^ 1];
1164		while (target->busy && wl_display_handle)
1165		{
1166			wl_display_dispatch(wl_display_handle);
1167		}
1168	}
1169	wl_cur_buffer = target == &wl_buffers[0] ? 1 : 0;
1170	uint32_t *pixels = target->pixels;
1171	uint32_t width_multiple = main_width / last_width_scale;
1172	uint32_t height_multiple = main_height / last_height_scale;
1173	uint32_t multiple = width_multiple < height_multiple ? width_multiple : height_multiple;
1174	if (max_multiple && multiple > max_multiple) {
1175		multiple = max_multiple;
1176	}
1177	height_multiple = last_height_scale * multiple / last_height;
1178	uint32_t *cur_line = pixels + (main_width - last_width_scale * multiple)/2;
1179	cur_line += wl_stride * (main_height - last_height_scale * multiple) / (2 * sizeof(uint32_t));
1180	uint32_t *src_line = copy_buffer;
1181	memset(pixels, 0, wl_stride * main_height);
1182	if (height_multiple * last_height == multiple * last_height_scale) {
1183		if (last_width == last_width_scale) {
1184			for (uint32_t y = 0; y < last_height; y++)
1185			{
1186				for (uint32_t i = 0; i < height_multiple; i++)
1187				{
1188					uint32_t *cur = cur_line;
1189					uint32_t *src = src_line;
1190					for (uint32_t x = 0; x < last_width	; x++)
1191					{
1192						uint32_t pixel = *(src++);
1193						for (uint32_t j = 0; j < multiple; j++)
1194						{
1195							*(cur++) = pixel;
1196						}
1197					}
1198					
1199					cur_line += wl_stride / sizeof(uint32_t);
1200				}
1201				src_line += LINEBUF_SIZE;
1202			}
1203		} else {
1204			float scale_multiple = ((float)(last_width_scale * multiple)) / (float)last_width;
1205			float remaining = 0.0f;
1206			uint32_t last_pixel = 0;
1207			for (uint32_t y = 0; y < last_height; y++)
1208			{
1209				for (uint32_t i = 0; i < height_multiple; i++)
1210				{
1211					uint32_t *cur = cur_line;
1212					uint32_t *src = src_line;
1213					for (uint32_t x = 0; x < last_width	; x++)
1214					{
1215						uint32_t pixel = *(src++);
1216						float count = scale_multiple;
1217						if (remaining > 0.0f) {
1218							*(cur++) = mix_pixel(last_pixel, pixel, remaining);
1219							count -= 1.0f - remaining;
1220						}
1221						for (; count >= 1; count -= 1.0f)
1222						{
1223							*(cur++) = pixel;
1224						}
1225						remaining = count;
1226						last_pixel = pixel;
1227					}
1228					
1229					cur_line += wl_stride / sizeof(uint32_t);
1230				}
1231				src_line += LINEBUF_SIZE;
1232			}
1233		}
1234	} else {
1235		float height_scale = ((float)(last_height_scale * multiple)) / (float)last_height;
1236		float height_remaining = 0.0f;
1237		uint32_t *last_line;
1238		if (last_width == last_width_scale) {
1239			for (uint32_t y = 0; y < last_height; y++)
1240			{
1241				float hcount = height_scale;
1242				if (height_remaining > 0.0f) {
1243					uint32_t *cur = cur_line;
1244					uint32_t *src = src_line;
1245					uint32_t *last = last_line;
1246					for (uint32_t x = 0; x < last_width	; x++)
1247					{
1248						uint32_t mixed = mix_pixel(*(last++), *(src++), height_remaining);
1249						for (uint32_t j = 0; j < multiple; j++)
1250						{
1251							*(cur++) = mixed;
1252						}
1253					}
1254					hcount -= 1.0f - height_remaining;
1255					cur_line += wl_stride / sizeof(uint32_t);
1256				}
1257				for(; hcount >= 1; hcount -= 1.0f)
1258				{
1259					uint32_t *cur = cur_line;
1260					uint32_t *src = src_line;
1261					for (uint32_t x = 0; x < last_width	; x++)
1262					{
1263						uint32_t pixel = *(src++);
1264						for (uint32_t j = 0; j < multiple; j++)
1265						{
1266							*(cur++) = pixel;
1267						}
1268					}
1269					
1270					cur_line += wl_stride / sizeof(uint32_t);
1271				}
1272				height_remaining = hcount;
1273				last_line = src_line;
1274				src_line += LINEBUF_SIZE;
1275			}
1276		} else {
1277			float scale_multiple = ((float)(last_width_scale * multiple)) / (float)last_width;
1278			float remaining = 0.0f;
1279			uint32_t last_pixel = 0;
1280			for (uint32_t y = 0; y < last_height; y++)
1281			{
1282				float hcount = height_scale;
1283				if (height_remaining > 0.0f) {
1284					uint32_t *cur = cur_line;
1285					uint32_t *src = src_line;
1286					uint32_t *last = last_line;
1287					
1288					for (uint32_t x = 0; x < last_width; x++)
1289					{
1290						uint32_t pixel = mix_pixel(*(last++), *(src++), height_remaining);
1291						float count = scale_multiple;
1292						if (remaining > 0.0f) {
1293							*(cur++) = mix_pixel(last_pixel, pixel, remaining);
1294							count -= 1.0f - remaining;
1295						}
1296						for (; count >= 1.0f; count -= 1.0f)
1297						{
1298							*(cur++) = pixel;
1299						}
1300						remaining = count;
1301						last_pixel = pixel;
1302					}
1303					hcount -= 1.0f - height_remaining;
1304					cur_line += wl_stride / sizeof(uint32_t);
1305				}
1306				
1307				for (; hcount >= 1.0f; hcount -= 1.0f)
1308				{
1309					uint32_t *cur = cur_line;
1310					uint32_t *src = src_line;
1311					for (uint32_t x = 0; x < last_width	; x++)
1312					{
1313						uint32_t pixel = *(src++);
1314						float count = scale_multiple;
1315						if (remaining > 0.0f) {
1316							*(cur++) = mix_pixel(last_pixel, pixel, remaining);
1317							count -= 1.0f - remaining;
1318						}
1319						for (; count >= 1; count -= 1.0f)
1320						{
1321							*(cur++) = pixel;
1322						}
1323						remaining = count;
1324						last_pixel = pixel;
1325					}
1326					
1327					cur_line += wl_stride / sizeof(uint32_t);
1328				}
1329				height_remaining = hcount;
1330				last_line = src_line;
1331				src_line += LINEBUF_SIZE;
1332			}
1333		}
1334	}
1335	wl_surface_attach(wl_surface_handle, target->buffer, 0, 0);
1336	wl_surface_damage(wl_surface_handle, 0, 0, main_width, main_height);
1337	frame_callback = wl_surface_frame(wl_surface_handle);
1338	wl_callback_add_listener(frame_callback, &frame_listener, NULL);
1339	frame_pending = 1;
1340	wl_surface_commit(wl_surface_handle);
1341	target->busy = 1;
1342	wl_display_flush(wl_display_handle);
1343}
1344
1345void window_setup(void)
1346{
1347	tern_val def = {.ptrval = "audio"};
1348	tern_node *video = tern_find_node(config, "video");
1349	if (video)
1350	{
1351		for (int i = 0; i < NUM_VID_STD; i++)
1352		{
1353			tern_node *std_settings = tern_find_node(video, vid_std_names[i]);
1354			if (std_settings) {
1355				char *val = tern_find_path_default(std_settings, "overscan\0top\0", (tern_val){.ptrval = NULL}, TVAL_PTR).ptrval;
1356				if (val) {
1357					overscan_top[i] = atoi(val);
1358				}
1359				val = tern_find_path_default(std_settings, "overscan\0bottom\0", (tern_val){.ptrval = NULL}, TVAL_PTR).ptrval;
1360				if (val) {
1361					overscan_bot[i] = atoi(val);
1362				}
1363				val = tern_find_path_default(std_settings, "overscan\0left\0", (tern_val){.ptrval = NULL}, TVAL_PTR).ptrval;
1364				if (val) {
1365					overscan_left[i] = atoi(val);
1366				}
1367				val = tern_find_path_default(std_settings, "overscan\0right\0", (tern_val){.ptrval = NULL}, TVAL_PTR).ptrval;
1368				if (val) {
1369					overscan_right[i] = atoi(val);
1370				}
1371			}
1372		}
1373	}
1374	wl_display_handle = wl_display_connect(NULL);
1375	if (!wl_display_handle) {
1376		fatal_error("Failed to connect to Wayland display\n");
1377	}
1378	struct wl_registry *registry = wl_display_get_registry(wl_display_handle);
1379	wl_registry_add_listener(registry, &registry_listener, NULL);
1380	wl_display_roundtrip(wl_display_handle);
1381	if (!wl_compositor_handle || !wl_shm_handle || !xdg_wm_base_handle) {
1382		fatal_error("Wayland compositor is missing wl_compositor, wl_shm or xdg_wm_base support\n");
1383	}
1384	wl_display_roundtrip(wl_display_handle);
1385	wl_surface_handle = wl_compositor_create_surface(wl_compositor_handle);
1386	xdg_surface_handle = xdg_wm_base_get_xdg_surface(xdg_wm_base_handle, wl_surface_handle);
1387	xdg_surface_add_listener(xdg_surface_handle, &xdg_surface_listener, NULL);
1388	xdg_toplevel_handle = xdg_surface_get_toplevel(xdg_surface_handle);
1389	xdg_toplevel_add_listener(xdg_toplevel_handle, &xdg_toplevel_listener, NULL);
1390	if (caption) {
1391		xdg_toplevel_set_title(xdg_toplevel_handle, caption);
1392	}
1393	wl_surface_commit(wl_surface_handle);
1394	while (!wl_configured && wl_display_dispatch(wl_display_handle) != -1)
1395	{
1396	}
1397	wl_stride = main_width * sizeof(uint32_t);
1398	create_wayland_buffer(&wl_buffers[0]);
1399	create_wayland_buffer(&wl_buffers[1]);
1400	printf("Wayland shm window: %d x %d\n", main_width, main_height);
1401
1402	def.ptrval = "0";
1403	max_multiple = atoi(tern_find_path_default(config, "video\0wayland\0max_multiple\0", def, TVAL_PTR).ptrval);
1404	
1405}
1406
1407void restore_tty(void)
1408{
1409	ioctl(STDIN_FILENO, KDSETMODE, KD_TEXT);
1410	for (int i = 0; i < cur_devices; i++)
1411	{
1412		if (device_types[i] == DEV_KEYBOARD) {
1413			ioctl(device_fds[i], EVIOCGRAB, 0);
1414		}
1415	}
1416}
1417
1418static void init_evdev(void)
1419{
1420	tern_val def = {.ptrval = "off"};
1421	if (strcmp(tern_find_path_default(config, "video\0wayland\0evdev\0", def, TVAL_PTR).ptrval, "on")) {
1422		return;
1423	}
1424	DIR *d = opendir("/dev/input");
1425	if (!d) {
1426		warning("Failed to open /dev/input for reading: %s\n", strerror(errno));
1427		return;
1428	}
1429	struct dirent* entry;
1430	int joystick_counter = 0;
1431	while ((entry = readdir(d)) && cur_devices < MAX_DEVICES)
1432	{
1433		if (!strncmp("event", entry->d_name, strlen("event"))) {
1434			char *filename = alloc_concat("/dev/input/", entry->d_name);
1435			int fd = open(filename, O_RDONLY);
1436			if (fd == -1) {
1437				int errnum = errno;
1438				warning("Failed to open evdev device %s for reading: %s\n", filename, strerror(errnum));
1439				free(filename);
1440				continue;
1441			}
1442			
1443			unsigned long bits;
1444			if (-1 == ioctl(fd, EVIOCGBIT(0, sizeof(bits)), &bits)) {
1445				int errnum = errno;
1446				warning("Failed get capability bits from evdev device %s: %s\n", filename, strerror(errnum));
1447				free(filename);
1448				close(fd);
1449				continue;
1450			}
1451			if (!(1 & bits >> EV_KEY)) {
1452				free(filename);
1453				close(fd);
1454				continue;
1455			}
1456			unsigned long button_bits[(BTN_THUMBR+8*sizeof(long))/(8*sizeof(long))];
1457			int res = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(button_bits)), button_bits);
1458			if (-1 == res) {
1459				int errnum = errno;
1460				warning("Failed get capability bits from evdev device %s: %s\n", filename, strerror(errnum));
1461				free(filename);
1462				close(fd);
1463				continue;
1464			}
1465			int to_check[] = {KEY_ENTER, BTN_MOUSE, BTN_GAMEPAD};
1466			device_type dtype = DEV_NONE;
1467			for (int i = 0; i < 3; i++)
1468			{
1469				if (1 & button_bits[to_check[i]/(8*sizeof(button_bits[0]))] >> to_check[i]%(8*sizeof(button_bits[0]))) {
1470					dtype = i + 1;
1471				}
1472			}
1473			if (dtype == DEV_NONE) {
1474				close(fd);
1475			} else {
1476				device_fds[cur_devices] = fd;
1477				device_types[cur_devices] = dtype;
1478				char name[1024];
1479				char *names[] = {"Keyboard", "Mouse", "Gamepad"};
1480				ioctl(fd, EVIOCGNAME(sizeof(name)), name);
1481				printf("%s is a %s\n%s\n", filename, names[dtype - 1], name);
1482				
1483				if (dtype == DEV_GAMEPAD) {
1484					handle_joy_added(joystick_counter++);
1485				} else if (dtype == DEV_KEYBOARD && isatty(STDIN_FILENO)) {
1486					ioctl(fd, EVIOCGRAB, 1);
1487				}
1488				
1489				fcntl(fd, F_SETFL, O_NONBLOCK);
1490				cur_devices++;
1491			}
1492			free(filename);
1493		}
1494	}
1495	closedir(d);
1496}
1497
1498void render_init(int width, int height, char * title)
1499{
1500	if (height <= 0) {
1501		float aspect = config_aspect() > 0.0f ? config_aspect() : 4.0f/3.0f;
1502		height = ((float)width / aspect) + 0.5f;
1503	}
1504	printf("width: %d, height: %d\n", width, height);
1505	main_width = width;
1506	main_height = height;
1507	
1508	caption = title;
1509	
1510	if (isatty(STDIN_FILENO)) {
1511		ioctl(STDIN_FILENO, KDSETMODE, KD_GRAPHICS);
1512		atexit(restore_tty);
1513	}
1514	
1515	window_setup();
1516	
1517	init_audio();
1518	
1519	render_set_video_standard(VID_NTSC);
1520	init_evdev();
1521
1522	atexit(render_quit);
1523}
1524static void update_source(audio_source *src, double rc, uint8_t sync_changed)
1525{
1526	double alpha = src->dt / (src->dt + rc);
1527	int32_t lowpass_alpha = (int32_t)(((double)0x10000) * alpha);
1528	src->lowpass_alpha = lowpass_alpha;
1529}
1530
1531void render_config_updated(void)
1532{
1533	
1534	destroy_wayland();
1535	drain_events();
1536	
1537	window_setup();
1538
1539	render_close_audio();
1540	init_audio();
1541	render_set_video_standard(video_standard);
1542	
1543	double lowpass_cutoff = get_lowpass_cutoff(config);
1544	double rc = (1.0 / lowpass_cutoff) / (2.0 * M_PI);
1545	for (uint8_t i = 0; i < num_audio_sources; i++)
1546	{
1547		update_source(audio_sources[i], rc, 0);
1548	}
1549	for (uint8_t i = 0; i < num_inactive_audio_sources; i++)
1550	{
1551		update_source(inactive_audio_sources[i], rc, 0);
1552	}
1553	drain_events();
1554}
1555
1556void render_set_video_standard(vid_std std)
1557{
1558	video_standard = std;
1559}
1560
1561void render_update_caption(char *title)
1562{
1563	caption = title;
1564	if (xdg_toplevel_handle) {
1565		xdg_toplevel_set_title(xdg_toplevel_handle, title);
1566	}
1567	free(fps_caption);
1568	fps_caption = NULL;
1569}
1570
1571static char *screenshot_path;
1572void render_save_screenshot(char *path)
1573{
1574	if (screenshot_path) {
1575		free(screenshot_path);
1576	}
1577	screenshot_path = path;
1578}
1579
1580uint8_t render_create_window(char *caption, uint32_t width, uint32_t height, window_close_handler close_handler)
1581{
1582	//no op
1583	return 0;
1584}
1585
1586void render_destroy_window(uint8_t which)
1587{
1588	//no op
1589}
1590
1591static uint8_t last_video_buffer;
1592static uint32_t video_buffer_offset;
1593uint32_t *render_get_video_buffer(uint8_t which, int *pitch)
1594{
1595	if (last_video_buffer != which) {
1596		*pitch = LINEBUF_SIZE * sizeof(uint32_t) * 2;
1597		return video_buffer + video_buffer_offset + (which == VIDEO_BUFFER_EVEN ? LINEBUF_SIZE : 0);
1598	}
1599	*pitch = LINEBUF_SIZE * sizeof(uint32_t);
1600	return video_buffer + video_buffer_offset;
1601}
1602
1603uint8_t events_processed;
1604#define FPS_INTERVAL 1000
1605
1606void render_video_buffer_updated(uint8_t which, int width)
1607{
1608	uint32_t height = which <= VIDEO_BUFFER_EVEN 
1609		? (video_standard == VID_NTSC ? 243 : 294) - (overscan_top[video_standard] + overscan_bot[video_standard])
1610		: 240;
1611	width -= overscan_left[video_standard] + overscan_right[video_standard];
1612	last_width = width;
1613	last_width_scale = LINEBUF_SIZE - (overscan_left[video_standard] + overscan_right[video_standard]);
1614	last_height = last_height_scale = height;
1615	copy_buffer = video_buffer + video_buffer_offset + overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard];
1616	if (which != last_video_buffer) {
1617		last_height *= 2;
1618		copy_buffer += LINEBUF_SIZE * overscan_top[video_standard];
1619		uint32_t *src = video_buffer + (video_buffer_offset ? 0 : LINEBUF_SIZE * MAX_VIDEO_BUFFER_LINES) + overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard] + LINEBUF_SIZE * overscan_top[video_standard];
1620		uint32_t *dst = copy_buffer;
1621		if (which == VIDEO_BUFFER_ODD) {
1622			src += LINEBUF_SIZE;
1623			dst += LINEBUF_SIZE;
1624		}
1625		for (int i = 0; i < height; i++)
1626		{
1627			memcpy(dst, src, width * sizeof(uint32_t));
1628			src += LINEBUF_SIZE * 2;
1629			dst += LINEBUF_SIZE * 2;
1630		}
1631		video_buffer_offset = video_buffer_offset ? 0 : LINEBUF_SIZE * MAX_VIDEO_BUFFER_LINES;
1632	}
1633	do_buffer_copy();
1634	last_video_buffer = which;
1635	if (!events_processed) {
1636		process_events();
1637	}
1638	events_processed = 0;
1639}
1640
1641uint32_t render_emulated_width()
1642{
1643	return last_width - overscan_left[video_standard] - overscan_right[video_standard];
1644}
1645
1646uint32_t render_emulated_height()
1647{
1648	return (video_standard == VID_NTSC ? 243 : 294) - overscan_top[video_standard] - overscan_bot[video_standard];
1649}
1650
1651uint32_t render_overscan_left()
1652{
1653	return overscan_left[video_standard];
1654}
1655
1656uint32_t render_overscan_top()
1657{
1658	return overscan_top[video_standard];
1659}
1660
1661void render_wait_quit(vdp_context * context)
1662{
1663	for(;;)
1664	{
1665		drain_events();
1666		sleep(1);
1667	}
1668}
1669
1670int render_lookup_button(char *name)
1671{
1672	static tern_node *button_lookup;
1673	if (!button_lookup) {
1674		//xbox names
1675		button_lookup = tern_insert_int(button_lookup, "a", BTN_SOUTH);
1676		button_lookup = tern_insert_int(button_lookup, "b", BTN_EAST);
1677		button_lookup = tern_insert_int(button_lookup, "x", BTN_WEST);
1678		button_lookup = tern_insert_int(button_lookup, "y", BTN_NORTH);
1679		button_lookup = tern_insert_int(button_lookup, "back", BTN_SELECT);
1680		button_lookup = tern_insert_int(button_lookup, "start", BTN_START);
1681		button_lookup = tern_insert_int(button_lookup, "guid", BTN_MODE);
1682		button_lookup = tern_insert_int(button_lookup, "leftshoulder", BTN_TL);
1683		button_lookup = tern_insert_int(button_lookup, "rightshoulder", BTN_TR);
1684		button_lookup = tern_insert_int(button_lookup, "leftstick", BTN_THUMBL);
1685		button_lookup = tern_insert_int(button_lookup, "rightstick", BTN_THUMBR);
1686		//ps names
1687		button_lookup = tern_insert_int(button_lookup, "cross", BTN_SOUTH);
1688		button_lookup = tern_insert_int(button_lookup, "circle", BTN_EAST);
1689		button_lookup = tern_insert_int(button_lookup, "square", BTN_WEST);
1690		button_lookup = tern_insert_int(button_lookup, "triangle", BTN_NORTH);
1691		button_lookup = tern_insert_int(button_lookup, "share", BTN_SELECT);
1692		button_lookup = tern_insert_int(button_lookup, "select", BTN_SELECT);
1693		button_lookup = tern_insert_int(button_lookup, "options", BTN_START);
1694		button_lookup = tern_insert_int(button_lookup, "l1", BTN_TL);
1695		button_lookup = tern_insert_int(button_lookup, "r1", BTN_TR);
1696		button_lookup = tern_insert_int(button_lookup, "l3", BTN_THUMBL);
1697		button_lookup = tern_insert_int(button_lookup, "r3", BTN_THUMBR);
1698	}
1699	return (int)tern_find_int(button_lookup, name, KEY_CNT);
1700}
1701
1702int render_lookup_axis(char *name)
1703{
1704	static tern_node *axis_lookup;
1705	if (!axis_lookup) {
1706		//xbox names
1707		axis_lookup = tern_insert_int(axis_lookup, "leftx", ABS_X);
1708		axis_lookup = tern_insert_int(axis_lookup, "lefty", ABS_Y);
1709		axis_lookup = tern_insert_int(axis_lookup, "lefttrigger", ABS_Z);
1710		axis_lookup = tern_insert_int(axis_lookup, "rightx", ABS_RX);
1711		axis_lookup = tern_insert_int(axis_lookup, "righty", ABS_RY);
1712		axis_lookup = tern_insert_int(axis_lookup, "righttrigger", ABS_RZ);
1713		//ps names
1714		axis_lookup = tern_insert_int(axis_lookup, "l2", ABS_Z);
1715		axis_lookup = tern_insert_int(axis_lookup, "r2", ABS_RZ);
1716	}
1717	return (int)tern_find_int(axis_lookup, name, ABS_CNT);
1718}
1719
1720int32_t render_translate_input_name(int32_t controller, char *name, uint8_t is_axis)
1721{
1722	if (is_axis) {
1723		int axis = render_lookup_axis(name);
1724		if (axis == ABS_CNT) {
1725			return RENDER_INVALID_NAME;
1726		}
1727		return RENDER_AXIS_BIT | axis;
1728	} else {
1729		int button = render_lookup_button(name);
1730		if (button != KEY_CNT) {
1731			return button;
1732		}
1733		if (!strcmp("dpup", name)) {
1734			return RENDER_DPAD_BIT | 1;
1735		}
1736		if (!strcmp("dpdown", name)) {
1737			return RENDER_DPAD_BIT | 4;
1738		}
1739		if (!strcmp("dpdleft", name)) {
1740			return RENDER_DPAD_BIT | 8;
1741		}
1742		if (!strcmp("dpright", name)) {
1743			return RENDER_DPAD_BIT | 2;
1744		}
1745		return RENDER_INVALID_NAME;
1746	}
1747}
1748
1749int32_t render_dpad_part(int32_t input)
1750{
1751	return input >> 4 & 0xFFFFFF;
1752}
1753
1754uint8_t render_direction_part(int32_t input)
1755{
1756	return input & 0xF;
1757}
1758
1759int32_t render_axis_part(int32_t input)
1760{
1761	return input & 0xFFFFFFF;
1762}
1763
1764void process_events()
1765{
1766	if (events_processed > MAX_EVENT_POLL_PER_FRAME) {
1767		return;
1768	}
1769	if (wl_display_handle) {
1770		dispatch_wayland_pending(0);
1771	}
1772	drain_events();
1773	events_processed++;
1774}
1775
1776uint32_t render_audio_buffer()
1777{
1778	return buffer_samples;
1779}
1780
1781uint32_t render_sample_rate()
1782{
1783	return sample_rate;
1784}
1785
1786void render_errorbox(char *title, char *message)
1787{
1788	
1789}
1790
1791void render_warnbox(char *title, char *message)
1792{
1793	
1794}
1795
1796void render_infobox(char *title, char *message)
1797{
1798	
1799}
1800
1801uint8_t render_get_active_video_buffer(void)
1802{
1803	return VIDEO_BUFFER_ODD;
1804}