commit 3c1b49d

Devine Lu Linvega  ·  2025-04-19 17:19:29 +0000 UTC
parent 6169107
Removed device files
16 files changed,  +29, -1228
+0, -234
  1@@ -1,234 +0,0 @@
  2-#undef _POSIX_C_SOURCE
  3-#define _POSIX_C_SOURCE 200112L
  4-
  5-#include <signal.h>
  6-#include <stdio.h>
  7-#include <stdlib.h>
  8-#include <sys/select.h>
  9-#include <sys/wait.h>
 10-#include <unistd.h>
 11-
 12-#ifdef __linux
 13-#include <pty.h>
 14-#include <sys/prctl.h>
 15-#endif
 16-
 17-#ifdef __NetBSD__
 18-#include <sys/ioctl.h>
 19-#include <util.h>
 20-#endif
 21-
 22-#include "../uxn.h"
 23-#include "console.h"
 24-
 25-/*
 26-Copyright (c) 2022-2025 Devine Lu Linvega, Andrew Alderwick
 27-
 28-Permission to use, copy, modify, and distribute this software for any
 29-purpose with or without fee is hereby granted, provided that the above
 30-copyright notice and this permission notice appear in all copies.
 31-
 32-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 33-WITH REGARD TO THIS SOFTWARE.
 34-*/
 35-
 36-/* subprocess support */
 37-static char *fork_args[4] = {"/bin/sh", "-c", "", NULL};
 38-static int child_mode;
 39-static int to_child_fd[2];
 40-static int from_child_fd[2];
 41-static int saved_in;
 42-static int saved_out;
 43-static pid_t child_pid;
 44-
 45-/* child_mode:
 46- * 0x01: writes to child's stdin
 47- * 0x02: reads from child's stdout
 48- * 0x04: reads from child's stderr
 49- * 0x08: kill previous process (if any) but do not start
 50- * (other bits ignored for now )
 51- */
 52-
 53-#define CMD_LIVE 0x15 /* 0x00 not started, 0x01 running, 0xff dead */
 54-#define CMD_EXIT 0x16 /* if dead, exit code of process */
 55-#define CMD_ADDR 0x1c /* address to read command args from */
 56-#define CMD_MODE 0x1e /* mode to execute, 0x00 to 0x07 */
 57-#define CMD_EXEC 0x1f /* write to execute programs, etc */
 58-
 59-/* call after we're sure the process has exited */
 60-static void
 61-clean_after_child(void)
 62-{
 63-	child_pid = 0;
 64-	if(child_mode & 0x01) {
 65-		close(to_child_fd[1]);
 66-		dup2(saved_out, 1);
 67-	}
 68-	if(child_mode & (0x04 | 0x02)) {
 69-		close(from_child_fd[0]);
 70-		dup2(saved_in, 0);
 71-	}
 72-	child_mode = 0;
 73-	saved_in = -1;
 74-	saved_out = -1;
 75-}
 76-
 77-static void
 78-start_fork_pipe(void)
 79-{
 80-	pid_t pid;
 81-	pid_t parent_pid = getpid();
 82-	int addr = PEEK2(&uxn.dev[CMD_ADDR]);
 83-	fflush(stdout);
 84-	if(child_mode & 0x08) {
 85-		uxn.dev[CMD_EXIT] = uxn.dev[CMD_LIVE] = 0x00;
 86-		return;
 87-	}
 88-	if(child_mode & 0x01) {
 89-		/* parent writes to child's stdin */
 90-		if(pipe(to_child_fd) == -1) {
 91-			uxn.dev[CMD_EXIT] = uxn.dev[CMD_LIVE] = 0xff;
 92-			fprintf(stderr, "pipe error: to child\n");
 93-			return;
 94-		}
 95-	}
 96-	if(child_mode & (0x04 | 0x02)) {
 97-		/* parent reads from child's stdout and/or stderr */
 98-		if(pipe(from_child_fd) == -1) {
 99-			uxn.dev[CMD_EXIT] = uxn.dev[CMD_LIVE] = 0xff;
100-			fprintf(stderr, "pipe error: from child\n");
101-			return;
102-		}
103-	}
104-
105-	fork_args[2] = (char *)&uxn.ram[addr];
106-	pid = fork();
107-	if(pid < 0) { /* failure */
108-		uxn.dev[CMD_EXIT] = uxn.dev[CMD_LIVE] = 0xff;
109-		fprintf(stderr, "fork failure\n");
110-	} else if(pid == 0) { /* child */
111-
112-#ifdef __linux__
113-		int r = prctl(PR_SET_PDEATHSIG, SIGTERM);
114-		if(r == -1) {
115-			perror(0);
116-			exit(6);
117-		}
118-		if(getppid() != parent_pid) exit(13);
119-#endif
120-
121-		if(child_mode & 0x01) {
122-			dup2(to_child_fd[0], 0);
123-			close(to_child_fd[1]);
124-		}
125-		if(child_mode & (0x04 | 0x02)) {
126-			if(child_mode & 0x02) dup2(from_child_fd[1], 1);
127-			if(child_mode & 0x04) dup2(from_child_fd[1], 2);
128-			close(from_child_fd[0]);
129-		}
130-		fflush(stdout);
131-		execvp(fork_args[0], fork_args);
132-		exit(1);
133-	} else { /*parent*/
134-		child_pid = pid;
135-		uxn.dev[CMD_LIVE] = 0x01;
136-		uxn.dev[CMD_EXIT] = 0x00;
137-		if(child_mode & 0x01) {
138-			saved_out = dup(1);
139-			dup2(to_child_fd[1], 1);
140-			close(to_child_fd[0]);
141-		}
142-		if(child_mode & (0x04 | 0x02)) {
143-			saved_in = dup(0);
144-			dup2(from_child_fd[0], 0);
145-			close(from_child_fd[1]);
146-		}
147-	}
148-}
149-
150-static void
151-check_child(void)
152-{
153-	int wstatus;
154-	if(child_pid) {
155-		if(waitpid(child_pid, &wstatus, WNOHANG)) {
156-			uxn.dev[CMD_LIVE] = 0xff;
157-			uxn.dev[CMD_EXIT] = WEXITSTATUS(wstatus);
158-			clean_after_child();
159-		} else {
160-			uxn.dev[CMD_LIVE] = 0x01;
161-			uxn.dev[CMD_EXIT] = 0x00;
162-		}
163-	}
164-}
165-
166-static void
167-kill_child(void)
168-{
169-	int wstatus;
170-	if(child_pid) {
171-		kill(child_pid, 9);
172-		if(waitpid(child_pid, &wstatus, WNOHANG)) {
173-			uxn.dev[CMD_LIVE] = 0xff;
174-			uxn.dev[CMD_EXIT] = WEXITSTATUS(wstatus);
175-			clean_after_child();
176-		}
177-	}
178-}
179-
180-static void
181-start_fork(void)
182-{
183-	fflush(stderr);
184-	kill_child();
185-	child_mode = uxn.dev[CMD_MODE];
186-	start_fork_pipe();
187-}
188-
189-void
190-close_console(void)
191-{
192-	kill_child();
193-}
194-
195-int
196-console_input(int c, int type)
197-{
198-	if(c == EOF) c = 0, type = 4;
199-	uxn.dev[0x12] = c, uxn.dev[0x17] = type;
200-	uxn_eval(console_vector);
201-	return type != 4;
202-}
203-
204-void
205-console_arguments(int i, int argc, char **argv)
206-{
207-	for(; i < argc; i++) {
208-		char *p = argv[i];
209-		while(*p)
210-			console_input(*p++, CONSOLE_ARG);
211-		console_input('\n', i == argc - 1 ? CONSOLE_END : CONSOLE_EOA);
212-	}
213-}
214-
215-Uint8
216-console_dei(Uint8 addr)
217-{
218-	switch(addr) {
219-	case CMD_LIVE:
220-	case CMD_EXIT: check_child(); break;
221-	}
222-	return uxn.dev[addr];
223-}
224-
225-void
226-console_deo(Uint8 addr)
227-{
228-	FILE *fd;
229-	switch(addr) {
230-	case 0x11: console_vector = PEEK2(&uxn.dev[0x10]); return;
231-	case 0x18: fd = stdout, fputc(uxn.dev[0x18], fd), fflush(fd); break;
232-	case 0x19: fd = stderr, fputc(uxn.dev[0x19], fd), fflush(fd); break;
233-	case CMD_EXEC: start_fork(); break;
234-	}
235-}
+0, -24
 1@@ -1,24 +0,0 @@
 2-/*
 3-Copyright (c) 2021-2025 Devine Lu Linvega, Andrew Alderwick
 4-
 5-Permission to use, copy, modify, and distribute this software for any
 6-purpose with or without fee is hereby granted, provided that the above
 7-copyright notice and this permission notice appear in all copies.
 8-
 9-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10-WITH REGARD TO THIS SOFTWARE.
11-*/
12-
13-#define CONSOLE_STD 0x1
14-#define CONSOLE_ARG 0x2
15-#define CONSOLE_EOA 0x3
16-#define CONSOLE_END 0x4
17-
18-void close_console(void);
19-
20-int console_input(int c, int type);
21-void console_arguments(int i, int argc, char **argv);
22-Uint8 console_dei(Uint8 addr);
23-void console_deo(Uint8 addr);
24-
25-extern int console_vector;
+0, -51
 1@@ -1,51 +0,0 @@
 2-#include "../uxn.h"
 3-#include "controller.h"
 4-
 5-/*
 6-Copyright (c) 2021-2023 Devine Lu Linvega, Andrew Alderwick
 7-
 8-Permission to use, copy, modify, and distribute this software for any
 9-purpose with or without fee is hereby granted, provided that the above
10-copyright notice and this permission notice appear in all copies.
11-
12-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13-WITH REGARD TO THIS SOFTWARE.
14-*/
15-
16-static int controller_vector;
17-
18-void
19-controller_down(Uint8 mask)
20-{
21-	if(mask) {
22-		uxn.dev[0x82] |= mask;
23-		uxn_eval(controller_vector);
24-	}
25-}
26-
27-void
28-controller_up(Uint8 mask)
29-{
30-	if(mask) {
31-		uxn.dev[0x82] &= (~mask);
32-		uxn_eval(controller_vector);
33-	}
34-}
35-
36-void
37-controller_key(Uint8 key)
38-{
39-	if(key) {
40-		uxn.dev[0x83] = key;
41-		uxn_eval(controller_vector);
42-		uxn.dev[0x83] = 0;
43-	}
44-}
45-
46-void
47-controller_deo(Uint8 addr)
48-{
49-	switch(addr) {
50-	case 0x81: controller_vector = PEEK2(&uxn.dev[0x80]); break;
51-	}
52-}
+0, -16
 1@@ -1,16 +0,0 @@
 2-/*
 3-Copyright (c) 2021 Devine Lu Linvega, Andrew Alderwick
 4-
 5-Permission to use, copy, modify, and distribute this software for any
 6-purpose with or without fee is hereby granted, provided that the above
 7-copyright notice and this permission notice appear in all copies.
 8-
 9-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10-WITH REGARD TO THIS SOFTWARE.
11-*/
12-
13-void controller_down(Uint8 mask);
14-void controller_up(Uint8 mask);
15-void controller_key(Uint8 key);
16-
17-void controller_deo(Uint8 addr);
+0, -39
 1@@ -1,39 +0,0 @@
 2-#include <time.h>
 3-
 4-#include "../uxn.h"
 5-#include "datetime.h"
 6-
 7-/*
 8-Copyright (c) 2021-2023 Devine Lu Linvega, Andrew Alderwick
 9-
10-Permission to use, copy, modify, and distribute this software for any
11-purpose with or without fee is hereby granted, provided that the above
12-copyright notice and this permission notice appear in all copies.
13-
14-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15-WITH REGARD TO THIS SOFTWARE.
16-*/
17-
18-Uint8
19-datetime_dei(Uint8 addr)
20-{
21-	time_t seconds = time(NULL);
22-	struct tm zt = {0};
23-	struct tm *t = localtime(&seconds);
24-	if(t == NULL)
25-		t = &zt;
26-	switch(addr) {
27-	case 0xc0: return (t->tm_year + 1900) >> 8;
28-	case 0xc1: return (t->tm_year + 1900);
29-	case 0xc2: return t->tm_mon;
30-	case 0xc3: return t->tm_mday;
31-	case 0xc4: return t->tm_hour;
32-	case 0xc5: return t->tm_min;
33-	case 0xc6: return t->tm_sec;
34-	case 0xc7: return t->tm_wday;
35-	case 0xc8: return t->tm_yday >> 8;
36-	case 0xc9: return t->tm_yday;
37-	case 0xca: return t->tm_isdst;
38-	default: return uxn.dev[addr];
39-	}
40-}
+0, -12
 1@@ -1,12 +0,0 @@
 2-/*
 3-Copyright (c) 2021 Devine Lu Linvega, Andrew Alderwick
 4-
 5-Permission to use, copy, modify, and distribute this software for any
 6-purpose with or without fee is hereby granted, provided that the above
 7-copyright notice and this permission notice appear in all copies.
 8-
 9-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10-WITH REGARD TO THIS SOFTWARE.
11-*/
12-
13-Uint8 datetime_dei(Uint8 addr);
+0, -272
  1@@ -1,272 +0,0 @@
  2-#include <stdio.h>
  3-#include <stdlib.h>
  4-#include <dirent.h>
  5-#include <sys/stat.h>
  6-#include <unistd.h>
  7-#include <string.h>
  8-
  9-#include "../uxn.h"
 10-#include "file.h"
 11-
 12-#define DIRCHAR '/'
 13-
 14-/*
 15-Copyright (c) 2021-2025 Devine Lu Linvega, Andrew Alderwick
 16-
 17-Permission to use, copy, modify, and distribute this software for any
 18-purpose with or without fee is hereby granted, provided that the above
 19-copyright notice and this permission notice appear in all copies.
 20-
 21-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 22-WITH REGARD TO THIS SOFTWARE.
 23-*/
 24-
 25-typedef struct {
 26-	FILE *f;
 27-	DIR *dir;
 28-	char *filepath;
 29-	enum { IDLE,
 30-		FILE_READ,
 31-		FILE_WRITE,
 32-		DIR_READ,
 33-		DIR_WRITE
 34-	} state;
 35-} UxnFile;
 36-
 37-static UxnFile ufs[2];
 38-static Uint8 dirbuf[0x10000], *_dirbuf = dirbuf;
 39-
 40-static void
 41-make_pathfile(char *pathbuf, const char *filepath, const char *basename)
 42-{
 43-	char c = DIRCHAR;
 44-	while(*filepath)
 45-		c = *filepath++, *pathbuf = c, pathbuf++;
 46-	if(c != DIRCHAR)
 47-		*pathbuf = DIRCHAR, pathbuf++;
 48-	while(*basename)
 49-		*pathbuf = *basename++, pathbuf++;
 50-	*pathbuf = 0;
 51-}
 52-
 53-static int
 54-put_fill(Uint8 *dest, int len, char c)
 55-{
 56-	int i;
 57-	for(i = 0; i < len; i++)
 58-		*dest = c, dest++;
 59-	return len;
 60-}
 61-
 62-static int
 63-put_size(Uint8 *dest, int len, int size)
 64-{
 65-	int i;
 66-	for(i = 0, dest += len; i < len; i++, size >>= 4)
 67-		*(--dest) = "0123456789abcdef"[(Uint8)(size & 0xf)];
 68-	return len;
 69-}
 70-
 71-static int
 72-put_text(Uint8 *dest, const char *text)
 73-{
 74-	Uint8 *anchor = dest;
 75-	while(*text)
 76-		*dest = *text++, dest++;
 77-	*dest = 0;
 78-	return dest - anchor;
 79-}
 80-
 81-static int
 82-put_stat(Uint8 *dest, int len, int size, int err, int dir, int capsize)
 83-{
 84-	if(err) return put_fill(dest, len, '!');
 85-	if(dir) return put_fill(dest, len, '-');
 86-	if(capsize && size >= 0x10000) return put_fill(dest, len, '?');
 87-	return put_size(dest, len, size);
 88-}
 89-
 90-static int
 91-put_statfile(Uint8 *dest, const char *filepath, const char *basename)
 92-{
 93-	int err, dir;
 94-	struct stat st;
 95-	Uint8 *anchor = dest;
 96-	char pathbuf[0x2000];
 97-	make_pathfile(pathbuf, filepath, basename);
 98-	err = stat(pathbuf, &st);
 99-	dir = S_ISDIR(st.st_mode);
100-	dest += put_stat(dest, 4, st.st_size, err, dir, 1);
101-	dest += put_text(dest, " ");
102-	dest += put_text(dest, basename);
103-	dest += put_text(dest, dir ? "/\n" : "\n");
104-	return dest - anchor;
105-}
106-
107-static int
108-put_fdir(Uint8 *dest, int len, const char *filepath, DIR *dir)
109-{
110-	int i;
111-	struct dirent *de = readdir(dir);
112-	for(_dirbuf = dirbuf; de != NULL; de = readdir(dir)) {
113-		char *name = de->d_name;
114-		if(name[0] == '.' && (name[1] == '.' || name[1] == '\0'))
115-			continue;
116-		else
117-			_dirbuf += put_statfile(_dirbuf, filepath, name);
118-	}
119-	for(i = 0; i < len && dirbuf[i]; i++)
120-		dest[i] = dirbuf[i];
121-	dest[i] = 0;
122-	return i;
123-}
124-
125-static int
126-is_dir_path(char *p)
127-{
128-	char c;
129-	int saw_slash = 0;
130-	while((c = *p++)) saw_slash = c == DIRCHAR;
131-	return saw_slash;
132-}
133-
134-static int
135-is_dir_real(char *p)
136-{
137-	struct stat st;
138-	return stat(p, &st) == 0 && S_ISDIR(st.st_mode);
139-}
140-
141-static int
142-file_write_dir(char *p)
143-{
144-	int ok = 1;
145-	char c, *s = p;
146-	for(; ok && (c = *p); p++) {
147-		if(c == DIRCHAR) {
148-			*p = '\0';
149-			ok = is_dir_real(s) || (mkdir(s, 0755) == 0);
150-			*p = c;
151-		}
152-	}
153-	return ok;
154-}
155-
156-static void
157-file_reset(int id)
158-{
159-	if(ufs[id].f != NULL) fclose(ufs[id].f), ufs[id].f = NULL;
160-	if(ufs[id].dir != NULL) closedir(ufs[id].dir), ufs[id].dir = NULL;
161-	ufs[id].state = IDLE;
162-}
163-
164-static int
165-file_init(int id, Uint16 addr)
166-{
167-	file_reset(id);
168-	ufs[id].filepath = (char *)&uxn.ram[addr];
169-	return 0;
170-}
171-
172-static int
173-file_not_ready(int id)
174-{
175-	if(ufs[id].filepath == 0) {
176-		fprintf(stderr, "File %d is uninitialized\n", id);
177-		return 1;
178-	} else
179-		return 0;
180-}
181-
182-static int
183-file_read(int id, Uint16 addr, int len)
184-{
185-	void *dest = &uxn.ram[addr];
186-	if(file_not_ready(id))
187-		return 0;
188-	if(ufs[id].state != FILE_READ && ufs[id].state != DIR_READ) {
189-		file_reset(id);
190-		if((ufs[id].dir = opendir(ufs[id].filepath)) != NULL)
191-			ufs[id].state = DIR_READ;
192-		else if((ufs[id].f = fopen(ufs[id].filepath, "rb")) != NULL)
193-			ufs[id].state = FILE_READ;
194-	}
195-	if(ufs[id].state == FILE_READ)
196-		return fread(dest, 1, len, ufs[id].f);
197-	if(ufs[id].state == DIR_READ)
198-		return put_fdir(dest, len, ufs[id].filepath, ufs[id].dir);
199-	return 0;
200-}
201-
202-static int
203-file_write(int id, Uint16 addr, int len, Uint8 flags)
204-{
205-	int ret = 0;
206-	if(file_not_ready(id))
207-		return 0;
208-	file_write_dir(ufs[id].filepath);
209-	if(ufs[id].state != FILE_WRITE && ufs[id].state != DIR_WRITE) {
210-		file_reset(id);
211-		if(is_dir_path(ufs[id].filepath))
212-			ufs[id].state = DIR_WRITE;
213-		else if((ufs[id].f = fopen(ufs[id].filepath, (flags & 0x01) ? "ab" : "wb")) != NULL)
214-			ufs[id].state = FILE_WRITE;
215-	}
216-	if(ufs[id].state == FILE_WRITE)
217-		if((ret = fwrite(&uxn.ram[addr], 1, len, ufs[id].f)) > 0 && fflush(ufs[id].f) != 0)
218-			ret = 0;
219-	if(ufs[id].state == DIR_WRITE)
220-		ret = is_dir_real(ufs[id].filepath);
221-	return ret;
222-}
223-
224-static int
225-file_stat(int id, Uint16 addr, int len)
226-{
227-	int err, dir;
228-	struct stat st;
229-	if(file_not_ready(id))
230-		return 0;
231-	err = stat(ufs[id].filepath, &st);
232-	dir = S_ISDIR(st.st_mode);
233-	return put_stat(&uxn.ram[addr], len, st.st_size, err, dir, 0);
234-}
235-
236-static int
237-file_delete(int id)
238-{
239-	if(file_not_ready(id))
240-		return -1;
241-	return unlink(ufs[id].filepath);
242-}
243-
244-static void
245-file_success(int port, int value)
246-{
247-	POKE2(&uxn.dev[port], value);
248-}
249-
250-/* file registers */
251-
252-static int rL1, rL2;
253-
254-void
255-file_deo(Uint8 port)
256-{
257-	switch(port) {
258-	/* File 1 */
259-	case 0xab: rL1 = PEEK2(&uxn.dev[0xaa]); break;
260-	case 0xa5: file_success(0xa2, file_stat(0, PEEK2(&uxn.dev[0xa4]), rL1)); break;
261-	case 0xa6: file_success(0xa2, file_delete(0)); break;
262-	case 0xa9: file_success(0xa2, file_init(0, PEEK2(&uxn.dev[0xa8]))); break;
263-	case 0xad: file_success(0xa2, file_read(0, PEEK2(&uxn.dev[0xac]), rL1)); break;
264-	case 0xaf: file_success(0xa2, file_write(0, PEEK2(&uxn.dev[0xae]), rL1, uxn.dev[0xa7])); break;
265-	/* File 2 */
266-	case 0xbb: rL2 = PEEK2(&uxn.dev[0xba]); break;
267-	case 0xb5: file_success(0xb2, file_stat(1, PEEK2(&uxn.dev[0xb4]), rL2)); break;
268-	case 0xb6: file_success(0xb2, file_delete(1)); break;
269-	case 0xb9: file_success(0xb2, file_init(1, PEEK2(&uxn.dev[0xb8]))); break;
270-	case 0xbd: file_success(0xb2, file_read(1, PEEK2(&uxn.dev[0xbc]), rL2)); break;
271-	case 0xbf: file_success(0xb2, file_write(1, PEEK2(&uxn.dev[0xbe]), rL2, uxn.dev[0xb7])); break;
272-	}
273-}
+0, -12
 1@@ -1,12 +0,0 @@
 2-/*
 3-Copyright (c) 2021 Devine Lu Linvega, Andrew Alderwick
 4-
 5-Permission to use, copy, modify, and distribute this software for any
 6-purpose with or without fee is hereby granted, provided that the above
 7-copyright notice and this permission notice appear in all copies.
 8-
 9-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10-WITH REGARD TO THIS SOFTWARE.
11-*/
12-
13-void file_deo(Uint8 port);
+0, -56
 1@@ -1,56 +0,0 @@
 2-#include "../uxn.h"
 3-#include "mouse.h"
 4-#include <stdio.h>
 5-
 6-/*
 7-Copyright (c) 2021-2023 Devine Lu Linvega, Andrew Alderwick
 8-
 9-Permission to use, copy, modify, and distribute this software for any
10-purpose with or without fee is hereby granted, provided that the above
11-copyright notice and this permission notice appear in all copies.
12-
13-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14-WITH REGARD TO THIS SOFTWARE.
15-*/
16-
17-static int mouse_vector;
18-
19-void
20-mouse_down(Uint8 mask)
21-{
22-	uxn.dev[0x96] |= mask;
23-	uxn_eval(mouse_vector);
24-}
25-
26-void
27-mouse_up(Uint8 mask)
28-{
29-	uxn.dev[0x96] &= (~mask);
30-	uxn_eval(mouse_vector);
31-}
32-
33-void
34-mouse_pos(Uint16 x, Uint16 y)
35-{
36-	uxn.dev[0x92] = x >> 8, uxn.dev[0x93] = x;
37-	uxn.dev[0x94] = y >> 8, uxn.dev[0x95] = y;
38-	uxn_eval(mouse_vector);
39-}
40-
41-void
42-mouse_scroll(Uint16 x, Uint16 y)
43-{
44-	uxn.dev[0x9a] = x >> 8, uxn.dev[0x9b] = x;
45-	uxn.dev[0x9c] = -y >> 8, uxn.dev[0x9d] = -y;
46-	uxn_eval(mouse_vector);
47-	uxn.dev[0x9a] = 0, uxn.dev[0x9b] = 0;
48-	uxn.dev[0x9c] = 0, uxn.dev[0x9d] = 0;
49-}
50-
51-void
52-mouse_deo(Uint8 addr)
53-{
54-	switch(addr) {
55-	case 0x91: mouse_vector = PEEK2(&uxn.dev[0x90]); break;
56-	}
57-}
+0, -17
 1@@ -1,17 +0,0 @@
 2-/*
 3-Copyright (c) 2021 Devine Lu Linvega, Andrew Alderwick
 4-
 5-Permission to use, copy, modify, and distribute this software for any
 6-purpose with or without fee is hereby granted, provided that the above
 7-copyright notice and this permission notice appear in all copies.
 8-
 9-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10-WITH REGARD TO THIS SOFTWARE.
11-*/
12-
13-void mouse_down(Uint8 mask);
14-void mouse_up(Uint8 mask);
15-void mouse_pos(Uint16 x, Uint16 y);
16-void mouse_scroll(Uint16 x, Uint16 y);
17-
18-void mouse_deo(Uint8 addr);
+0, -230
  1@@ -1,230 +0,0 @@
  2-#include <stdlib.h>
  3-#include <string.h>
  4-
  5-#include "../uxn.h"
  6-#include "screen.h"
  7-
  8-/*
  9-Copyright (c) 2021-2025 Devine Lu Linvega, Andrew Alderwick
 10-
 11-Permission to use, copy, modify, and distribute this software for any
 12-purpose with or without fee is hereby granted, provided that the above
 13-copyright notice and this permission notice appear in all copies.
 14-
 15-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 16-WITH REGARD TO THIS SOFTWARE.
 17-*/
 18-
 19-UxnScreen uxn_screen;
 20-
 21-#define MAR(x) (x + 0x8)
 22-#define MAR2(x) (x + 0x10)
 23-
 24-/* c = !ch ? (color % 5 ? color >> 2 : 0) : color % 4 + ch == 1 ? 0 : (ch - 2 + (color & 3)) % 3 + 1; */
 25-
 26-static Uint8 blending[4][16] = {
 27-	{0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0},
 28-	{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3},
 29-	{1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1},
 30-	{2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2}};
 31-
 32-int
 33-screen_changed(void)
 34-{
 35-	clamp(uxn_screen.x1, 0, uxn_screen.width);
 36-	clamp(uxn_screen.y1, 0, uxn_screen.height);
 37-	clamp(uxn_screen.x2, 0, uxn_screen.width);
 38-	clamp(uxn_screen.y2, 0, uxn_screen.height);
 39-	return uxn_screen.x2 > uxn_screen.x1 &&
 40-		uxn_screen.y2 > uxn_screen.y1;
 41-}
 42-
 43-void
 44-screen_change(int x1, int y1, int x2, int y2)
 45-{
 46-	if(x1 < uxn_screen.x1) uxn_screen.x1 = x1;
 47-	if(y1 < uxn_screen.y1) uxn_screen.y1 = y1;
 48-	if(x2 > uxn_screen.x2) uxn_screen.x2 = x2;
 49-	if(y2 > uxn_screen.y2) uxn_screen.y2 = y2;
 50-}
 51-
 52-void
 53-screen_palette(void)
 54-{
 55-	int i, shift, colors[4];
 56-	for(i = 0, shift = 4; i < 4; ++i, shift ^= 4) {
 57-		Uint8
 58-			r = (uxn.dev[0x8 + i / 2] >> shift) & 0xf,
 59-			g = (uxn.dev[0xa + i / 2] >> shift) & 0xf,
 60-			b = (uxn.dev[0xc + i / 2] >> shift) & 0xf;
 61-		colors[i] = 0x0f000000 | r << 16 | g << 8 | b;
 62-		colors[i] |= colors[i] << 4;
 63-	}
 64-	for(i = 0; i < 16; i++)
 65-		uxn_screen.palette[i] = colors[(i >> 2) ? (i >> 2) : (i & 3)];
 66-	screen_change(0, 0, uxn_screen.width, uxn_screen.height);
 67-}
 68-
 69-void
 70-screen_apply(int width, int height)
 71-{
 72-	int length;
 73-	clamp(width, 8, 0x800);
 74-	clamp(height, 8, 0x800);
 75-	length = MAR2(width) * MAR2(height);
 76-	uxn_screen.bg = realloc(uxn_screen.bg, length), uxn_screen.fg = realloc(uxn_screen.fg, length);
 77-	memset(uxn_screen.bg, 0, length);
 78-	memset(uxn_screen.fg, 0, length);
 79-	uxn_screen.width = width, uxn_screen.height = height;
 80-	screen_change(0, 0, width, height);
 81-	emu_resize();
 82-}
 83-
 84-void
 85-screen_redraw(void)
 86-{
 87-	int i, x, y, k, l;
 88-	for(y = uxn_screen.y1; y < uxn_screen.y2; y++) {
 89-		int ys = y * uxn_screen.zoom;
 90-		for(x = uxn_screen.x1, i = MAR(x) + MAR(y) * MAR2(uxn_screen.width); x < uxn_screen.x2; x++, i++) {
 91-			int c = uxn_screen.palette[uxn_screen.fg[i] << 2 | uxn_screen.bg[i]];
 92-			for(k = 0; k < uxn_screen.zoom; k++) {
 93-				int oo = ((ys + k) * uxn_screen.width + x) * uxn_screen.zoom;
 94-				for(l = 0; l < uxn_screen.zoom; l++)
 95-					uxn_screen.pixels[oo + l] = c;
 96-			}
 97-		}
 98-	}
 99-	uxn_screen.x1 = uxn_screen.y1 = 9999;
100-	uxn_screen.x2 = uxn_screen.y2 = 0;
101-}
102-
103-/* screen registers */
104-
105-static int rX, rY, rA, rMX, rMY, rMA, rML, rDX, rDY;
106-
107-Uint8
108-screen_dei(Uint8 addr)
109-{
110-	switch(addr) {
111-	case 0x22: return uxn_screen.width >> 8;
112-	case 0x23: return uxn_screen.width;
113-	case 0x24: return uxn_screen.height >> 8;
114-	case 0x25: return uxn_screen.height;
115-	case 0x28: return rX >> 8;
116-	case 0x29: return rX;
117-	case 0x2a: return rY >> 8;
118-	case 0x2b: return rY;
119-	case 0x2c: return rA >> 8;
120-	case 0x2d: return rA;
121-	default: return uxn.dev[addr];
122-	}
123-}
124-
125-void
126-screen_deo(Uint8 addr)
127-{
128-	switch(addr) {
129-	case 0x21: uxn_screen.vector = PEEK2(&uxn.dev[0x20]); return;
130-	case 0x23: screen_apply(PEEK2(&uxn.dev[0x22]), uxn_screen.height); return;
131-	case 0x25: screen_apply(uxn_screen.width, PEEK2(&uxn.dev[0x24])); return;
132-	case 0x26: rMX = uxn.dev[0x26] & 0x1, rMY = uxn.dev[0x26] & 0x2, rMA = uxn.dev[0x26] & 0x4, rML = uxn.dev[0x26] >> 4, rDX = rMX << 3, rDY = rMY << 2; return;
133-	case 0x28:
134-	case 0x29: rX = (uxn.dev[0x28] << 8) | uxn.dev[0x29], rX = twos(rX); return;
135-	case 0x2a:
136-	case 0x2b: rY = (uxn.dev[0x2a] << 8) | uxn.dev[0x2b], rY = twos(rY); return;
137-	case 0x2c:
138-	case 0x2d: rA = (uxn.dev[0x2c] << 8) | uxn.dev[0x2d]; return;
139-	case 0x2e: {
140-		int ctrl = uxn.dev[0x2e];
141-		int color = ctrl & 0x3;
142-		int len = MAR2(uxn_screen.width);
143-		Uint8 *layer = ctrl & 0x40 ? uxn_screen.fg : uxn_screen.bg;
144-		/* fill mode */
145-		if(ctrl & 0x80) {
146-			int x1, y1, x2, y2, ax, bx, ay, by, hor, ver;
147-			if(ctrl & 0x10)
148-				x1 = 0, x2 = rX;
149-			else
150-				x1 = rX, x2 = uxn_screen.width;
151-			if(ctrl & 0x20)
152-				y1 = 0, y2 = rY;
153-			else
154-				y1 = rY, y2 = uxn_screen.height;
155-			screen_change(x1, y1, x2, y2);
156-			x1 = MAR(x1), y1 = MAR(y1);
157-			hor = MAR(x2) - x1, ver = MAR(y2) - y1;
158-			for(ay = y1 * len, by = ay + ver * len; ay < by; ay += len)
159-				for(ax = ay + x1, bx = ax + hor; ax < bx; ax++)
160-					layer[ax] = color;
161-		}
162-		/* pixel mode */
163-		else {
164-			if(rX >= 0 && rY >= 0 && rX < len && rY < uxn_screen.height)
165-				layer[MAR(rX) + MAR(rY) * len] = color;
166-			screen_change(rX, rY, rX + 1, rY + 1);
167-			if(rMX) rX++;
168-			if(rMY) rY++;
169-		}
170-		return;
171-	}
172-	case 0x2f: {
173-		int ctrl = uxn.dev[0x2f];
174-		int blend = ctrl & 0xf, opaque = blend % 5;
175-		int fx = ctrl & 0x10 ? -1 : 1, fy = ctrl & 0x20 ? -1 : 1;
176-		int qfx = fx > 0 ? 7 : 0, qfy = fy < 0 ? 7 : 0;
177-		int dxy = fy * rDX, dyx = fx * rDY;
178-		int wmar = MAR(uxn_screen.width), wmar2 = MAR2(uxn_screen.width);
179-		int hmar2 = MAR2(uxn_screen.height);
180-		int i, x1, x2, y1, y2, ax, ay, qx, qy, x = rX, y = rY;
181-		Uint8 *layer = ctrl & 0x40 ? uxn_screen.fg : uxn_screen.bg;
182-		if(ctrl & 0x80) {
183-			int addr_incr = rMA << 2;
184-			for(i = 0; i <= rML; i++, x += dyx, y += dxy, rA += addr_incr) {
185-				Uint16 xmar = MAR(x), ymar = MAR(y);
186-				Uint16 xmar2 = MAR2(x), ymar2 = MAR2(y);
187-				if(xmar < wmar && ymar2 < hmar2) {
188-					Uint8 *sprite = &uxn.ram[rA];
189-					int by = ymar2 * wmar2;
190-					for(ay = ymar * wmar2, qy = qfy; ay < by; ay += wmar2, qy += fy) {
191-						int ch1 = sprite[qy], ch2 = sprite[qy + 8] << 1, bx = xmar2 + ay;
192-						for(ax = xmar + ay, qx = qfx; ax < bx; ax++, qx -= fx) {
193-							int color = ((ch1 >> qx) & 1) | ((ch2 >> qx) & 2);
194-							if(opaque || color) layer[ax] = blending[color][blend];
195-						}
196-					}
197-				}
198-			}
199-		} else {
200-			int addr_incr = rMA << 1;
201-			for(i = 0; i <= rML; i++, x += dyx, y += dxy, rA += addr_incr) {
202-				Uint16 xmar = MAR(x), ymar = MAR(y);
203-				Uint16 xmar2 = MAR2(x), ymar2 = MAR2(y);
204-				if(xmar < wmar && ymar2 < hmar2) {
205-					Uint8 *sprite = &uxn.ram[rA];
206-					int by = ymar2 * wmar2;
207-					for(ay = ymar * wmar2, qy = qfy; ay < by; ay += wmar2, qy += fy) {
208-						int ch1 = sprite[qy], bx = xmar2 + ay;
209-						for(ax = xmar + ay, qx = qfx; ax < bx; ax++, qx -= fx) {
210-							int color = (ch1 >> qx) & 1;
211-							if(opaque || color) layer[ax] = blending[color][blend];
212-						}
213-					}
214-				}
215-			}
216-		}
217-		if(fx < 0)
218-			x1 = x, x2 = rX;
219-		else
220-			x1 = rX, x2 = x;
221-		if(fy < 0)
222-			y1 = y, y2 = rY;
223-		else
224-			y1 = rY, y2 = y;
225-		screen_change(x1 - 8, y1 - 8, x2 + 8, y2 + 8);
226-		if(rMX) rX += rDX * fx;
227-		if(rMY) rY += rDY * fy;
228-		return;
229-	}
230-	}
231-}
+0, -34
 1@@ -1,34 +0,0 @@
 2-/*
 3-Copyright (c) 2021-2025 Devine Lu Linvega, Andrew Alderwick
 4-
 5-Permission to use, copy, modify, and distribute this software for any
 6-purpose with or without fee is hereby granted, provided that the above
 7-copyright notice and this permission notice appear in all copies.
 8-
 9-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10-WITH REGARD TO THIS SOFTWARE.
11-*/
12-
13-typedef struct UxnScreen {
14-	int width, height, vector, zoom, x1, y1, x2, y2;
15-	Uint32 palette[16], *pixels;
16-	Uint8 *fg, *bg;
17-} UxnScreen;
18-
19-extern UxnScreen uxn_screen;
20-extern void emu_resize(void);
21-void screen_change(int x1, int y1, int x2, int y2);
22-int screen_changed(void);
23-void screen_palette(void);
24-void screen_apply(int width, int height);
25-void screen_redraw(void);
26-
27-Uint8 screen_dei(Uint8 addr);
28-void screen_deo(Uint8 addr);
29-
30-/* clang-format off */
31-
32-#define clamp(v,a,b) { if(v < a) v = a; else if(v >= b) v = b; }
33-#define twos(v) (v & 0x8000 ? (int)v - 0x10000 : (int)v)
34-
35-/* clang-format on */
+0, -122
  1@@ -1,122 +0,0 @@
  2-#include <stdio.h>
  3-
  4-#include "../uxn.h"
  5-#include "system.h"
  6-
  7-/*
  8-Copyright (c) 2022-2025 Devine Lu Linvega, Andrew Alderwick
  9-
 10-Permission to use, copy, modify, and distribute this software for any
 11-purpose with or without fee is hereby granted, provided that the above
 12-copyright notice and this permission notice appear in all copies.
 13-
 14-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 15-WITH REGARD TO THIS SOFTWARE.
 16-*/
 17-
 18-char *boot_path;
 19-
 20-static void
 21-system_print(char *name, Stack *s)
 22-{
 23-	Uint8 i;
 24-	fprintf(stderr, "%s ", name);
 25-	for(i = s->ptr - 8; i != (Uint8)(s->ptr); i++)
 26-		fprintf(stderr, "%02x%c", s->dat[i], i == 0xff ? '|' : ' ');
 27-	fprintf(stderr, "<%02x\n", s->ptr);
 28-}
 29-
 30-static int
 31-system_load(Uint8 *ram, char *rom_path)
 32-{
 33-	FILE *f = fopen(rom_path, "rb");
 34-	if(f) {
 35-		int i = 0, l = fread(ram, 0x10000 - PAGE_PROGRAM, 1, f);
 36-		while(l && ++i < RAM_PAGES)
 37-			l = fread(ram + 0x10000 * i - PAGE_PROGRAM, 0x10000, 1, f);
 38-		fclose(f);
 39-	}
 40-	return !!f;
 41-}
 42-
 43-int
 44-system_error(char *msg, const char *err)
 45-{
 46-	fprintf(stderr, "%s: %s\n", msg, err), fflush(stderr);
 47-	return 0;
 48-}
 49-
 50-int
 51-system_boot(Uint8 *ram, char *rom_path, int has_args)
 52-{
 53-	uxn.ram = ram;
 54-	boot_path = rom_path;
 55-	uxn.dev[0x17] = has_args;
 56-	if(ram && system_load(uxn.ram + PAGE_PROGRAM, rom_path))
 57-		return uxn_eval(PAGE_PROGRAM);
 58-	return 0;
 59-}
 60-
 61-int
 62-system_reboot(int soft)
 63-{
 64-	int i;
 65-	for(i = 0x0; i < 0x100; i++) uxn.dev[i] = 0;
 66-	for(i = soft ? 0x100 : 0; i < 0x10000; i++) uxn.ram[i] = 0;
 67-	uxn.wst.ptr = uxn.rst.ptr = 0;
 68-	return system_boot(uxn.ram, boot_path, 0);
 69-}
 70-
 71-/* IO */
 72-
 73-Uint8
 74-system_dei(Uint8 addr)
 75-{
 76-	switch(addr) {
 77-	case 0x4: return uxn.wst.ptr;
 78-	case 0x5: return uxn.rst.ptr;
 79-	default: return uxn.dev[addr];
 80-	}
 81-}
 82-
 83-void
 84-system_deo(Uint8 port)
 85-{
 86-	switch(port) {
 87-	case 0x3: {
 88-		Uint16 value;
 89-		Uint16 addr = PEEK2(uxn.dev + 2);
 90-		Uint8 *aptr = uxn.ram + addr;
 91-		Uint16 length = PEEK2(aptr + 1);
 92-		if(uxn.ram[addr] == 0x0) {
 93-			unsigned int a = PEEK2(aptr + 3) * 0x10000 + PEEK2(aptr + 5);
 94-			unsigned int b = a + length;
 95-			value = uxn.ram[addr + 7];
 96-			for(; a < b; uxn.ram[a++] = value);
 97-		} else if(uxn.ram[addr] == 0x1) {
 98-			unsigned int a = PEEK2(aptr + 3) * 0x10000 + PEEK2(aptr + 5);
 99-			unsigned int b = a + length;
100-			unsigned int c = PEEK2(aptr + 7) * 0x10000 + PEEK2(aptr + 9);
101-			for(; a < b; uxn.ram[c++] = uxn.ram[a++]);
102-		} else if(uxn.ram[addr] == 0x2) {
103-			unsigned int a = PEEK2(aptr + 3) * 0x10000 + PEEK2(aptr + 5);
104-			unsigned int b = a + length;
105-			unsigned int c = PEEK2(aptr + 7) * 0x10000 + PEEK2(aptr + 9);
106-			unsigned int d = c + length;
107-			for(; b >= a; uxn.ram[--d] = uxn.ram[--b]);
108-		} else
109-			fprintf(stderr, "Unknown Expansion Command 0x%02x\n", uxn.ram[addr]);
110-		break;
111-	}
112-	case 0x4:
113-		uxn.wst.ptr = uxn.dev[4];
114-		break;
115-	case 0x5:
116-		uxn.rst.ptr = uxn.dev[5];
117-		break;
118-	case 0xe:
119-		system_print("WST", &uxn.wst);
120-		system_print("RST", &uxn.rst);
121-		break;
122-	}
123-}
+0, -19
 1@@ -1,19 +0,0 @@
 2-/*
 3-Copyright (c) 2022-2025 Devine Lu Linvega, Andrew Alderwick
 4-
 5-Permission to use, copy, modify, and distribute this software for any
 6-purpose with or without fee is hereby granted, provided that the above
 7-copyright notice and this permission notice appear in all copies.
 8-
 9-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10-WITH REGARD TO THIS SOFTWARE.
11-*/
12-
13-#define RAM_PAGES 0x10
14-
15-int system_error(char *msg, const char *err);
16-int system_boot(Uint8 *ram, char *rom_path, int has_args);
17-int system_reboot(int soft);
18-
19-Uint8 system_dei(Uint8 addr);
20-void system_deo(Uint8 addr);
+0, -41
 1@@ -1,41 +0,0 @@
 2-/*
 3-Copyright (c) 2021 Devine Lu Linvega
 4-
 5-Permission to use, copy, modify, and distribute this software for any
 6-purpose with or without fee is hereby granted, provided that the above
 7-copyright notice and this permission notice appear in all copies.
 8-
 9-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10-WITH REGARD TO THIS SOFTWARE.
11-*/
12-
13-/* clang-format off */
14-
15-#define PEEK2(d) (*(d) << 8 | (d)[1])
16-#define POKE2(d, v) { *(d) = (v) >> 8; (d)[1] = (v); }
17-
18-/* clang-format on */
19-
20-#define STEP_MAX 0x80000000
21-#define PAGE_PROGRAM 0x0100
22-
23-typedef unsigned char Uint8;
24-typedef signed char Sint8;
25-typedef unsigned short Uint16;
26-typedef signed short Sint16;
27-typedef unsigned int Uint32;
28-
29-typedef struct {
30-	Uint8 dat[0x100], ptr;
31-} Stack;
32-
33-typedef struct Uxn {
34-	Uint8 *ram, dev[0x100];
35-	Stack wst, rst;
36-} Uxn;
37-
38-extern Uint8 emu_dei(Uint8 addr);
39-extern void emu_deo( Uint8 addr, Uint8 value);
40-extern Uxn uxn;
41-
42-int uxn_eval(Uint16 pc);
+29, -49
  1@@ -1,6 +1,7 @@
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <unistd.h>
  5+#include <string.h>
  6 
  7 #include <X11/Xlib.h>
  8 #include <X11/Xutil.h>
  9@@ -57,6 +58,8 @@ static Uxn uxn;
 10 
 11 #define PEEK2(d) (*(d) << 8 | (d)[1])
 12 #define POKE2(d, v) { *(d) = (v) >> 8; (d)[1] = (v); }
 13+#define clamp(v,a,b) { if(v < a) v = a; else if(v >= b) v = b; }
 14+#define twos(v) (v & 0x8000 ? (int)v - 0x10000 : (int)v)
 15 
 16 #define OPC(opc, init, body) {\
 17 	case 0x00|opc: {const int _2=0,_r=0;init body;} break;\
 18@@ -424,8 +427,8 @@ start_fork(void)
 19 	start_fork_pipe();
 20 }
 21 
 22-void
 23-close_console(void)
 24+static void
 25+console_close(void)
 26 {
 27 	kill_child();
 28 }
 29@@ -475,47 +478,25 @@ console_deo(Uint8 addr)
 30 /*
 31 @|Screen ------------------------------------------------------------ */
 32 
 33+#define MAR(x) (x + 0x8)
 34+#define MAR2(x) (x + 0x10)
 35+
 36 typedef struct UxnScreen {
 37 	int width, height, vector, zoom, x1, y1, x2, y2;
 38 	Uint32 palette[16], *pixels;
 39 	Uint8 *fg, *bg;
 40 } UxnScreen;
 41 
 42-extern UxnScreen uxn_screen;
 43-extern void emu_resize(void);
 44-void screen_change(int x1, int y1, int x2, int y2);
 45-int screen_changed(void);
 46-void screen_palette(void);
 47-void screen_apply(int width, int height);
 48-void screen_redraw(void);
 49-
 50-Uint8 screen_dei(Uint8 addr);
 51-void screen_deo(Uint8 addr);
 52-
 53-/* clang-format off */
 54-
 55-#define clamp(v,a,b) { if(v < a) v = a; else if(v >= b) v = b; }
 56-#define twos(v) (v & 0x8000 ? (int)v - 0x10000 : (int)v)
 57-
 58-/* clang-format on */
 59-
 60-#include <stdlib.h>
 61-#include <string.h>
 62-
 63-UxnScreen uxn_screen;
 64-
 65-#define MAR(x) (x + 0x8)
 66-#define MAR2(x) (x + 0x10)
 67-
 68-/* c = !ch ? (color % 5 ? color >> 2 : 0) : color % 4 + ch == 1 ? 0 : (ch - 2 + (color & 3)) % 3 + 1; */
 69+void emu_resize(void);
 70 
 71+static UxnScreen uxn_screen;
 72 static Uint8 blending[4][16] = {
 73 	{0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0},
 74 	{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3},
 75 	{1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1},
 76 	{2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2}};
 77 
 78-int
 79+static int
 80 screen_changed(void)
 81 {
 82 	clamp(uxn_screen.x1, 0, uxn_screen.width);
 83@@ -526,7 +507,7 @@ screen_changed(void)
 84 		uxn_screen.y2 > uxn_screen.y1;
 85 }
 86 
 87-void
 88+static void
 89 screen_change(int x1, int y1, int x2, int y2)
 90 {
 91 	if(x1 < uxn_screen.x1) uxn_screen.x1 = x1;
 92@@ -535,7 +516,7 @@ screen_change(int x1, int y1, int x2, int y2)
 93 	if(y2 > uxn_screen.y2) uxn_screen.y2 = y2;
 94 }
 95 
 96-void
 97+static void
 98 screen_palette(void)
 99 {
100 	int i, shift, colors[4];
101@@ -552,7 +533,7 @@ screen_palette(void)
102 	screen_change(0, 0, uxn_screen.width, uxn_screen.height);
103 }
104 
105-void
106+static void
107 screen_apply(int width, int height)
108 {
109 	int length;
110@@ -567,7 +548,7 @@ screen_apply(int width, int height)
111 	emu_resize();
112 }
113 
114-void
115+static void
116 screen_redraw(void)
117 {
118 	int i, x, y, k, l;
119@@ -590,7 +571,7 @@ screen_redraw(void)
120 
121 static int rX, rY, rA, rMX, rMY, rMA, rML, rDX, rDY;
122 
123-Uint8
124+static Uint8
125 screen_dei(Uint8 addr)
126 {
127 	switch(addr) {
128@@ -608,7 +589,7 @@ screen_dei(Uint8 addr)
129 	}
130 }
131 
132-void
133+static void
134 screen_deo(Uint8 addr)
135 {
136 	switch(addr) {
137@@ -721,7 +702,7 @@ screen_deo(Uint8 addr)
138 
139 static int controller_vector;
140 
141-void
142+static void
143 controller_down(Uint8 mask)
144 {
145 	if(mask) {
146@@ -730,7 +711,7 @@ controller_down(Uint8 mask)
147 	}
148 }
149 
150-void
151+static void
152 controller_up(Uint8 mask)
153 {
154 	if(mask) {
155@@ -739,7 +720,7 @@ controller_up(Uint8 mask)
156 	}
157 }
158 
159-void
160+static void
161 controller_key(Uint8 key)
162 {
163 	if(key) {
164@@ -749,7 +730,7 @@ controller_key(Uint8 key)
165 	}
166 }
167 
168-void
169+static void
170 controller_deo(Uint8 addr)
171 {
172 	switch(addr) {
173@@ -762,21 +743,21 @@ controller_deo(Uint8 addr)
174 
175 static int mouse_vector;
176 
177-void
178+static void
179 mouse_down(Uint8 mask)
180 {
181 	uxn.dev[0x96] |= mask;
182 	uxn_eval(mouse_vector);
183 }
184 
185-void
186+static void
187 mouse_up(Uint8 mask)
188 {
189 	uxn.dev[0x96] &= (~mask);
190 	uxn_eval(mouse_vector);
191 }
192 
193-void
194+static void
195 mouse_pos(Uint16 x, Uint16 y)
196 {
197 	uxn.dev[0x92] = x >> 8, uxn.dev[0x93] = x;
198@@ -784,7 +765,7 @@ mouse_pos(Uint16 x, Uint16 y)
199 	uxn_eval(mouse_vector);
200 }
201 
202-void
203+static void
204 mouse_scroll(Uint16 x, Uint16 y)
205 {
206 	uxn.dev[0x9a] = x >> 8, uxn.dev[0x9b] = x;
207@@ -794,7 +775,7 @@ mouse_scroll(Uint16 x, Uint16 y)
208 	uxn.dev[0x9c] = 0, uxn.dev[0x9d] = 0;
209 }
210 
211-void
212+static void
213 mouse_deo(Uint8 addr)
214 {
215 	switch(addr) {
216@@ -807,7 +788,6 @@ mouse_deo(Uint8 addr)
217 
218 #include <dirent.h>
219 #include <sys/stat.h>
220-#include <string.h>
221 
222 typedef struct {
223 	FILE *f;
224@@ -1123,7 +1103,7 @@ emu_deo(Uint8 addr, Uint8 value)
225 	}
226 }
227 
228-void
229+static void
230 emu_repaint(void)
231 {
232 	int x = uxn_screen.x1 * uxn_screen.zoom;
233@@ -1154,7 +1134,7 @@ emu_resize(void)
234 static void
235 emu_restart(int soft)
236 {
237-	close_console();
238+	console_close();
239 	screen_apply(WIDTH, HEIGHT);
240 	system_reboot(soft);
241 }
242@@ -1337,7 +1317,7 @@ main(int argc, char **argv)
243 		return !fprintf(stdout, "Could not load %s.\n", argv[i - 1]);
244 	console_arguments(i, argc, argv);
245 	emu_run();
246-	close_console();
247+	console_close();
248 	XDestroyImage(ximage), XDestroyWindow(display, window), XCloseDisplay(display);
249 	return uxn.dev[0x0f] & 0x7f;
250 }