From 3fb7fefd1fc9f89b55e5ab934dedeb350a5ba5d1 Mon Sep 17 00:00:00 2001 From: DiabloPhD Date: Tue, 29 Oct 2024 18:19:05 -0700 Subject: [PATCH 1/5] Pushing Suhani's code --- Makefile | 1 + kernel/syscall.c | 20 +++++++++ kernel/syscall.h | 9 ++++ user/snake.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++ user/user.h | 10 +++++ 5 files changed, 154 insertions(+) create mode 100644 user/snake.c diff --git a/Makefile b/Makefile index 2584e4a..c8c8dce 100644 --- a/Makefile +++ b/Makefile @@ -127,6 +127,7 @@ UPROGS=\ $U/_mkdir\ $U/_rm\ $U/_sh\ + $U/_snake\ $U/_stressfs\ $U/_usertests\ $U/_grind\ diff --git a/kernel/syscall.c b/kernel/syscall.c index ed65409..feaa7f5 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -102,6 +102,15 @@ extern uint64 sys_link(void); extern uint64 sys_mkdir(void); extern uint64 sys_close(void); +extern void sys_clear_screen(void); +extern void sys_draw_border(void); +extern void sys_draw_snake(void); +extern void sys_draw_food(void); +extern void sys_update_snake(void); +extern void sys_check_collision(void); +extern void sys_place_food(void); +extern void sys_game_over(void); + // An array mapping syscall numbers from syscall.h // to the function that handles the system call. static uint64 (*syscalls[])(void) = { @@ -145,3 +154,14 @@ syscall(void) p->trapframe->a0 = -1; } } + +static void (*syscalls[])(void) = { + [SYS_clear_screen] sys_clear_screen, + [SYS_draw_border] sys_draw_border, + [SYS_draw_snake] sys_draw_snake, + [SYS_draw_food] sys_draw_food, + [SYS_update_snake] sys_update_snake, + [SYS_check_collision] sys_check_collision, + [SYS_place_food] sys_place_food, + [SYS_game_over] sys_game_over, +}; diff --git a/kernel/syscall.h b/kernel/syscall.h index bc5f356..5dbdd28 100644 --- a/kernel/syscall.h +++ b/kernel/syscall.h @@ -20,3 +20,12 @@ #define SYS_link 19 #define SYS_mkdir 20 #define SYS_close 21 +//snake system calls +#define SYS_clear_screen 22 +#define SYS_draw_border 23 +#define SYS_draw_snake 24 +#define SYS_draw_food 25 +#define SYS_update_snake 26 +#define SYS_check_collision 27 +#define SYS_place_food 28 +#define SYS_game_over 29 \ No newline at end of file diff --git a/user/snake.c b/user/snake.c new file mode 100644 index 0000000..6bf07c7 --- /dev/null +++ b/user/snake.c @@ -0,0 +1,114 @@ +#include "kernel/types.h" +#include "kernel/stat.h" +#include "user/user.h" +#include "kernel/fcntl.h" + +#define WIDTH 20 +#define HEIGHT 10 +#define SNAKE_MAX_LENGTH 100 + +typedef struct { + int x, y; +} Point; + +typedef struct { + Point body[SNAKE_MAX_LENGTH]; + int length; + Point direction; +} Snake; + +void clear_screen() { + printf("\033[H\033[J"); +} + +void draw_border() { + for (int i = 0; i < WIDTH + 2; i++) printf("#"); + printf("\n"); + for (int i = 0; i < HEIGHT; i++) { + printf("#"); + for (int j = 0; j < WIDTH; j++) printf(" "); + printf("#\n"); + } + for (int i = 0; i < WIDTH + 2; i++) printf("#"); + printf("\n"); +} + +void draw_snake(Snake *snake) { + for (int i = 0; i < snake->length; i++) { + printf("\033[%d;%dH@", snake->body[i].y + 2, snake->body[i].x + 2); + } +} + +void draw_food(Point *food) { + printf("\033[%d;%dH*", food->y + 2, food->x + 2); +} + +void update_snake(Snake *snake) { + for (int i = snake->length - 1; i > 0; i--) { + snake->body[i] = snake->body[i - 1]; + } + snake->body[0].x += snake->direction.x; + snake->body[0].y += snake->direction.y; +} + +int check_collision(Snake *snake) { + Point head = snake->body[0]; + if (head.x < 0 || head.x >= WIDTH || head.y < 0 || head.y >= HEIGHT) return 1; + for (int i = 1; i < snake->length; i++) { + if (head.x == snake->body[i].x && head.y == snake->body[i].y) return 1; + } + return 0; +} + +void place_food(Point *food, Snake *snake) { + int valid; + do { + valid = 1; + food->x = rand() % WIDTH; + food->y = rand() % HEIGHT; + for (int i = 0; i < snake->length; i++) { + if (food->x == snake->body[i].x && food->y == snake->body[i].y) { + valid = 0; + break; + } + } + } while (!valid); +} + +void game_over() { + printf("\033[%d;%dHGame Over!\n", HEIGHT / 2 + 2, WIDTH / 2 - 4); + exit(0); +} + +int main() { + Snake snake; + Point food; + snake.length = 1; + snake.body[0].x = WIDTH / 2; + snake.body[0].y = HEIGHT / 2; + snake.direction.x = 1; + snake.direction.y = 0; + + place_food(&food, &snake); + + clear_screen(); + draw_border(); + draw_snake(&snake); + draw_food(&food); + + while (1) { + if (check_collision(&snake)) game_over(); + if (snake.body[0].x == food.x && snake.body[0].y == food.y) { + if (snake.length < SNAKE_MAX_LENGTH) snake.length++; + place_food(&food, &snake); + } + update_snake(&snake); + clear_screen(); + draw_border(); + draw_snake(&snake); + draw_food(&food); + sleep(1); + } + return 0; +} + diff --git a/user/user.h b/user/user.h index 2e6fc55..b0eb1b2 100644 --- a/user/user.h +++ b/user/user.h @@ -41,3 +41,13 @@ void free(void*); int atoi(const char*); int memcmp(const void *, const void *, uint); void *memcpy(void *, const void *, uint); + +// Functions for game-related system calls +void clear_screen(void); +void draw_border(void); +void draw_snake(Snake *snake); +void draw_food(Point *food); +void update_snake(Snake *snake); +int check_collision(Snake *snake); +void place_food(Point *food, Snake *snake); +void game_over(void); \ No newline at end of file From 1bc90534c09e4de432ec11a5b6b1e7de1122a111 Mon Sep 17 00:00:00 2001 From: Duncan Birdsall Date: Tue, 29 Oct 2024 18:48:45 -0700 Subject: [PATCH 2/5] Snake is now runnable, but not displaying properly --- kernel/syscall.c | 20 -------------------- kernel/syscall.h | 9 --------- kernel/types.h | 10 ++++++++++ user/snake.c | 18 ++++++++---------- 4 files changed, 18 insertions(+), 39 deletions(-) diff --git a/kernel/syscall.c b/kernel/syscall.c index feaa7f5..ed65409 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -102,15 +102,6 @@ extern uint64 sys_link(void); extern uint64 sys_mkdir(void); extern uint64 sys_close(void); -extern void sys_clear_screen(void); -extern void sys_draw_border(void); -extern void sys_draw_snake(void); -extern void sys_draw_food(void); -extern void sys_update_snake(void); -extern void sys_check_collision(void); -extern void sys_place_food(void); -extern void sys_game_over(void); - // An array mapping syscall numbers from syscall.h // to the function that handles the system call. static uint64 (*syscalls[])(void) = { @@ -154,14 +145,3 @@ syscall(void) p->trapframe->a0 = -1; } } - -static void (*syscalls[])(void) = { - [SYS_clear_screen] sys_clear_screen, - [SYS_draw_border] sys_draw_border, - [SYS_draw_snake] sys_draw_snake, - [SYS_draw_food] sys_draw_food, - [SYS_update_snake] sys_update_snake, - [SYS_check_collision] sys_check_collision, - [SYS_place_food] sys_place_food, - [SYS_game_over] sys_game_over, -}; diff --git a/kernel/syscall.h b/kernel/syscall.h index 5dbdd28..bc5f356 100644 --- a/kernel/syscall.h +++ b/kernel/syscall.h @@ -20,12 +20,3 @@ #define SYS_link 19 #define SYS_mkdir 20 #define SYS_close 21 -//snake system calls -#define SYS_clear_screen 22 -#define SYS_draw_border 23 -#define SYS_draw_snake 24 -#define SYS_draw_food 25 -#define SYS_update_snake 26 -#define SYS_check_collision 27 -#define SYS_place_food 28 -#define SYS_game_over 29 \ No newline at end of file diff --git a/kernel/types.h b/kernel/types.h index ee73164..cbef7be 100644 --- a/kernel/types.h +++ b/kernel/types.h @@ -8,3 +8,13 @@ typedef unsigned int uint32; typedef unsigned long uint64; typedef uint64 pde_t; + +typedef struct { + int x, y; +} Point; + +typedef struct { + Point body[100]; + int length; + Point direction; +} Snake; diff --git a/user/snake.c b/user/snake.c index 6bf07c7..a3183e3 100644 --- a/user/snake.c +++ b/user/snake.c @@ -7,15 +7,13 @@ #define HEIGHT 10 #define SNAKE_MAX_LENGTH 100 -typedef struct { - int x, y; -} Point; - -typedef struct { - Point body[SNAKE_MAX_LENGTH]; - int length; - Point direction; -} Snake; +uint32 rand() { + uint32 x = uptime(); + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + return x; +} void clear_screen() { printf("\033[H\033[J"); @@ -107,7 +105,7 @@ int main() { draw_border(); draw_snake(&snake); draw_food(&food); - sleep(1); + sleep(100); } return 0; } From 9ce58521a5c9495eb91963c1e1c83b2cd00d0dea Mon Sep 17 00:00:00 2001 From: Duncan Birdsall Date: Wed, 30 Oct 2024 00:08:45 -0700 Subject: [PATCH 3/5] Snake is playable! Must fix console afterwards though. --- kernel/console.c | 38 ++++++++++++++++++++++++++++++++++++++ kernel/defs.h | 1 + kernel/file.c | 28 ++++++++++++++++++++++++++++ kernel/file.h | 1 + kernel/syscall.c | 2 ++ kernel/syscall.h | 1 + kernel/sysfile.c | 14 ++++++++++++++ user/snake.c | 35 ++++++++++++++++++++++++++++++----- user/user.h | 11 +---------- user/usys.pl | 1 + 10 files changed, 117 insertions(+), 15 deletions(-) diff --git a/kernel/console.c b/kernel/console.c index 05dc526..5068282 100644 --- a/kernel/console.c +++ b/kernel/console.c @@ -126,6 +126,43 @@ consoleread(int user_dst, uint64 dst, int n) return target - n; } +//Get current keypress from console with no delay. +int +consolekeys(int user_dst, uint64 dst, int n) +{ + uint target; + int c; + char cbuf; + + target = n; + acquire(&cons.lock); + while(n > 0){ + + if(killed(myproc())){ + release(&cons.lock); + return -1; + } + + c = cons.buf[cons.r++ % INPUT_BUF_SIZE]; + // copy the input byte to the user-space buffer. + cbuf = c; + if (c != '\033' && c!= '[' && c != 'A' && c != 'B' && c != 'C' && c != 'D'){ + uartputc_sync(c); uartputc_sync(' '); uartputc_sync(c); + cons.r--; + break; + } + + if(either_copyout(user_dst, dst, &cbuf, 1) == -1) + break; + + dst++; + --n; + } + release(&cons.lock); + + return target - n; +} + // // the console input interrupt handler. // uartintr() calls this for input character. @@ -188,5 +225,6 @@ consoleinit(void) // connect read and write system calls // to consoleread and consolewrite. devsw[CONSOLE].read = consoleread; + devsw[CONSOLE].keys = consolekeys; devsw[CONSOLE].write = consolewrite; } diff --git a/kernel/defs.h b/kernel/defs.h index a3c962b..e4f7d8c 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -30,6 +30,7 @@ struct file* filealloc(void); void fileclose(struct file*); struct file* filedup(struct file*); void fileinit(void); +int filekeys(struct file*, uint64, int n); int fileread(struct file*, uint64, int n); int filestat(struct file*, uint64 addr); int filewrite(struct file*, uint64, int n); diff --git a/kernel/file.c b/kernel/file.c index 25fa226..6bdf3c1 100644 --- a/kernel/file.c +++ b/kernel/file.c @@ -129,6 +129,34 @@ fileread(struct file *f, uint64 addr, int n) return r; } +// Read keys from file f. +// addr is a user virtual address. +int +filekeys(struct file *f, uint64 addr, int n) +{ + int r = 0; + + if(f->readable == 0) + return -1; + + if(f->type == FD_PIPE){ + r = piperead(f->pipe, addr, n); + } else if(f->type == FD_DEVICE){ + if(f->major < 0 || f->major >= NDEV || !devsw[f->major].keys) + return -1; + r = devsw[f->major].keys(1, addr, n); + } else if(f->type == FD_INODE){ + ilock(f->ip); + if((r = readi(f->ip, 1, addr, f->off, n)) > 0) + f->off += r; + iunlock(f->ip); + } else { + panic("fileread"); + } + + return r; +} + // Write to file f. // addr is a user virtual address. int diff --git a/kernel/file.h b/kernel/file.h index b076d1d..e3eaaf5 100644 --- a/kernel/file.h +++ b/kernel/file.h @@ -33,6 +33,7 @@ struct inode { struct devsw { int (*read)(int, uint64, int); int (*write)(int, uint64, int); + int (*keys)(int, uint64, int); }; extern struct devsw devsw[]; diff --git a/kernel/syscall.c b/kernel/syscall.c index ed65409..5d06f87 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -101,6 +101,7 @@ extern uint64 sys_unlink(void); extern uint64 sys_link(void); extern uint64 sys_mkdir(void); extern uint64 sys_close(void); +extern uint64 sys_keys(void); // An array mapping syscall numbers from syscall.h // to the function that handles the system call. @@ -126,6 +127,7 @@ static uint64 (*syscalls[])(void) = { [SYS_link] sys_link, [SYS_mkdir] sys_mkdir, [SYS_close] sys_close, +[SYS_keys] sys_keys, }; void diff --git a/kernel/syscall.h b/kernel/syscall.h index bc5f356..5872397 100644 --- a/kernel/syscall.h +++ b/kernel/syscall.h @@ -20,3 +20,4 @@ #define SYS_link 19 #define SYS_mkdir 20 #define SYS_close 21 +#define SYS_keys 22 diff --git a/kernel/sysfile.c b/kernel/sysfile.c index 16b668c..3e39708 100644 --- a/kernel/sysfile.c +++ b/kernel/sysfile.c @@ -79,6 +79,20 @@ sys_read(void) return fileread(f, p, n); } +uint64 +sys_keys(void) +{ + struct file *f; + int n; + uint64 p; + + argaddr(1, &p); + argint(2, &n); + if(argfd(0, 0, &f) < 0) + return -1; + return filekeys(f, p, n); +} + uint64 sys_write(void) { diff --git a/user/snake.c b/user/snake.c index a3183e3..e9b192e 100644 --- a/user/snake.c +++ b/user/snake.c @@ -1,7 +1,6 @@ #include "kernel/types.h" #include "kernel/stat.h" #include "user/user.h" -#include "kernel/fcntl.h" #define WIDTH 20 #define HEIGHT 10 @@ -15,6 +14,10 @@ uint32 rand() { return x; } +void move_cursor() { + printf("\033[%d;1H", HEIGHT + 3); +} + void clear_screen() { printf("\033[H\033[J"); } @@ -29,16 +32,19 @@ void draw_border() { } for (int i = 0; i < WIDTH + 2; i++) printf("#"); printf("\n"); + move_cursor(); } void draw_snake(Snake *snake) { for (int i = 0; i < snake->length; i++) { printf("\033[%d;%dH@", snake->body[i].y + 2, snake->body[i].x + 2); } + move_cursor(); } void draw_food(Point *food) { printf("\033[%d;%dH*", food->y + 2, food->x + 2); + move_cursor(); } void update_snake(Snake *snake) { @@ -47,6 +53,7 @@ void update_snake(Snake *snake) { } snake->body[0].x += snake->direction.x; snake->body[0].y += snake->direction.y; + move_cursor(); } int check_collision(Snake *snake) { @@ -71,11 +78,14 @@ void place_food(Point *food, Snake *snake) { } } } while (!valid); + move_cursor(); } -void game_over() { +void game_over(Snake *snake) { printf("\033[%d;%dHGame Over!\n", HEIGHT / 2 + 2, WIDTH / 2 - 4); - exit(0); + printf("\033[%d;%dHYou scored %d!\n", HEIGHT / 2 + 3, WIDTH / 2 - 4, snake->length-1); + move_cursor(); + return; } int main() { @@ -95,7 +105,22 @@ int main() { draw_food(&food); while (1) { - if (check_collision(&snake)) game_over(); + char input[3]; // Buffer to store escape sequences + int n = keys(0, input, 3); // Read up to 3 characters + if (n > 0) { + if (n == 3 && input[0] == '\033' && input[1] == '[') { + switch (input[2]) { + case 'A': if (snake.direction.y == 0) { snake.direction.x = 0; snake.direction.y = -1; } break; // Up + case 'B': if (snake.direction.y == 0) { snake.direction.x = 0; snake.direction.y = 1; } break; // Down + case 'C': if (snake.direction.x == 0) { snake.direction.x = 1; snake.direction.y = 0; } break; // Right + case 'D': if (snake.direction.x == 0) { snake.direction.x = -1; snake.direction.y = 0; } break; // Left + } + } + } + if (check_collision(&snake)){ + game_over(&snake); + break; + } if (snake.body[0].x == food.x && snake.body[0].y == food.y) { if (snake.length < SNAKE_MAX_LENGTH) snake.length++; place_food(&food, &snake); @@ -105,7 +130,7 @@ int main() { draw_border(); draw_snake(&snake); draw_food(&food); - sleep(100); + sleep(3); } return 0; } diff --git a/user/user.h b/user/user.h index b0eb1b2..1ce2bcd 100644 --- a/user/user.h +++ b/user/user.h @@ -22,6 +22,7 @@ int getpid(void); char* sbrk(int); int sleep(int); int uptime(void); +int keys(int, void*, int); // ulib.c int stat(const char*, struct stat*); @@ -41,13 +42,3 @@ void free(void*); int atoi(const char*); int memcmp(const void *, const void *, uint); void *memcpy(void *, const void *, uint); - -// Functions for game-related system calls -void clear_screen(void); -void draw_border(void); -void draw_snake(Snake *snake); -void draw_food(Point *food); -void update_snake(Snake *snake); -int check_collision(Snake *snake); -void place_food(Point *food, Snake *snake); -void game_over(void); \ No newline at end of file diff --git a/user/usys.pl b/user/usys.pl index 01e426e..520f65f 100755 --- a/user/usys.pl +++ b/user/usys.pl @@ -36,3 +36,4 @@ sub entry { entry("sbrk"); entry("sleep"); entry("uptime"); +entry("keys"); From ca942ecfb39800eac51fe0c8924e07fe05881ab5 Mon Sep 17 00:00:00 2001 From: Duncan Birdsall Date: Wed, 30 Oct 2024 02:20:00 -0700 Subject: [PATCH 4/5] Almost working! --- kernel/console.c | 2 +- user/snake.c | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/kernel/console.c b/kernel/console.c index 5068282..108668c 100644 --- a/kernel/console.c +++ b/kernel/console.c @@ -145,9 +145,9 @@ consolekeys(int user_dst, uint64 dst, int n) c = cons.buf[cons.r++ % INPUT_BUF_SIZE]; // copy the input byte to the user-space buffer. + cons.w = cons.e; cbuf = c; if (c != '\033' && c!= '[' && c != 'A' && c != 'B' && c != 'C' && c != 'D'){ - uartputc_sync(c); uartputc_sync(' '); uartputc_sync(c); cons.r--; break; } diff --git a/user/snake.c b/user/snake.c index e9b192e..2691f5e 100644 --- a/user/snake.c +++ b/user/snake.c @@ -32,19 +32,16 @@ void draw_border() { } for (int i = 0; i < WIDTH + 2; i++) printf("#"); printf("\n"); - move_cursor(); } void draw_snake(Snake *snake) { for (int i = 0; i < snake->length; i++) { printf("\033[%d;%dH@", snake->body[i].y + 2, snake->body[i].x + 2); } - move_cursor(); } void draw_food(Point *food) { printf("\033[%d;%dH*", food->y + 2, food->x + 2); - move_cursor(); } void update_snake(Snake *snake) { @@ -53,7 +50,6 @@ void update_snake(Snake *snake) { } snake->body[0].x += snake->direction.x; snake->body[0].y += snake->direction.y; - move_cursor(); } int check_collision(Snake *snake) { @@ -78,7 +74,6 @@ void place_food(Point *food, Snake *snake) { } } } while (!valid); - move_cursor(); } void game_over(Snake *snake) { @@ -119,7 +114,7 @@ int main() { } if (check_collision(&snake)){ game_over(&snake); - break; + return 0; } if (snake.body[0].x == food.x && snake.body[0].y == food.y) { if (snake.length < SNAKE_MAX_LENGTH) snake.length++; @@ -130,6 +125,7 @@ int main() { draw_border(); draw_snake(&snake); draw_food(&food); + move_cursor(); sleep(3); } return 0; From 8f630f4434f90f2f9198f00ff34ff7a7754f4321 Mon Sep 17 00:00:00 2001 From: Duncan Birdsall Date: Wed, 30 Oct 2024 02:31:09 -0700 Subject: [PATCH 5/5] Issue with overflow somewhere --- kernel/types.h | 2 +- user/snake.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/types.h b/kernel/types.h index cbef7be..8f1bcf1 100644 --- a/kernel/types.h +++ b/kernel/types.h @@ -14,7 +14,7 @@ typedef struct { } Point; typedef struct { - Point body[100]; + Point body[sizeof(Point)*20]; int length; Point direction; } Snake; diff --git a/user/snake.c b/user/snake.c index 2691f5e..b7b81e0 100644 --- a/user/snake.c +++ b/user/snake.c @@ -4,7 +4,7 @@ #define WIDTH 20 #define HEIGHT 10 -#define SNAKE_MAX_LENGTH 100 +#define SNAKE_MAX_LENGTH 20 uint32 rand() { uint32 x = uptime();