Implemented mouse
This commit is contained in:
parent
f494421979
commit
a1ade4ce45
4
build.sh
4
build.sh
|
@ -9,10 +9,10 @@ echo "Building.."
|
||||||
mkdir -p bin
|
mkdir -p bin
|
||||||
|
|
||||||
# Build(debug)
|
# Build(debug)
|
||||||
gcc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined src/uxn.c src/devices/system.c src/devices/screen.c src/devices/controller.c src/uxn11.c -o bin/uxn11 -lX11
|
gcc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined src/uxn.c src/devices/system.c src/devices/screen.c src/devices/controller.c src/devices/mouse.c src/devices/datetime.c src/uxn11.c -o bin/uxn11 -lX11
|
||||||
|
|
||||||
# Build(release)
|
# Build(release)
|
||||||
# gcc src/uxn.c src/devices/system.c src/devices/screen.c src/devices/controller.c src/uxn11.c -o bin/uxn11 -lX11
|
# gcc src/uxn.c src/devices/system.c src/devices/screen.c src/devices/controller.c src/devices/mouse.c src/devices/datetime.c src/uxn11.c -o bin/uxn11 -lX11
|
||||||
|
|
||||||
echo "Running.."
|
echo "Running.."
|
||||||
bin/uxn11 etc/controller.rom
|
bin/uxn11 etc/controller.rom
|
||||||
|
|
Binary file not shown.
|
@ -1,97 +0,0 @@
|
||||||
#include "../uxn.h"
|
|
||||||
#include "apu.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright (c) 2021 Devine Lu Linvega
|
|
||||||
Copyright (c) 2021 Andrew Alderwick
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define NOTE_PERIOD (SAMPLE_FREQUENCY * 0x4000 / 11025)
|
|
||||||
#define ADSR_STEP (SAMPLE_FREQUENCY / 0xf)
|
|
||||||
|
|
||||||
/* clang-format off */
|
|
||||||
|
|
||||||
static Uint32 advances[12] = {
|
|
||||||
0x80000, 0x879c8, 0x8facd, 0x9837f, 0xa1451, 0xaadc1,
|
|
||||||
0xb504f, 0xbfc88, 0xcb2ff, 0xd7450, 0xe411f, 0xf1a1c
|
|
||||||
};
|
|
||||||
|
|
||||||
/* clang-format on */
|
|
||||||
|
|
||||||
static Sint32
|
|
||||||
envelope(Apu *c, Uint32 age)
|
|
||||||
{
|
|
||||||
if(!c->r) return 0x0888;
|
|
||||||
if(age < c->a) return 0x0888 * age / c->a;
|
|
||||||
if(age < c->d) return 0x0444 * (2 * c->d - c->a - age) / (c->d - c->a);
|
|
||||||
if(age < c->s) return 0x0444;
|
|
||||||
if(age < c->r) return 0x0444 * (c->r - age) / (c->r - c->s);
|
|
||||||
c->advance = 0;
|
|
||||||
return 0x0000;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
apu_render(Apu *c, Sint16 *sample, Sint16 *end)
|
|
||||||
{
|
|
||||||
Sint32 s;
|
|
||||||
if(!c->advance || !c->period) return 0;
|
|
||||||
while(sample < end) {
|
|
||||||
c->count += c->advance;
|
|
||||||
c->i += c->count / c->period;
|
|
||||||
c->count %= c->period;
|
|
||||||
if(c->i >= c->len) {
|
|
||||||
if(!c->repeat) {
|
|
||||||
c->advance = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
c->i %= c->len;
|
|
||||||
}
|
|
||||||
s = (Sint8)(c->addr[c->i] + 0x80) * envelope(c, c->age++);
|
|
||||||
*sample++ += s * c->volume[0] / 0x180;
|
|
||||||
*sample++ += s * c->volume[1] / 0x180;
|
|
||||||
}
|
|
||||||
if(!c->advance) apu_finished_handler(c);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
apu_start(Apu *c, Uint16 adsr, Uint8 pitch)
|
|
||||||
{
|
|
||||||
if(pitch < 108 && c->len)
|
|
||||||
c->advance = advances[pitch % 12] >> (8 - pitch / 12);
|
|
||||||
else {
|
|
||||||
c->advance = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
c->a = ADSR_STEP * (adsr >> 12);
|
|
||||||
c->d = ADSR_STEP * (adsr >> 8 & 0xf) + c->a;
|
|
||||||
c->s = ADSR_STEP * (adsr >> 4 & 0xf) + c->d;
|
|
||||||
c->r = ADSR_STEP * (adsr >> 0 & 0xf) + c->s;
|
|
||||||
c->age = 0;
|
|
||||||
c->i = 0;
|
|
||||||
if(c->len <= 0x100) /* single cycle mode */
|
|
||||||
c->period = NOTE_PERIOD * 337 / 2 / c->len;
|
|
||||||
else /* sample repeat mode */
|
|
||||||
c->period = NOTE_PERIOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
Uint8
|
|
||||||
apu_get_vu(Apu *c)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
Sint32 sum[2] = {0, 0};
|
|
||||||
if(!c->advance || !c->period) return 0;
|
|
||||||
for(i = 0; i < 2; ++i) {
|
|
||||||
if(!c->volume[i]) continue;
|
|
||||||
sum[i] = 1 + envelope(c, c->age) * c->volume[i] / 0x800;
|
|
||||||
if(sum[i] > 0xf) sum[i] = 0xf;
|
|
||||||
}
|
|
||||||
return (sum[0] << 4) | sum[1];
|
|
||||||
}
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
#include "../uxn.h"
|
||||||
|
#include "mouse.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (c) 2021 Devine Lu Linvega
|
||||||
|
Copyright (c) 2021 Andrew Alderwick
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
mouse_down(Device *d, Uint8 mask)
|
||||||
|
{
|
||||||
|
d->dat[6] |= mask;
|
||||||
|
uxn_eval(d->u, GETVECTOR(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mouse_up(Device *d, Uint8 mask)
|
||||||
|
{
|
||||||
|
d->dat[6] &= (~mask);
|
||||||
|
uxn_eval(d->u, GETVECTOR(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mouse_pos(Device *d, Uint16 x, Uint16 y)
|
||||||
|
{
|
||||||
|
DEVPOKE16(0x2, x);
|
||||||
|
DEVPOKE16(0x4, y);
|
||||||
|
uxn_eval(d->u, GETVECTOR(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mouse_scroll(Device *d, Uint16 x, Uint16 y)
|
||||||
|
{
|
||||||
|
DEVPOKE16(0xa, x);
|
||||||
|
DEVPOKE16(0xc, -y);
|
||||||
|
uxn_eval(d->u, GETVECTOR(d));
|
||||||
|
DEVPOKE16(0xa, 0);
|
||||||
|
DEVPOKE16(0xc, 0);
|
||||||
|
}
|
|
@ -10,19 +10,7 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
WITH REGARD TO THIS SOFTWARE.
|
WITH REGARD TO THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef signed int Sint32;
|
void mouse_down(Device *d, Uint8 mask);
|
||||||
|
void mouse_up(Device *d, Uint8 mask);
|
||||||
#define SAMPLE_FREQUENCY 44100
|
void mouse_pos(Device *d, Uint16 x, Uint16 y);
|
||||||
|
void mouse_scroll(Device *d, Uint16 x, Uint16 y);
|
||||||
typedef struct {
|
|
||||||
Uint8 *addr;
|
|
||||||
Uint32 count, advance, period, age, a, d, s, r;
|
|
||||||
Uint16 i, len;
|
|
||||||
Sint8 volume[2];
|
|
||||||
Uint8 pitch, repeat;
|
|
||||||
} Apu;
|
|
||||||
|
|
||||||
int apu_render(Apu *c, Sint16 *sample, Sint16 *end);
|
|
||||||
void apu_start(Apu *c, Uint16 adsr, Uint8 pitch);
|
|
||||||
Uint8 apu_get_vu(Apu *c);
|
|
||||||
void apu_finished_handler(Apu *c);
|
|
32
src/uxn11.c
32
src/uxn11.c
|
@ -13,8 +13,10 @@
|
||||||
#include "devices/system.h"
|
#include "devices/system.h"
|
||||||
#include "devices/screen.h"
|
#include "devices/screen.h"
|
||||||
#include "devices/controller.h"
|
#include "devices/controller.h"
|
||||||
|
#include "devices/mouse.h"
|
||||||
|
#include "devices/datetime.h"
|
||||||
|
|
||||||
static Device *devctrl;
|
static Device *devscreen, *devctrl, *devmouse;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
error(char *msg, const char *err)
|
error(char *msg, const char *err)
|
||||||
|
@ -79,6 +81,8 @@ redraw(Display *display, Visual *visual, Window window)
|
||||||
|
|
||||||
/* /usr/include/X11/keysymdef.h */
|
/* /usr/include/X11/keysymdef.h */
|
||||||
|
|
||||||
|
#define XK_Escape 0xff1b
|
||||||
|
|
||||||
#define XK_Left 0xff51
|
#define XK_Left 0xff51
|
||||||
#define XK_Up 0xff52
|
#define XK_Up 0xff52
|
||||||
#define XK_Right 0xff53
|
#define XK_Right 0xff53
|
||||||
|
@ -100,6 +104,7 @@ processEvent(Display *display, Visual *visual, Window window)
|
||||||
break;
|
break;
|
||||||
case KeyPress: {
|
case KeyPress: {
|
||||||
XKeyPressedEvent *e = (XKeyPressedEvent *)&ev;
|
XKeyPressedEvent *e = (XKeyPressedEvent *)&ev;
|
||||||
|
if(e->keycode == XKeysymToKeycode(display, XK_Escape)) exit(0);
|
||||||
if(e->keycode == XKeysymToKeycode(display, XK_Up)) controller_down(devctrl, 0x10);
|
if(e->keycode == XKeysymToKeycode(display, XK_Up)) controller_down(devctrl, 0x10);
|
||||||
if(e->keycode == XKeysymToKeycode(display, XK_Down)) controller_down(devctrl, 0x20);
|
if(e->keycode == XKeysymToKeycode(display, XK_Down)) controller_down(devctrl, 0x20);
|
||||||
if(e->keycode == XKeysymToKeycode(display, XK_Left)) controller_down(devctrl, 0x40);
|
if(e->keycode == XKeysymToKeycode(display, XK_Left)) controller_down(devctrl, 0x40);
|
||||||
|
@ -120,8 +125,19 @@ processEvent(Display *display, Visual *visual, Window window)
|
||||||
if(e->keycode == XKeysymToKeycode(display, XK_Shift)) controller_up(devctrl, 0x04);
|
if(e->keycode == XKeysymToKeycode(display, XK_Shift)) controller_up(devctrl, 0x04);
|
||||||
if(e->keycode == XKeysymToKeycode(display, XK_Home)) controller_up(devctrl, 0x08);
|
if(e->keycode == XKeysymToKeycode(display, XK_Home)) controller_up(devctrl, 0x08);
|
||||||
} break;
|
} break;
|
||||||
case ButtonPress:
|
case ButtonPress: {
|
||||||
exit(0);
|
XButtonPressedEvent *e = (XButtonPressedEvent *)&ev;
|
||||||
|
mouse_down(devmouse, e->button);
|
||||||
|
} break;
|
||||||
|
case ButtonRelease: {
|
||||||
|
XButtonPressedEvent *e = (XButtonPressedEvent *)&ev;
|
||||||
|
mouse_up(devmouse, e->button);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MotionNotify: {
|
||||||
|
XMotionEvent *e = (XMotionEvent *)&ev;
|
||||||
|
mouse_pos(devmouse, e->x, e->y);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
if(uxn_screen.fg.changed || uxn_screen.bg.changed) {
|
if(uxn_screen.fg.changed || uxn_screen.bg.changed) {
|
||||||
redraw(display, visual, window);
|
redraw(display, visual, window);
|
||||||
|
@ -135,17 +151,17 @@ start(Uxn *u)
|
||||||
return error("Boot", "Failed");
|
return error("Boot", "Failed");
|
||||||
/* system */ uxn_port(u, 0x0, system_dei, system_deo);
|
/* system */ uxn_port(u, 0x0, system_dei, system_deo);
|
||||||
/* console */ uxn_port(u, 0x1, nil_dei, console_deo);
|
/* console */ uxn_port(u, 0x1, nil_dei, console_deo);
|
||||||
/* screen */ uxn_port(u, 0x2, screen_dei, screen_deo);
|
/* screen */ devscreen = uxn_port(u, 0x2, screen_dei, screen_deo);
|
||||||
/* empty */ uxn_port(u, 0x3, nil_dei, nil_deo);
|
/* empty */ uxn_port(u, 0x3, nil_dei, nil_deo);
|
||||||
/* empty */ uxn_port(u, 0x4, nil_dei, nil_deo);
|
/* empty */ uxn_port(u, 0x4, nil_dei, nil_deo);
|
||||||
/* empty */ uxn_port(u, 0x5, nil_dei, nil_deo);
|
/* empty */ uxn_port(u, 0x5, nil_dei, nil_deo);
|
||||||
/* empty */ uxn_port(u, 0x6, nil_dei, nil_deo);
|
/* empty */ uxn_port(u, 0x6, nil_dei, nil_deo);
|
||||||
/* empty */ uxn_port(u, 0x7, nil_dei, nil_deo);
|
/* empty */ uxn_port(u, 0x7, nil_dei, nil_deo);
|
||||||
/* control */ devctrl = uxn_port(u, 0x8, nil_dei, nil_deo);
|
/* control */ devctrl = uxn_port(u, 0x8, nil_dei, nil_deo);
|
||||||
/* empty */ uxn_port(u, 0x9, nil_dei, nil_deo);
|
/* mouse */ devmouse = uxn_port(u, 0x9, nil_dei, nil_deo);
|
||||||
/* file */ uxn_port(u, 0xa, nil_dei, nil_deo);
|
/* file */ uxn_port(u, 0xa, nil_dei, nil_deo);
|
||||||
/* datetime */ uxn_port(u, 0xb, nil_dei, nil_deo);
|
/* datetime */ uxn_port(u, 0xb, nil_dei, nil_deo);
|
||||||
/* empty */ uxn_port(u, 0xc, nil_dei, nil_deo);
|
/* empty */ uxn_port(u, 0xc, datetime_dei, nil_deo);
|
||||||
/* empty */ uxn_port(u, 0xd, nil_dei, nil_deo);
|
/* empty */ uxn_port(u, 0xd, nil_dei, nil_deo);
|
||||||
/* empty */ uxn_port(u, 0xe, nil_dei, nil_deo);
|
/* empty */ uxn_port(u, 0xe, nil_dei, nil_deo);
|
||||||
/* empty */ uxn_port(u, 0xf, nil_dei, nil_deo);
|
/* empty */ uxn_port(u, 0xf, nil_dei, nil_deo);
|
||||||
|
@ -177,10 +193,12 @@ main(int argc, char **argv)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
XSelectInput(display, window, ButtonPressMask | ExposureMask | KeyPressMask | KeyReleaseMask);
|
XSelectInput(display, window, ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask | KeyPressMask | KeyReleaseMask);
|
||||||
XMapWindow(display, window);
|
XMapWindow(display, window);
|
||||||
while(1) {
|
while(1) {
|
||||||
processEvent(display, visual, window);
|
processEvent(display, visual, window);
|
||||||
|
uxn_eval(&u, GETVECTOR(devscreen));
|
||||||
|
/* sleep(0.01); */
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
Loading…
Reference in New Issue