From b79e1dd054b8fc627289e0c215d5243b12baf877 Mon Sep 17 00:00:00 2001 From: Adam Greenwood-Byrne Date: Wed, 15 Jul 2020 17:52:03 +0100 Subject: [PATCH] Tidy up of the breakout code --- part6-breakout/breakout.c | 252 -------------------------------------- part6-breakout/breakout.h | 1 - part6-breakout/fb.c | 147 +++++++++++----------- part6-breakout/kernel.c | 252 +++++++++++++++++++++++++++++++++++++- part6-breakout/mb.c | 2 +- 5 files changed, 323 insertions(+), 331 deletions(-) delete mode 100644 part6-breakout/breakout.c delete mode 100644 part6-breakout/breakout.h diff --git a/part6-breakout/breakout.c b/part6-breakout/breakout.c deleted file mode 100644 index 36abe25..0000000 --- a/part6-breakout/breakout.c +++ /dev/null @@ -1,252 +0,0 @@ -#include "fb.h" -#include "io.h" - -// The screen -#define WIDTH 1920 -#define HEIGHT 1080 -#define MARGIN 75 -#define VIRTWIDTH (WIDTH-(2*MARGIN)) -#define FONT_BPG 8 - -// For the bricks -#define ROWS 5 -#define COLS 10 -unsigned int bricks = ROWS * COLS; - -// Gameplay -#define NUM_LIVES 3 - -// OBJECT TRACKING - -struct Object -{ - unsigned int type; - unsigned int x; - unsigned int y; - unsigned int width; - unsigned int height; - unsigned char alive; -}; - -enum { - OBJ_NONE = 0, - OBJ_BRICK = 1, - OBJ_PADDLE = 2, - OBJ_BALL = 3 -}; - -unsigned int numobjs = 0; -struct Object objects[(ROWS * COLS) + (2 * NUM_LIVES)]; -struct Object *ball; -struct Object *paddle; - -void removeObject(struct Object *object) -{ - drawRect(object->x, object->y, object->x + object->width, object->y + object->height, 0, 1); - object->alive = 0; -} - -void moveObject(struct Object *object, int xoff, int yoff) -{ - moveRect(object->x, object->y, object->width, object->height, xoff, yoff, 0x00); - object->x = object->x + xoff; - object->y = object->y + yoff; -} - -struct Object *objectAt(unsigned int x, unsigned int y) -{ - for (int i=0; i= objects[i].x && x <= objects[i].x + objects[i].width) { - if (y >= objects[i].y && y <= objects[i].y + objects[i].height) { - if (&objects[i] != ball && objects[i].alive == 1) { - return &objects[i]; - } - } - } - } - return 0; -} - -struct Object *detectCollision(int xoff, int yoff) -{ - struct Object *collision; - - unsigned int x = ball->x + xoff; - unsigned int y = ball->y + yoff; - - collision = objectAt(x,y); - if (collision) return collision; - - collision = objectAt(x + ball->width, y); - if (collision) return collision; - - collision = objectAt(x, y + ball->height); - if (collision) return collision; - - collision = objectAt(x + ball->width, y + ball->height); - if (collision) return collision; - - return 0; -} - -// KEY HANDLER - -unsigned char getUart() -{ - unsigned char ch = 0; - - if (uart_isReadByteReady()) ch = uart_readByte(); - return ch; -} - -// OBJECT INITIALISERS - -void initBricks() -{ - int brickwidth = 32; - int brickheight = 8; - int brickspacer = 20; - int brickcols[5] = { 0x01, 0x02, 0x0E, 0x04, 0x06 }; - - int ybrick = MARGIN + brickheight; - - for (int i=0; i 0 && bricks > 0) { - // Get any waiting input and flush the buffer - if ( ( ch = getUart() ) ) { - if (ch == 'l') if (paddle->x + paddle->width + (paddle->width / 2) <= WIDTH-MARGIN) moveObject(paddle, paddle->width / 2, 0); - if (ch == 'h') if (paddle->x >= MARGIN+(paddle->width / 2)) moveObject(paddle, -(paddle->width / 2), 0); - } - uart_loadOutputFifo(); - - // Are we going to hit anything? - foundObject = detectCollision(velocity_x, velocity_y); - - if (foundObject) { - if (foundObject == paddle) { - velocity_y = -velocity_y; - // Are we going to hit the side of the paddle - if (ball->x + ball->width + velocity_x == paddle->x || ball->x + velocity_x == paddle->x + paddle->width) velocity_x = -velocity_x; - } else if (foundObject->type == OBJ_BRICK) { - removeObject(foundObject); - velocity_y = -velocity_y; - bricks--; - points++; - drawScoreboard(points, lives); - } - } - - wait_msec(4000); // Wait for a tenth of a second - moveObject(ball, velocity_x, velocity_y); - - // Check we're in the game arena still - if (ball->x + ball->width >= WIDTH-MARGIN) { - velocity_x = -velocity_x; - } else if (ball->x <= MARGIN) { - velocity_x = -velocity_x; - } else if (ball->y + ball->height >= HEIGHT-MARGIN) { - lives--; - - removeObject(ball); - removeObject(paddle); - - initBall(); - initPaddle(); - drawScoreboard(points, lives); - } else if (ball->y <= MARGIN) { - velocity_y = -velocity_y; - } - } - - int zoom = WIDTH/192; - int strwidth = 10 * FONT_BPG * zoom; - int strheight = FONT_BPG * zoom; - - if (bricks == 0) drawString((WIDTH/2)-(strwidth/2), (HEIGHT/2)-(strheight/2), "Well done!", 0x02, zoom); - else drawString((WIDTH/2)-(strwidth/2), (HEIGHT/2)-(strheight/2), "Game over!", 0x04, zoom); -} diff --git a/part6-breakout/breakout.h b/part6-breakout/breakout.h deleted file mode 100644 index 3fb5023..0000000 --- a/part6-breakout/breakout.h +++ /dev/null @@ -1 +0,0 @@ -void game(); diff --git a/part6-breakout/fb.c b/part6-breakout/fb.c index ba6ddb1..8dc7592 100644 --- a/part6-breakout/fb.c +++ b/part6-breakout/fb.c @@ -5,7 +5,6 @@ unsigned int width, height, pitch, isrgb; unsigned char *fb; -// Refer to https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface in write-up! void fb_init() { mbox[0] = 35*4; // Length of message in bytes @@ -69,36 +68,6 @@ void drawPixel(int x, int y, unsigned char attr) *((unsigned int*)(fb + offs)) = vgapal[attr & 0x0f]; } -void drawChar(unsigned char ch, int x, int y, unsigned char attr, int zoom) -{ - unsigned char *glyph = (unsigned char *)&font + (ch < FONT_NUMGLYPHS ? ch : 0) * FONT_BPG; - - for (int i=1;i<=(FONT_HEIGHT*zoom);i++) { - for (int j=0;j<(FONT_WIDTH*zoom);j++) { - unsigned char mask = 1 << (j/zoom); - unsigned char col = (*glyph & mask) ? attr & 0x0f : (attr & 0xf0) >> 4; - - drawPixel(x+j, y+i, col); - } - glyph += (i%zoom) ? 0 : FONT_BPL; - } -} - -void drawString(int x, int y, char *s, unsigned char attr, int zoom) -{ - while(*s) { - if (*s == '\r') { - x = 0; - } else if(*s == '\n') { - x = 0; y += FONT_HEIGHT; - } else { - drawChar(*s, x, y, attr, zoom); - x += (FONT_WIDTH*zoom); - } - s++; - } -} - void drawRect(int x1, int y1, int x2, int y2, unsigned char attr, int fill) { int y=y1; @@ -106,42 +75,14 @@ void drawRect(int x1, int y1, int x2, int y2, unsigned char attr, int fill) while (y <= y2) { int x=x1; while (x <= x2) { - if (fill || (x == x1 || x == x2) || (y == y1 || y == y2)) drawPixel(x, y, attr); + if ((x == x1 || x == x2) || (y == y1 || y == y2)) drawPixel(x, y, attr); + else if (fill) drawPixel(x, y, (attr & 0xf0) >> 4); x++; } y++; } } -void moveRect(int oldx, int oldy, int width, int height, int shiftx, int shifty, unsigned char attr) -{ - unsigned int newx = oldx + shiftx, newy = oldy + shifty; - unsigned int xcount = 0, ycount = 0; - unsigned int bitmap[width][height]; // This is very unsafe if it's too big for the stack... - unsigned int offs; - - // Save the bitmap - while (xcount < width) { - while (ycount < height) { - offs = ((oldy + ycount) * pitch) + ((oldx + xcount) * 4); - - bitmap[xcount][ycount] = *((unsigned int*)(fb + offs)); - ycount++; - } - ycount=0; - xcount++; - } - // Wipe it out with background colour - drawRect(oldx, oldy, oldx + width, oldy + width, attr, 1); - // Draw it again - for (int i=newx;i= y) { if (fill) { - drawLine(x0 - y, y0 + x, x0 + y, y0 + x, attr); - drawLine(x0 - x, y0 + y, x0 + x, y0 + y, attr); - drawLine(x0 - x, y0 - y, x0 + x, y0 - y, attr); - drawLine(x0 - y, y0 - x, x0 + y, y0 - x, attr); - } else { - drawPixel(x0 - y, y0 + x, attr); - drawPixel(x0 + y, y0 + x, attr); - drawPixel(x0 - x, y0 + y, attr); - drawPixel(x0 + x, y0 + y, attr); - drawPixel(x0 - x, y0 - y, attr); - drawPixel(x0 + x, y0 - y, attr); - drawPixel(x0 - y, y0 - x, attr); - drawPixel(x0 + y, y0 - x, attr); + drawLine(x0 - y, y0 + x, x0 + y, y0 + x, (attr & 0xf0) >> 4); + drawLine(x0 - x, y0 + y, x0 + x, y0 + y, (attr & 0xf0) >> 4); + drawLine(x0 - x, y0 - y, x0 + x, y0 - y, (attr & 0xf0) >> 4); + drawLine(x0 - y, y0 - x, x0 + y, y0 - x, (attr & 0xf0) >> 4); } + drawPixel(x0 - y, y0 + x, attr); + drawPixel(x0 + y, y0 + x, attr); + drawPixel(x0 - x, y0 + y, attr); + drawPixel(x0 + x, y0 + y, attr); + drawPixel(x0 - x, y0 - y, attr); + drawPixel(x0 + x, y0 - y, attr); + drawPixel(x0 - y, y0 - x, attr); + drawPixel(x0 + y, y0 - x, attr); if (err <= 0) { y += 1; @@ -200,6 +140,65 @@ void drawCircle(int x0, int y0, int radius, unsigned char attr, int fill) } } +void drawChar(unsigned char ch, int x, int y, unsigned char attr, int zoom) +{ + unsigned char *glyph = (unsigned char *)&font + (ch < FONT_NUMGLYPHS ? ch : 0) * FONT_BPG; + + for (int i=1;i<=(FONT_HEIGHT*zoom);i++) { + for (int j=0;j<(FONT_WIDTH*zoom);j++) { + unsigned char mask = 1 << (j/zoom); + unsigned char col = (*glyph & mask) ? attr & 0x0f : (attr & 0xf0) >> 4; + + drawPixel(x+j, y+i, col); + } + glyph += (i%zoom) ? 0 : FONT_BPL; + } +} + +void drawString(int x, int y, char *s, unsigned char attr, int zoom) +{ + while(*s) { + if (*s == '\r') { + x = 0; + } else if(*s == '\n') { + x = 0; y += FONT_HEIGHT; + } else { + drawChar(*s, x, y, attr, zoom); + x += (FONT_WIDTH*zoom); + } + s++; + } +} + +void moveRect(int oldx, int oldy, int width, int height, int shiftx, int shifty, unsigned char attr) +{ + unsigned int newx = oldx + shiftx, newy = oldy + shifty; + unsigned int xcount = 0, ycount = 0; + unsigned int bitmap[width][height]; // This is very unsafe if it's too big for the stack... + unsigned int offs; + + // Save the bitmap + while (xcount < width) { + while (ycount < height) { + offs = ((oldy + ycount) * pitch) + ((oldx + xcount) * 4); + + bitmap[xcount][ycount] = *((unsigned int*)(fb + offs)); + ycount++; + } + ycount=0; + xcount++; + } + // Wipe it out with background colour + drawRect(oldx, oldy, oldx + width, oldy + width, attr, 1); + // Draw it again + for (int i=newx;ix, object->y, object->x + object->width, object->y + object->height, 0, 1); + object->alive = 0; +} + +void moveObject(struct Object *object, int xoff, int yoff) +{ + moveRect(object->x, object->y, object->width, object->height, xoff, yoff, 0x00); + object->x = object->x + xoff; + object->y = object->y + yoff; +} + +struct Object *objectAt(unsigned int x, unsigned int y) +{ + for (int i=0; i= objects[i].x && x <= objects[i].x + objects[i].width) { + if (y >= objects[i].y && y <= objects[i].y + objects[i].height) { + if (&objects[i] != ball && objects[i].alive == 1) { + return &objects[i]; + } + } + } + } + return 0; +} + +struct Object *detectCollision(int xoff, int yoff) +{ + struct Object *collision; + + unsigned int x = ball->x + xoff; + unsigned int y = ball->y + yoff; + + collision = objectAt(x,y); + if (collision) return collision; + + collision = objectAt(x + ball->width, y); + if (collision) return collision; + + collision = objectAt(x, y + ball->height); + if (collision) return collision; + + collision = objectAt(x + ball->width, y + ball->height); + if (collision) return collision; + + return 0; +} + +// KEY HANDLER + +unsigned char getUart() +{ + unsigned char ch = 0; + + if (uart_isReadByteReady()) ch = uart_readByte(); + return ch; +} + +// OBJECT INITIALISERS + +void initBricks() +{ + int brickwidth = 32; + int brickheight = 8; + int brickspacer = 20; + int brickcols[5] = { 0x11, 0x22, 0xEE, 0x44, 0x66 }; + + int ybrick = MARGIN + brickheight; + + for (int i=0; i 0 && bricks > 0) { + // Get any waiting input and flush the buffer + if ( ( ch = getUart() ) ) { + if (ch == 'l') if (paddle->x + paddle->width + (paddle->width / 2) <= WIDTH-MARGIN) moveObject(paddle, paddle->width / 2, 0); + if (ch == 'h') if (paddle->x >= MARGIN+(paddle->width / 2)) moveObject(paddle, -(paddle->width / 2), 0); + } + uart_loadOutputFifo(); + + // Are we going to hit anything? + foundObject = detectCollision(velocity_x, velocity_y); + + if (foundObject) { + if (foundObject == paddle) { + velocity_y = -velocity_y; + // Are we going to hit the side of the paddle + if (ball->x + ball->width + velocity_x == paddle->x || ball->x + velocity_x == paddle->x + paddle->width) velocity_x = -velocity_x; + } else if (foundObject->type == OBJ_BRICK) { + removeObject(foundObject); + velocity_y = -velocity_y; + bricks--; + points++; + drawScoreboard(points, lives); + } + } + + wait_msec(4000); // Wait for a tenth of a second + moveObject(ball, velocity_x, velocity_y); + + // Check we're in the game arena still + if (ball->x + ball->width >= WIDTH-MARGIN) { + velocity_x = -velocity_x; + } else if (ball->x <= MARGIN) { + velocity_x = -velocity_x; + } else if (ball->y + ball->height >= HEIGHT-MARGIN) { + lives--; + + removeObject(ball); + removeObject(paddle); + + initBall(); + initPaddle(); + drawScoreboard(points, lives); + } else if (ball->y <= MARGIN) { + velocity_y = -velocity_y; + } + } + + int zoom = WIDTH/192; + int strwidth = 10 * FONT_BPG * zoom; + int strheight = FONT_BPG * zoom; + + if (bricks == 0) drawString((WIDTH/2)-(strwidth/2), (HEIGHT/2)-(strheight/2), "Well done!", 0x02, zoom); + else drawString((WIDTH/2)-(strwidth/2), (HEIGHT/2)-(strheight/2), "Game over!", 0x04, zoom); + while (1); } diff --git a/part6-breakout/mb.c b/part6-breakout/mb.c index f9fb7a0..4354247 100644 --- a/part6-breakout/mb.c +++ b/part6-breakout/mb.c @@ -24,7 +24,7 @@ unsigned int mbox_call(unsigned char ch) // Wait until we can write while (mmio_read(MBOX_STATUS) & MBOX_FULL); - /* write the address of our message to the mailbox with channel identifier */ + // Write the address of our buffer to the mailbox with the channel appended mmio_write(MBOX_WRITE, r); while (1) {