diff --git a/Tetris/Makefile b/Tetris/Makefile new file mode 100644 index 0000000..0d55640 --- /dev/null +++ b/Tetris/Makefile @@ -0,0 +1,45 @@ +# run `make DEF=...` to add extra defines +PROGRAM := tetris +LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all +LDFLAGS += `pkg-config --libs ncurses` -lusefull_macros +SRCS := $(wildcard *.c) +DEFINES := $(DEF) +# -D_GNU_SOURCE -D_XOPEN_SOURCE=1111 +OBJDIR := mk +CFLAGS += -O2 -Wno-trampolines -std=gnu99 +CFLAGS += `pkg-config --cflags ncurses` +OBJS := $(addprefix $(OBJDIR)/, $(SRCS:%.c=%.o)) +DEPS := $(OBJS:.o=.d) +CC = gcc +#CXX = g++ + + +all : $(OBJDIR) $(PROGRAM) + +debug: CFLAGS += -DEBUG -Werror -Wall -Wextra +debug: all + +$(PROGRAM) : $(OBJS) + @echo -e "\t\tLD $(PROGRAM)" + $(CC) $(LDFLAGS) $(OBJS) -o $(PROGRAM) + +$(OBJDIR): + mkdir $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + +$(OBJDIR)/%.o: %.c + @echo -e "\t\tCC $<" + $(CC) -MD -c $(LDFLAGS) $(CFLAGS) $(DEFINES) -o $@ $< + +clean: + @echo -e "\t\tCLEAN" + @rm -f $(OBJS) $(DEPS) + @rmdir $(OBJDIR) 2>/dev/null || true + +xclean: clean + @rm -f $(PROGRAM) + +.PHONY: clean xclean diff --git a/Tetris/disp.c b/Tetris/disp.c new file mode 100644 index 0000000..02a4166 --- /dev/null +++ b/Tetris/disp.c @@ -0,0 +1,113 @@ +/* + * This file is part of the tetris project. + * Copyright 2020 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "disp.h" + +#define LEFTBRDR 10 + +void initscreen(int *maxx, int *maxy){ + initscr(); + int x, y; + getmaxyx(stdscr, y, x); // getyx - get current coords + cbreak(); + keypad(stdscr, TRUE); // We get F1, F2 etc.. + noecho(); + nodelay(stdscr, TRUE); // getch() returns ERR if no keys pressed + start_color(); + init_pair(1, COLOR_RED, COLOR_BLACK); + init_pair(2, COLOR_GREEN, COLOR_BLACK); + init_pair(3, COLOR_YELLOW, COLOR_BLACK); + init_pair(4, COLOR_BLUE, COLOR_BLACK); + init_pair(5, COLOR_MAGENTA, COLOR_BLACK); + init_pair(6, COLOR_CYAN, COLOR_BLACK); + init_pair(7, COLOR_WHITE, COLOR_BLACK); + clear(); + for(int y = 0; y < ROWS; ++y){ + mvaddch(y, LEFTBRDR-1, '|'); + mvaddch(y, LEFTBRDR+COLS, '|'); + } + for(int x = 0; x < COLS; ++x){ + mvaddch(ROWS, LEFTBRDR+x, '='); + mvaddch(ROWS, LEFTBRDR-1, '\\'); + mvaddch(ROWS, LEFTBRDR+COLS, '/'); + } + //mvaddstr(ROWS+1, 0, "Coords: (0, 0)"); + if(maxx) *maxx = x; + if(maxy) *maxy = y; +} + +void redisplay(){ + for(int x = 0; x < COLS; ++x) + for(int y = 0; y < ROWS; ++y){ + if(cup[y][x]){ + attron(COLOR_PAIR(cup[y][x])|WA_BOLD); + mvaddch(ymax-y, LEFTBRDR+x, '*'); + attroff(COLOR_PAIR(cup[y][x])|WA_BOLD); + }else mvaddch(ymax-y, LEFTBRDR+x, ' '); + } + refresh(); +} + +// return keycode or nothing +keycode getkey(){ + int n = getch(); + keycode k; + switch(n){ + case KEY_F(1): + k = KEY_0; + break; + case KEY_DOWN: + k = KEY_D; + break; + case KEY_UP: + k = KEY_U; + break; + case KEY_LEFT: + k = KEY_L; + break; + case KEY_RIGHT: + k = KEY_R; + break; + case 'q': + k = KEY_Q; + break; + case 'z': + k = KEY_ROTL; + break; + case 'x': + k = KEY_ROTR; + break; + default: + k = KEY_NONE; + } + return k; +} + +void shownext(const figure *F){ + for(int i = 1; i < 6; ++i) + mvprintw(i, 1, " "); + attron(COLOR_PAIR(F->color) | WA_BOLD); + for(int i = 0; i < 4; ++i){ + int xn = 3 + GETX(F->f[i]), yn = 3 + GETY(F->f[i]); + mvaddch(6 - yn, xn, '*'); + } + attroff(COLOR_PAIR(F->color) | WA_BOLD); +} diff --git a/Tetris/disp.h b/Tetris/disp.h new file mode 100644 index 0000000..65ea2e3 --- /dev/null +++ b/Tetris/disp.h @@ -0,0 +1,39 @@ +/* + * This file is part of the tetris project. + * Copyright 2020 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "displaybuf.h" +#define closescreen() endwin() + +typedef enum{ + KEY_NONE, + KEY_L, + KEY_R, + KEY_U, + KEY_D, + KEY_Q, + KEY_0, + KEY_ROTL, + KEY_ROTR +} keycode; + +void initscreen(int *maxx, int *maxy); +void redisplay(); +keycode getkey(); + +void shownext(const figure *F); + diff --git a/Tetris/displaybuf.c b/Tetris/displaybuf.c new file mode 100644 index 0000000..37d2ae7 --- /dev/null +++ b/Tetris/displaybuf.c @@ -0,0 +1,122 @@ +/* + * This file is part of the tetris project. + * Copyright 2020 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +//#include +//#include + +#include +#include "displaybuf.h" + + +uint8_t cup[ROWS][COLS]; // screen array with (0,0) @ left bottom + +// L: 00, 01, 02, 10 + 2 = 0x22, 0x23, 0x24, 0x32 +const figure L = { + .f = {0x22, 0x23, 0x24, 0x32}, + .color = 1 +}; +// J: 00, 01, 02, -10 + 2 = 0x22, 0x23, 0x24, 0x12 +const figure J = { + .f = {0x22, 0x23, 0x24, 0x12}, + .color = 2 +}; +// O: 00, 01, 10, 11 + 2 = 0x22, 0x23, 0x32, 0x33 +const figure O = { + .f = {0x22, 0x23, 0x32, 0x33}, + .color = 3 +}; + +// I: 0-1,00, 01, 02 + 2 = 0x21, 0x22, 0x23, 0x24 +const figure I = { + .f = {0x21, 0x22, 0x23, 0x24}, + .color = 4 +}; + +// chk if figure can be put to (x,y); @return 1 if empty +int chkfigure(int x, int y, const figure *F){ + if(x < 0 || x > xmax){ + return 0; + } + if(y < 0){ + return 0; + } + for(int i = 0; i < 4; ++i){ + int xn = x + GETX(F->f[i]), yn = y + GETY(F->f[i]); + if(yn > ymax){ + continue; // invisible + } + if(xn < 0 || xn > xmax || yn < 0){ + return 0; // border + } + if(cup[yn][xn]){ + return 0; // occupied + } + } + return 1; +} + +// clear figure from old location +void clearfigure(int x, int y, const figure *F){ + for(int i = 0; i < 4; ++i){ + int xn = x + GETX(F->f[i]), yn = y + GETY(F->f[i]); + if(xn < 0 || xn > xmax || yn < 0 || yn > ymax) continue; // out of cup + cup[yn][xn] = 0; + } +} + +// put figure into new location +void putfigure(int x, int y, const figure *F){ + for(int i = 0; i < 4; ++i){ + int xn = x + GETX(F->f[i]), yn = y + GETY(F->f[i]); + if(xn < 0 || xn > xmax || yn < 0 || yn > ymax) continue; // out of cup + cup[yn][xn] = F->color; + } +} + +// dir=0 - right, =1 - left +void rotatefigure(int dir, figure *F){ + figure nF = {.color = F->color}; + for(int i = 0; i < 4; ++i){ + int x = GETX(F->f[i]), y = GETY(F->f[i]), xn, yn; + if(dir){ // CW + xn = y; yn = -x; + }else{ // CCW + xn = -y; yn = x; + } + nF.f[i] = ((xn + 2) << 4) | (yn + 2); + } + memcpy(F, &nF, sizeof(figure)); +} + +// check cup for full lines & delete them; return 1 if need to update +int checkandroll(){ + int upper = ymax, ret = 0; + for(int y = ymax; y >= 0; --y){ + int N = 0; + for(int x = 0; x < COLS; ++x) + if(cup[y][x]) ++N; + if(N == 0) upper = y; + if(N == COLS){ // full line - roll all upper + ret = 1; + for(int yy = y; yy < upper; ++yy) + memcpy(cup[yy], cup[yy+1], COLS); + --upper; + } + } + return ret; +} diff --git a/Tetris/displaybuf.h b/Tetris/displaybuf.h new file mode 100644 index 0000000..2ad9ca6 --- /dev/null +++ b/Tetris/displaybuf.h @@ -0,0 +1,48 @@ +/* + * This file is part of the tetris project. + * Copyright 2020 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#ifndef DISPLAYBUF_H__ +#define DISPLAYBUF_H__ + +#include + +#define ROWS 30 +#define COLS 15 +#define xmax (COLS-1) +#define ymax (ROWS-1) + +// get coordinates by figure member +#define GETX(u) (((u) >> 4) - 2) +#define GETY(u) (((u) & 0xf) - 2) + +typedef struct{ + uint8_t f[4]; + uint8_t color; +} figure; + +#define FIGURESNUM (4) +extern const figure L, J, O, I; +extern uint8_t cup[ROWS][COLS]; + +int chkfigure(int x, int y, const figure *F); +void clearfigure(int x, int y, const figure *F); +void putfigure(int x, int y, const figure *F); +void rotatefigure(int dir, figure *F); +int checkandroll(); + +#endif // DISPLAYBUF_H__ diff --git a/Tetris/main.c b/Tetris/main.c new file mode 100644 index 0000000..002654f --- /dev/null +++ b/Tetris/main.c @@ -0,0 +1,134 @@ +/* + * This file is part of the tetris project. + * Copyright 2020 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +//#include +#include +#include +#include +#include +#include + + +#include "disp.h" +#include "displaybuf.h" + +// return 0 if cannot move +static int mvfig(int *x, int *y, int dx, int dy, figure *F){ + register int xx = *x, yy = *y; + int xnew = xx+dx, ynew = yy+dy, ret = 1; + clearfigure(xx, yy, F); + if(chkfigure(xnew, ynew, F)){ + xx = xnew; yy = ynew; + *x = xx; *y = yy; + }else ret = 0; + putfigure(xx, yy, F); + //mvprintw(ROWS+1, 0, "Coords: (%d, %d); new: (%d, %d)", xx, yy, xnew, ynew); + redisplay(); + return ret; +} + +static void rotfig(int x, int y, int dir, figure *F){ + figure newF; + memcpy(&newF, F, sizeof(figure)); + rotatefigure(dir, &newF); + clearfigure(x, y, F); + if(chkfigure(x, y, &newF)){ // can rotate - substitute old figure with new + memcpy(F, &newF, sizeof(figure)); + } + putfigure(x, y, F); + //mvprintw(ROWS+1, 0, "Coords: (%d, %d); new: (%d, %d)", x, y, x, y); + redisplay(); +} + +static int getrand(){ + static int oldnum[2] = {-1, -1}; + int r = rand() % FIGURESNUM; + if(r == oldnum[1]) r = rand() % FIGURESNUM; + if(r == oldnum[0]) r = rand() % FIGURESNUM; + oldnum[0] = oldnum[1]; + oldnum[1] = r; + return r; +} + +int main(){ + int maxx, maxy; + initscreen(&maxx, &maxy); + const figure *figures[FIGURESNUM] = {&L, &J, &O, &I}, *next = figures[getrand()]; + figure F; + memcpy(&F, &L, sizeof(figure)); + int x = xmax/2, y = ymax; + putfigure(x, y, &F); + shownext(next); + redisplay(); + //attron(A_BOLD); + int n = KEY_NONE; + do{ + n = getkey(); + switch(n){ + case KEY_0: + clearfigure(x, y, &F); + x = xmax/2; y = ymax; + if(!chkfigure(x, y, &F)){ // game over + goto gameover; + } + putfigure(x, y, &F); + redisplay(); + break; + case KEY_D: + if(!mvfig(&x,&y,0,-1,&F)){ // put new figure + if(checkandroll()) redisplay(); + x = xmax/2; y = ymax; + memcpy(&F, next, sizeof(figure)); + next = figures[getrand()]; + shownext(next); + if(!chkfigure(x, y, &F)){ // game over + goto gameover; + } + putfigure(x, y, &F); + redisplay(); + } + break; + case KEY_U: + mvfig(&x,&y,0,1,&F); + break; + case KEY_L: + mvfig(&x,&y,-1,0,&F); + break; + case KEY_R: + mvfig(&x,&y,1,0,&F); + break; + case KEY_ROTL: + rotfig(x, y, 0, &F); + break; + case KEY_ROTR: + rotfig(x, y, 1, &F); + break; + default: + continue; + break; + } + ; + }while(n != KEY_Q); +gameover: + //attroff(A_BOLD); + + closescreen(); + return 0; + } + +//mvaddch(yi, xi, '.'); mvaddstr(maxlines, 0, "Press any key to quit"); diff --git a/Tetris/tetris.cflags b/Tetris/tetris.cflags new file mode 100644 index 0000000..68d5165 --- /dev/null +++ b/Tetris/tetris.cflags @@ -0,0 +1 @@ +-std=c17 \ No newline at end of file diff --git a/Tetris/tetris.config b/Tetris/tetris.config new file mode 100644 index 0000000..baa1bf1 --- /dev/null +++ b/Tetris/tetris.config @@ -0,0 +1,3 @@ +// Add predefined macros for your project here. For example: +// #define THE_ANSWER 42 +#define EBUG diff --git a/Tetris/tetris.creator b/Tetris/tetris.creator new file mode 100644 index 0000000..e94cbbd --- /dev/null +++ b/Tetris/tetris.creator @@ -0,0 +1 @@ +[General] diff --git a/Tetris/tetris.cxxflags b/Tetris/tetris.cxxflags new file mode 100644 index 0000000..6435dfc --- /dev/null +++ b/Tetris/tetris.cxxflags @@ -0,0 +1 @@ +-std=c++17 \ No newline at end of file diff --git a/Tetris/tetris.files b/Tetris/tetris.files new file mode 100644 index 0000000..73eb5cd --- /dev/null +++ b/Tetris/tetris.files @@ -0,0 +1,5 @@ +disp.c +disp.h +displaybuf.c +displaybuf.h +main.c diff --git a/Tetris/tetris.includes b/Tetris/tetris.includes new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/Tetris/tetris.includes @@ -0,0 +1 @@ +. diff --git a/USBrelay/1.c b/USBrelay/1.c index 77de6bb..b8fcbff 100644 --- a/USBrelay/1.c +++ b/USBrelay/1.c @@ -48,6 +48,8 @@ #define RELAY_VENDOR_ID 0x16c0 #define RELAY_PRODUCT_ID 0x05df +#define RELAY_VENDOR_ID_STR "16c0" +#define RELAY_PRODUCT_ID_STR "05df" char *device = NULL; // device name int help = 0; // call help @@ -103,6 +105,58 @@ static void relay_cmd(int cmd, int relaynmbr){ #define INFO(...) do{if(!quiet){green(__VA_ARGS__); printf("\n");}}while(0) +static int get_relay_fd(){ + struct udev *udev; + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *dev_list_entry; + // Create the udev object + udev = udev_new(); + int fd = -1; + if(!udev){ + WARN("udev_new()"); + return -1; + } + // Create a list of the devices in the 'hidraw' subsystem. + enumerate = udev_enumerate_new(udev); + udev_enumerate_add_match_subsystem(enumerate, "hidraw"); + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + // Check out each device found + udev_list_entry_foreach(dev_list_entry, devices){ + const char *path; + struct udev_device *dev; + path = udev_list_entry_get_name(dev_list_entry); + dev = udev_device_new_from_syspath(udev, path); + const char *devpath = udev_device_get_devnode(dev); + DBG("Device Node Path: %s", devpath); + dev = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device"); + if(!dev){ + udev_device_unref(dev); + continue; + } + const char *vid, *pid; + vid = udev_device_get_sysattr_value(dev,"idVendor"); + pid = udev_device_get_sysattr_value(dev, "idProduct"); + DBG(" VID/PID: %s/%s", vid, pid); + if(strcmp(vid, RELAY_VENDOR_ID_STR) == 0 && strcmp(pid, RELAY_PRODUCT_ID_STR) == 0){ + fd = open(devpath, O_RDWR|O_NONBLOCK); + DBG("get fd: %d", fd); + if(fd < 0){ + udev_device_unref(dev); + continue; + } + DBG("%s %s", + udev_device_get_sysattr_value(dev,"manufacturer"), + udev_device_get_sysattr_value(dev,"product")); + udev_device_unref(dev); + break; + } + } + // Free the enumerator object + udev_enumerate_unref(enumerate); + return fd; +} + int main(int argc, char **argv){ int res; char buf[256]; @@ -111,11 +165,11 @@ int main(int argc, char **argv){ initial_setup(); parse_args(argc, argv); - if(!device) ERRX("No device given"); - - fd = open(device, O_RDWR|O_NONBLOCK); + if(!device){ + fd = get_relay_fd(); + }else fd = open(device, O_RDWR|O_NONBLOCK); if(fd < 0){ - WARN("Unable to open device"); + WARNX("Unable to open device"); return 1; } diff --git a/USBrelay/Makefile b/USBrelay/Makefile index 0065b51..d079010 100644 --- a/USBrelay/Makefile +++ b/USBrelay/Makefile @@ -1,9 +1,10 @@ # run `make DEF=...` to add extra defines PROGRAM := relay_manage LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all -LDFLAGS += -lusefull_macros +LDFLAGS += -lusefull_macros -ludev SRCS := $(wildcard *.c) DEFINES := $(DEF) -D_GNU_SOURCE -D_XOPEN_SOURCE=1111 +DEFINES += -DEBUG OBJDIR := mk CFLAGS += -O2 -Wall -Wextra -Wno-trampolines -std=gnu99 OBJS := $(addprefix $(OBJDIR)/, $(SRCS:%.c=%.o)) diff --git a/avx/SIMD_SSE_AVX b/avx/SIMD_SSE_AVX new file mode 100644 index 0000000..e69de29