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
|
||||
|
||||
# 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)
|
||||
# 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.."
|
||||
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.
|
||||
*/
|
||||
|
||||
typedef signed int Sint32;
|
||||
|
||||
#define SAMPLE_FREQUENCY 44100
|
||||
|
||||
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);
|
||||
void mouse_down(Device *d, Uint8 mask);
|
||||
void mouse_up(Device *d, Uint8 mask);
|
||||
void mouse_pos(Device *d, Uint16 x, Uint16 y);
|
||||
void mouse_scroll(Device *d, Uint16 x, Uint16 y);
|
32
src/uxn11.c
32
src/uxn11.c
|
@ -13,8 +13,10 @@
|
|||
#include "devices/system.h"
|
||||
#include "devices/screen.h"
|
||||
#include "devices/controller.h"
|
||||
#include "devices/mouse.h"
|
||||
#include "devices/datetime.h"
|
||||
|
||||
static Device *devctrl;
|
||||
static Device *devscreen, *devctrl, *devmouse;
|
||||
|
||||
static int
|
||||
error(char *msg, const char *err)
|
||||
|
@ -79,6 +81,8 @@ redraw(Display *display, Visual *visual, Window window)
|
|||
|
||||
/* /usr/include/X11/keysymdef.h */
|
||||
|
||||
#define XK_Escape 0xff1b
|
||||
|
||||
#define XK_Left 0xff51
|
||||
#define XK_Up 0xff52
|
||||
#define XK_Right 0xff53
|
||||
|
@ -100,6 +104,7 @@ processEvent(Display *display, Visual *visual, Window window)
|
|||
break;
|
||||
case KeyPress: {
|
||||
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_Down)) controller_down(devctrl, 0x20);
|
||||
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_Home)) controller_up(devctrl, 0x08);
|
||||
} break;
|
||||
case ButtonPress:
|
||||
exit(0);
|
||||
case ButtonPress: {
|
||||
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) {
|
||||
redraw(display, visual, window);
|
||||
|
@ -135,17 +151,17 @@ start(Uxn *u)
|
|||
return error("Boot", "Failed");
|
||||
/* system */ uxn_port(u, 0x0, system_dei, system_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, 0x4, 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, 0x7, 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);
|
||||
/* 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, 0xe, nil_dei, nil_deo);
|
||||
/* empty */ uxn_port(u, 0xf, nil_dei, nil_deo);
|
||||
|
@ -177,10 +193,12 @@ main(int argc, char **argv)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
XSelectInput(display, window, ButtonPressMask | ExposureMask | KeyPressMask | KeyReleaseMask);
|
||||
XSelectInput(display, window, ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask | KeyPressMask | KeyReleaseMask);
|
||||
XMapWindow(display, window);
|
||||
while(1) {
|
||||
processEvent(display, visual, window);
|
||||
uxn_eval(&u, GETVECTOR(devscreen));
|
||||
/* sleep(0.01); */
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue