From b446a43738993b229b497ea7f0c0ba9762efbff8 Mon Sep 17 00:00:00 2001 From: Quinn Date: Wed, 18 Jun 2025 15:48:56 +0200 Subject: [PATCH] use tabs over spaces --- .clang-format | 2 +- .editorconfig | 12 +- src/error.h | 46 +++---- src/game/game.c | 196 +++++++++++++-------------- src/game/game.h | 24 ++-- src/game/gametime.h | 16 +-- src/game/paths.c | 72 +++++----- src/game/tetromino/placing.c | 186 ++++++++++++------------- src/game/tetromino/placing.h | 12 +- src/game/tetromino/shapes.c | 44 +++--- src/game/tetromino/shapes.h | 24 ++-- src/io/audio.c | 256 +++++++++++++++++------------------ src/io/audio.h | 22 +-- src/io/colour/colour32.h | 16 +-- src/io/colour/colour8.h | 8 +- src/io/render.c | 176 ++++++++++++------------ src/io/render.h | 16 +-- src/main.c | 64 ++++----- src/util/compat.h | 12 +- 19 files changed, 599 insertions(+), 605 deletions(-) diff --git a/.clang-format b/.clang-format index b19a042..b8b00bc 100644 --- a/.clang-format +++ b/.clang-format @@ -6,7 +6,7 @@ BasedOnStyle: '' # (LLVM,Google,Chromium,Mozilla,Web Standard: Auto # automatically detect the language version ColumnLimit: 0 # 0: disable column limit LineEnding: LF # use LF line endings -UseTab: Never # (Never,ForIndentation,ForContinuationAndIndentation,Always) +UseTab: ForContinuationAndIndentation # (Never,ForIndentation,ForContinuationAndIndentation,Always) TabWidth: 4 # recommended to set this equal to IndentWidth IndentWidth: 4 # how wide each indent is ContinuationIndentWidth: 4 # width for a line continuation diff --git a/.editorconfig b/.editorconfig index 9957977..1d9052e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,22 +1,16 @@ -root = true - [*] charset = utf-8 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true -[*.{rs}] -indent_style = space -indent_size = 4 - [*.{c,h,cpp,hpp}] -indent_style = space -indent_size = 4 +indent_style = tab +indent_size = tab [makefile] indent_style = tab -indent_size = 2 +indent_size = tab [*.{yaml,json}] indent_style = space diff --git a/src/error.h b/src/error.h index e672cff..6b24216 100644 --- a/src/error.h +++ b/src/error.h @@ -6,27 +6,27 @@ /* defines statuses in the 0..127, any higher/negative values are POSIX-reserved. * The max value (or -1) shall mean the application is running, anything else shall mean an exit code of some kind */ enum gamestatus { - // clang-format off - STATUS_SUCCESS = 0, // 0; successful exit - STATUS_ERROR = 1, // miscellaneous error - ERROR_INIT = STATUS_ERROR | 2, // initialisation error + // clang-format off + STATUS_SUCCESS = 0, // 0; successful exit + STATUS_ERROR = 1, // miscellaneous error + ERROR_INIT = STATUS_ERROR | 2, // initialisation error - ERROR_STD = STATUS_ERROR | 64, // standard library error - ERROR_STD_INIT = ERROR_INIT | 64, // standard library initialisation error - ERROR_STD_MEMORY = ERROR_STD | 32, // memory error - ERROR_STD_MEMORY_INIT = ERROR_STD_INIT | 32, // memory initialization error + ERROR_STD = STATUS_ERROR | 64, // standard library error + ERROR_STD_INIT = ERROR_INIT | 64, // standard library initialisation error + ERROR_STD_MEMORY = ERROR_STD | 32, // memory error + ERROR_STD_MEMORY_INIT = ERROR_STD_INIT | 32, // memory initialization error - ERROR_SDL = STATUS_ERROR | 32, // SDL error - ERROR_SDL_INIT = ERROR_INIT | 32, // SDL initialization error - ERROR_SDL_RENDERING = ERROR_SDL | 16, // rendering error - ERROR_SDL_RENDERING_INIT = ERROR_SDL_INIT | 16, // rendering initialization error - ERROR_SDL_AUDIO = ERROR_SDL | 8, // audio error - ERROR_SDL_AUDIO_INIT = ERROR_SDL_INIT | 8, // audio initialization error - ERROR_SDL_FONT = ERROR_SDL | 4, // font error - ERROR_SDL_FONT_INIT = ERROR_SDL_INIT | 4, // font initialization error + ERROR_SDL = STATUS_ERROR | 32, // SDL error + ERROR_SDL_INIT = ERROR_INIT | 32, // SDL initialization error + ERROR_SDL_RENDERING = ERROR_SDL | 16, // rendering error + ERROR_SDL_RENDERING_INIT = ERROR_SDL_INIT | 16, // rendering initialization error + ERROR_SDL_AUDIO = ERROR_SDL | 8, // audio error + ERROR_SDL_AUDIO_INIT = ERROR_SDL_INIT | 8, // audio initialization error + ERROR_SDL_FONT = ERROR_SDL | 4, // font error + ERROR_SDL_FONT_INIT = ERROR_SDL_INIT | 4, // font initialization error - STATUS_RUNNING = -1, - // clang-format on + STATUS_RUNNING = -1, + // clang-format on }; #if __INCLUDE_LEVEL__ > 0 @@ -43,8 +43,8 @@ enum gamestatus { #define error(s, ...) fprintf(stderr, "\033[91m" __FILE__ ":" MACRO_STR2(__LINE__) ": [ERR]: " s "\033[0m\n" __VA_OPT__(, __VA_ARGS__)) #define fatal(c, s, ...) \ - do { \ - printf("\033[101m" __FILE__ ":" MACRO_STR2(__LINE__) ": [FAT]: " s "\033[0m\n" __VA_OPT__(, __VA_ARGS__)); \ - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "something went wrong! :O", "view stderr for full details: \n" s, NULL); \ - exit(c); \ - } while (0) + do { \ + printf("\033[101m" __FILE__ ":" MACRO_STR2(__LINE__) ": [FAT]: " s "\033[0m\n" __VA_OPT__(, __VA_ARGS__)); \ + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "something went wrong! :O", "view stderr for full details: \n" s, NULL); \ + exit(c); \ + } while (0) diff --git a/src/game/game.c b/src/game/game.c index 893f6c4..a70cd99 100644 --- a/src/game/game.c +++ b/src/game/game.c @@ -15,138 +15,138 @@ /* shuffle the array using a Fisher–Yates shuffle */ static inline void shuffle(uint8_t const size, shape_id* const elmnts) { - for (uint8_t i = 0; i < (size - 1); i++) { - uint8_t const j = i + rand() % (size - i); - shape_id const cache = elmnts[i]; - elmnts[i] = elmnts[j]; - elmnts[j] = cache; - } + for (uint8_t i = 0; i < (size - 1); i++) { + uint8_t const j = i + rand() % (size - i); + shape_id const cache = elmnts[i]; + elmnts[i] = elmnts[j]; + elmnts[j] = cache; + } } void next_shape(gamedata* const dat) { - dat->curr_idx++; // increase the current shape index - dat->sel_x = COLUMNS / 2 - SHAPE_WIDTH / 2; // move the shape position to the centre - dat->sel_y = 0; + dat->curr_idx++; // increase the current shape index + dat->sel_x = COLUMNS / 2 - SHAPE_WIDTH / 2; // move the shape position to the centre + dat->sel_y = 0; - // return if know which shape is next - if (dat->curr_idx < (TETROMINO_COUNT - 1)) - return; + // return if know which shape is next + if (dat->curr_idx < (TETROMINO_COUNT - 1)) + return; - dat->curr_idx = 0; + dat->curr_idx = 0; - shuffle(TETROMINO_COUNT - 1, dat->nxt); - shape_id cache = dat->nxt[0]; - dat->nxt[0] = dat->nxt[TETROMINO_COUNT - 1]; - dat->nxt[TETROMINO_COUNT - 1] = cache; + shuffle(TETROMINO_COUNT - 1, dat->nxt); + shape_id cache = dat->nxt[0]; + dat->nxt[0] = dat->nxt[TETROMINO_COUNT - 1]; + dat->nxt[TETROMINO_COUNT - 1] = cache; } void game_init(gamedata* const dat) { - // set a random seed using the system clock - srand(time(NULL)); + // set a random seed using the system clock + srand(time(NULL)); - struct gametime gt = {{0}, 0}; - gametime_get(>.ts); + struct gametime gt = {{0}, 0}; + gametime_get(>.ts); - // initialize audio device - audiodevice* ad = audio_device_init(32000, AUDIO_S16, 1, 4096); + // initialize audio device + audiodevice* ad = audio_device_init(32000, AUDIO_S16, 1, 4096); - *dat = (gamedata){ - {0}, // rowdat - {0}, // row - gt, // time - ad, // audio_device - audio_wav_load(ad, "korobeiniki.wav"), // music - audio_wav_load(ad, "place.wav"), // place_sfx - 0, // score - {0}, // nxt - 0, // curr_idx - 0, // sel_x - 0, // sel_y - true, // run - }; + *dat = (gamedata){ + {0}, // rowdat + {0}, // row + gt, // time + ad, // audio_device + audio_wav_load(ad, "korobeiniki.wav"), // music + audio_wav_load(ad, "place.wav"), // place_sfx + 0, // score + {0}, // nxt + 0, // curr_idx + 0, // sel_x + 0, // sel_y + true, // run + }; - // initialize the rows within the game data - for (int8_t i = 0; i < ROWS; i++) { - dat->rows[i] = dat->rowdat + (i * COLUMNS); - } + // initialize the rows within the game data + for (int8_t i = 0; i < ROWS; i++) { + dat->rows[i] = dat->rowdat + (i * COLUMNS); + } - // set the shape data in each slot to it's corrsponding ID - for (shape_id i = 0; i < TETROMINO_COUNT; i++) - dat->nxt[i] = i; + // set the shape data in each slot to it's corrsponding ID + for (shape_id i = 0; i < TETROMINO_COUNT; i++) + dat->nxt[i] = i; - dat->curr_idx = -1; // set the current index to the max so it becomes zero after increasement - next_shape(dat); // select the next shape (shuffle should not be triggered) - shuffle(TETROMINO_COUNT, dat->nxt); // manually trigger a shuffle + dat->curr_idx = -1; // set the current index to the max so it becomes zero after increasement + next_shape(dat); // select the next shape (shuffle should not be triggered) + shuffle(TETROMINO_COUNT, dat->nxt); // manually trigger a shuffle } // updates the gametime static inline void update_gametime(gamedata* dat) { - struct timespec ts; - gametime_get(&ts); - dat->time.ms = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; - dat->time.ts = ts; + struct timespec ts; + gametime_get(&ts); + dat->time.ms = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; + dat->time.ts = ts; } // called every time the game's state is updated void game_update(gamedata* const dat) { - static time_t timer_update = 0; - static time_t timer_music = 0; - static time_t timer_move = 0; - static time_t timer_rot = 0; - update_gametime(dat); - uint8_t const* keys = SDL_GetKeyboardState(NULL); + static time_t timer_update = 0; + static time_t timer_music = 0; + static time_t timer_move = 0; + static time_t timer_rot = 0; + update_gametime(dat); + uint8_t const* keys = SDL_GetKeyboardState(NULL); - if (keys[SDL_SCANCODE_ESCAPE]) - dat->run = false; + if (keys[SDL_SCANCODE_ESCAPE]) + dat->run = false; - input_data move = MOVE_NONE; // contains the move data - time_t ctime = dat->time.ms; + input_data move = MOVE_NONE; // contains the move data + time_t ctime = dat->time.ms; - if (ctime > timer_update) { - timer_update = ctime + 500; - move |= MOVE_DOWN; - } + if (ctime > timer_update) { + timer_update = ctime + 500; + move |= MOVE_DOWN; + } - if (ctime > timer_music) { - timer_music = ctime + (dat->music.ms); - audio_play(dat->audio_device, &dat->music); - } + if (ctime > timer_music) { + timer_music = ctime + (dat->music.ms); + audio_play(dat->audio_device, &dat->music); + } - // for rotation updating - if (ctime > timer_rot) { - input_data urot = MOVE_NONE; - if (keys[SDL_SCANCODE_Q]) urot |= MOVE_ROTLEFT; - if (keys[SDL_SCANCODE_E]) urot |= MOVE_ROTRIGHT; + // for rotation updating + if (ctime > timer_rot) { + input_data urot = MOVE_NONE; + if (keys[SDL_SCANCODE_Q]) urot |= MOVE_ROTLEFT; + if (keys[SDL_SCANCODE_E]) urot |= MOVE_ROTRIGHT; - if (urot != MOVE_NONE) { - timer_rot = ctime + 100; - move |= urot; - } - } + if (urot != MOVE_NONE) { + timer_rot = ctime + 100; + move |= urot; + } + } - // for movement updating - if (ctime > timer_move) { - input_data umove = MOVE_NONE; - if (keys[SDL_SCANCODE_LEFT] || keys[SDL_SCANCODE_A]) umove |= MOVE_LEFT; - if (keys[SDL_SCANCODE_RIGHT] || keys[SDL_SCANCODE_D]) umove |= MOVE_RIGHT; - if (keys[SDL_SCANCODE_DOWN] || keys[SDL_SCANCODE_S] || keys[SDL_SCANCODE_SPACE]) umove |= MOVE_DOWN; + // for movement updating + if (ctime > timer_move) { + input_data umove = MOVE_NONE; + if (keys[SDL_SCANCODE_LEFT] || keys[SDL_SCANCODE_A]) umove |= MOVE_LEFT; + if (keys[SDL_SCANCODE_RIGHT] || keys[SDL_SCANCODE_D]) umove |= MOVE_RIGHT; + if (keys[SDL_SCANCODE_DOWN] || keys[SDL_SCANCODE_S] || keys[SDL_SCANCODE_SPACE]) umove |= MOVE_DOWN; - if (umove != MOVE_NONE) { - timer_move = ctime + 20; - move |= umove; - } - } + if (umove != MOVE_NONE) { + timer_move = ctime + 20; + move |= umove; + } + } - // update the block position - if (move != MOVE_NONE) - place_update(dat, move); + // update the block position + if (move != MOVE_NONE) + place_update(dat, move); } void game_free(gamedata* const dat) { - audio_wav_unload(&dat->music); - audio_wav_unload(&dat->place_sfx); - audio_device_free(dat->audio_device); + audio_wav_unload(&dat->music); + audio_wav_unload(&dat->place_sfx); + audio_device_free(dat->audio_device); - // zero-out the rest of the data - *dat = (gamedata){0}; + // zero-out the rest of the data + *dat = (gamedata){0}; } diff --git a/src/game/game.h b/src/game/game.h index 82f00e6..ae9327e 100644 --- a/src/game/game.h +++ b/src/game/game.h @@ -22,18 +22,18 @@ typedef colour8 const* const row_const; typedef colour8* row; typedef struct { - colour8 rowdat[ROWS * COLUMNS]; - colour8* rows[ROWS]; - struct gametime time; - audiodevice* audio_device; - audiodata music; - audiodata place_sfx; - uint16_t score; - shape_id nxt[7]; // the order of the shape ids that they should appear in - uint8_t curr_idx; // current shape index - int8_t sel_x; // selected shape x position - int8_t sel_y; // selected shape y position - bool run; + colour8 rowdat[ROWS * COLUMNS]; + colour8* rows[ROWS]; + struct gametime time; + audiodevice* audio_device; + audiodata music; + audiodata place_sfx; + uint16_t score; + shape_id nxt[7]; // the order of the shape ids that they should appear in + uint8_t curr_idx; // current shape index + int8_t sel_x; // selected shape x position + int8_t sel_y; // selected shape y position + bool run; } gamedata; void next_shape(gamedata*); // initializes everything needed to start the game; outputs to gamedata diff --git a/src/game/gametime.h b/src/game/gametime.h index 0014c72..aa136fb 100644 --- a/src/game/gametime.h +++ b/src/game/gametime.h @@ -2,8 +2,8 @@ #include struct gametime { - struct timespec ts; - time_t ms; + struct timespec ts; + time_t ms; }; #if __has_include() @@ -12,17 +12,17 @@ struct gametime { #if __has_include() && _POSIX_C_SOURCE >= 199309L #include static inline void gametime_get(struct timespec* ts) { - clock_gettime(CLOCK_MONOTONIC, ts); + clock_gettime(CLOCK_MONOTONIC, ts); } #elif defined(_WIN32) #include #include #include static inline void gametime_get(struct timespec* ts) { - LARGE_INTEGER cnt, frq; - QueryPerformanceCounter(&cnt); - QueryPerformanceFrequency(&frq); - ts->tv_sec = (time_t)(cnt.QuadPart / frq.QuadPart); - ts->tv_nsec = (time_t)((cnt.QuadPart % frq.QuadPart) * 1000000000 / frq.QuadPart); + LARGE_INTEGER cnt, frq; + QueryPerformanceCounter(&cnt); + QueryPerformanceFrequency(&frq); + ts->tv_sec = (time_t)(cnt.QuadPart / frq.QuadPart); + ts->tv_nsec = (time_t)((cnt.QuadPart % frq.QuadPart) * 1000000000 / frq.QuadPart); } #endif diff --git a/src/game/paths.c b/src/game/paths.c index cb074c4..90db4ed 100644 --- a/src/game/paths.c +++ b/src/game/paths.c @@ -13,56 +13,56 @@ char const* restrict path_place_sfx = NULL; // gets the game's data path, returns 0 on failure, otherwise the datapath's string length static unsigned getdatpath(void) { - char const* home = getenv(unixonly("HOME") winonly("APPDATA")); // get the user data directory path (appropriated for each platform) - if (!home) home = "."; // if this failed, set the path to `.`, which represents cwd + char const* home = getenv(unixonly("HOME") winonly("APPDATA")); // get the user data directory path (appropriated for each platform) + if (!home) home = "."; // if this failed, set the path to `.`, which represents cwd - unsigned len = strlen(home); - len += 1 + 20 unixonly(+13); // add 21 bytes to the home length, to account for adding .local/share later - char* datpath = malloc(len); - if (!datpath) return 0; + unsigned len = strlen(home); + len += 1 + 20 unixonly(+13); // add 21 bytes to the home length, to account for adding .local/share later + char* datpath = malloc(len); + if (!datpath) return 0; - // copy the data from home into the datapath - strcpy(datpath, home); + // copy the data from home into the datapath + strcpy(datpath, home); #ifdef __unix__ - // include the .local/share directory, if the HOME environment variable was valid - if (home[0] != '.') strcat(datpath, "/.local/share"); - else { - // if the HOME directory wasn't defined, shrink the string - len -= 13; - void* ptr = realloc(datpath, len); - if (ptr) datpath = ptr; // likely doesn't actually change the pointer, but just to be sure - } + // include the .local/share directory, if the HOME environment variable was valid + if (home[0] != '.') strcat(datpath, "/.local/share"); + else { + // if the HOME directory wasn't defined, shrink the string + len -= 13; + void* ptr = realloc(datpath, len); + if (ptr) datpath = ptr; // likely doesn't actually change the pointer, but just to be sure + } #endif - strcat(datpath, PATH_SEP_STR "quinns_tetris_clone"); - path_dat = datpath; - return len; + strcat(datpath, PATH_SEP_STR "quinns_tetris_clone"); + path_dat = datpath; + return len; } static inline char const* init_path(char const* restrict const str, unsigned len) { - void* ptr = malloc(len); - if (!ptr) return NULL; - strcpy(ptr, path_dat); - strcat(ptr, str); - return ptr; + void* ptr = malloc(len); + if (!ptr) return NULL; + strcpy(ptr, path_dat); + strcat(ptr, str); + return ptr; } int paths_init(void) { - unsigned len = getdatpath(); - if (!len) return 1; + unsigned len = getdatpath(); + if (!len) return 1; - // these are explicitly static, as string literals just work like that - path_opts = init_path("/opts.cfg", len + 9); // TODO: shouldn't opts be stored at .config/? - path_font = init_path("/pixeldroid_botic-regular.ttf", len + 29); // TODO: these three paths should not be stored like opts - path_music = init_path("/korobeiniki.wav", len + 16); - path_place_sfx = init_path("place.wav", len + 10); - return -(!path_opts || !path_font || !path_music || !path_place_sfx); + // these are explicitly static, as string literals just work like that + path_opts = init_path("/opts.cfg", len + 9); // TODO: shouldn't opts be stored at .config/? + path_font = init_path("/pixeldroid_botic-regular.ttf", len + 29); // TODO: these three paths should not be stored like opts + path_music = init_path("/korobeiniki.wav", len + 16); + path_place_sfx = init_path("place.wav", len + 10); + return -(!path_opts || !path_font || !path_music || !path_place_sfx); } void paths_free(void) { - free((void*)path_dat), path_dat = NULL; - free((void*)path_opts), path_opts = NULL; - free((void*)path_music), path_music = NULL; - free((void*)path_place_sfx), path_place_sfx = NULL; + free((void*)path_dat), path_dat = NULL; + free((void*)path_opts), path_opts = NULL; + free((void*)path_music), path_music = NULL; + free((void*)path_place_sfx), path_place_sfx = NULL; } diff --git a/src/game/tetromino/placing.c b/src/game/tetromino/placing.c index 36c2352..41ba5bf 100644 --- a/src/game/tetromino/placing.c +++ b/src/game/tetromino/placing.c @@ -9,136 +9,136 @@ static int is_filled(row_const const row) { - for (int8_t x = 0; x < COLUMNS; x++) { - if (row[x] == 0) { - return 0; - } - } + for (int8_t x = 0; x < COLUMNS; x++) { + if (row[x] == 0) { + return 0; + } + } - return 1; + return 1; } static void clear_rows(row* const rows, uint16_t* const score) { - row cache[4] = {0}; // you can only clear four rows at a time - unsigned filled = 0; - unsigned checked = 0; + row cache[4] = {0}; // you can only clear four rows at a time + unsigned filled = 0; + unsigned checked = 0; - // loop through each row (excluding the empty rows at the top when clearing a line) - for (unsigned y = 0; y < (ROWS - filled); y++) { - int const i = (ROWS - 1) - y; // get the index starting from the bottom + // loop through each row (excluding the empty rows at the top when clearing a line) + for (unsigned y = 0; y < (ROWS - filled); y++) { + int const i = (ROWS - 1) - y; // get the index starting from the bottom - rows[i] = rows[i - filled]; // set the row to the new or same address + rows[i] = rows[i - filled]; // set the row to the new or same address - // continue if the line isn't filled or the max amount has been reached - if (checked >= 4 || !is_filled(rows[i])) { - if (filled > 0 && checked < 4) checked++; - continue; // continue to the next line - } + // continue if the line isn't filled or the max amount has been reached + if (checked >= 4 || !is_filled(rows[i])) { + if (filled > 0 && checked < 4) checked++; + continue; // continue to the next line + } - cache[filled] = rows[i]; // cache the current row address - filled++; // increase filled, and keep the row in the cache - checked++; // increase the checked count - y--; // decrease y to check this line again - } + cache[filled] = rows[i]; // cache the current row address + filled++; // increase filled, and keep the row in the cache + checked++; // increase the checked count + y--; // decrease y to check this line again + } - if (filled == 0) return; - *score += 8 << filled; + if (filled == 0) return; + *score += 8 << filled; - // do while, as we already know that entering the loop that filled is non-zero - do { - filled--; - rows[filled] = cache[filled]; + // do while, as we already know that entering the loop that filled is non-zero + do { + filled--; + rows[filled] = cache[filled]; - // zero out the filled row - for (unsigned x = 0; x < COLUMNS; x++) - cache[filled][x] = 0; - } while (filled > 0); + // zero out the filled row + for (unsigned x = 0; x < COLUMNS; x++) + cache[filled][x] = 0; + } while (filled > 0); } // sets a shape to the screen static void set_shape_i(row const* const row, shape_id const id, int8_t const pos_x) { - shape const shape = shape_from_id(id); - colour8 const colour = colour_from_id(id); - for (int8_t y = 0; y < SHAPE_HEIGHT; y++) { - shape_row const shape_row = shape_get_row(shape, y); + shape const shape = shape_from_id(id); + colour8 const colour = colour_from_id(id); + for (int8_t y = 0; y < SHAPE_HEIGHT; y++) { + shape_row const shape_row = shape_get_row(shape, y); - if (shape_row == 0) - continue; + if (shape_row == 0) + continue; - for (int8_t x = 0; x < SHAPE_WIDTH; x++) - if (shape_is_set(shape_row, x)) - row[y][x + pos_x] = colour; - } + for (int8_t x = 0; x < SHAPE_WIDTH; x++) + if (shape_is_set(shape_row, x)) + row[y][x + pos_x] = colour; + } } static inline void set_shape(row const* const row, shape_id const id, int8_t const pos_x, int8_t const pos_y) { - set_shape_i(&row[pos_y], id, pos_x); // calls itself, but omitting the pos_y argument, instead opting for specifying the row + set_shape_i(&row[pos_y], id, pos_x); // calls itself, but omitting the pos_y argument, instead opting for specifying the row } static int shape_intersects(row const* const rows, shape_id const id, int8_t const x, int8_t const y) { - shape const shape = shape_from_id(id); + shape const shape = shape_from_id(id); - for (int y0 = 0; y0 < SHAPE_HEIGHT; y0++) { - shape_row const shape_row = shape_get_row(shape, y0); // get the shape row - if (shape_row == 0) continue; // if the row doesn't contain data; continue + for (int y0 = 0; y0 < SHAPE_HEIGHT; y0++) { + shape_row const shape_row = shape_get_row(shape, y0); // get the shape row + if (shape_row == 0) continue; // if the row doesn't contain data; continue - for (int x0 = 0; x0 < SHAPE_WIDTH; x0++) { - if (shape_is_set(shape_row, x0) == false) continue; // if the bit isn't set at this index; continue - int const x1 = x + x0; - int const y1 = y + y0; + for (int x0 = 0; x0 < SHAPE_WIDTH; x0++) { + if (shape_is_set(shape_row, x0) == false) continue; // if the bit isn't set at this index; continue + int const x1 = x + x0; + int const y1 = y + y0; - if (x1 < 0 || x1 >= COLUMNS) return 1; // if X is out of bounds - if (y1 < 0 || y1 >= ROWS) return 1; // if Y is out of bounds - if (rows[y1][x1] != 0) return 1; // if there is a block here - } - } - return 0; + if (x1 < 0 || x1 >= COLUMNS) return 1; // if X is out of bounds + if (y1 < 0 || y1 >= ROWS) return 1; // if Y is out of bounds + if (rows[y1][x1] != 0) return 1; // if there is a block here + } + } + return 0; } static inline shape_id rotate_id(shape_id const id, int const dir) { - return (id + dir) & 31; + return (id + dir) & 31; } void place_update(gamedata* const game_data, input_data const move) { - // store the current index and ID, only changes when placed (which yields no movement) and rotation (which occurs last) - uint8_t const curr_idx = game_data->curr_idx; - shape_id const curr_id = game_data->nxt[curr_idx]; + // store the current index and ID, only changes when placed (which yields no movement) and rotation (which occurs last) + uint8_t const curr_idx = game_data->curr_idx; + shape_id const curr_id = game_data->nxt[curr_idx]; - // set the shape if we moved vertically and intersected - if (move & 4) { - int8_t const y = game_data->sel_y + 1; - if (shape_intersects(game_data->rows, curr_id, game_data->sel_x, y)) { - set_shape(game_data->rows, curr_id, game_data->sel_x, game_data->sel_y); // if the shape intersects vertically, write the shape at the current position and return - clear_rows(game_data->rows, &game_data->score); // clear the rows that have been completed + // set the shape if we moved vertically and intersected + if (move & 4) { + int8_t const y = game_data->sel_y + 1; + if (shape_intersects(game_data->rows, curr_id, game_data->sel_x, y)) { + set_shape(game_data->rows, curr_id, game_data->sel_x, game_data->sel_y); // if the shape intersects vertically, write the shape at the current position and return + clear_rows(game_data->rows, &game_data->score); // clear the rows that have been completed - audio_play(game_data->audio_device, &game_data->place_sfx); + audio_play(game_data->audio_device, &game_data->place_sfx); - next_shape(game_data); - if (shape_intersects(game_data->rows, game_data->curr_idx, game_data->sel_x, game_data->sel_y)) - game_data->run = false; - return; - } + next_shape(game_data); + if (shape_intersects(game_data->rows, game_data->curr_idx, game_data->sel_x, game_data->sel_y)) + game_data->run = false; + return; + } - // otherwise, just set Y - game_data->sel_y = y; - } + // otherwise, just set Y + game_data->sel_y = y; + } - // update shape's X coordinate movement - if ((move & 3) != 3 && (move & 3)) { - int8_t const x = game_data->sel_x + ((move & 3) == 1 ? -1 : 1); // either move along -x or +x - if (shape_intersects(game_data->rows, curr_id, x, game_data->sel_y) == false) { - game_data->sel_x = x; // set X if the shape does not intersect - } - } + // update shape's X coordinate movement + if ((move & 3) != 3 && (move & 3)) { + int8_t const x = game_data->sel_x + ((move & 3) == 1 ? -1 : 1); // either move along -x or +x + if (shape_intersects(game_data->rows, curr_id, x, game_data->sel_y) == false) { + game_data->sel_x = x; // set X if the shape does not intersect + } + } - // update the shape's rotation - if (move & 8 || move & 16) { - shape_id const id = move & 8 // check which direction we should move - ? rotate_id(curr_id, -8) - : rotate_id(curr_id, 8); - if (shape_intersects(game_data->rows, id, game_data->sel_x, game_data->sel_y) == false) { - game_data->nxt[curr_idx] = id; - } - } + // update the shape's rotation + if (move & 8 || move & 16) { + shape_id const id = move & 8 // check which direction we should move + ? rotate_id(curr_id, -8) + : rotate_id(curr_id, 8); + if (shape_intersects(game_data->rows, id, game_data->sel_x, game_data->sel_y) == false) { + game_data->nxt[curr_idx] = id; + } + } } diff --git a/src/game/tetromino/placing.h b/src/game/tetromino/placing.h index e3ef5cc..df6b6cc 100644 --- a/src/game/tetromino/placing.h +++ b/src/game/tetromino/placing.h @@ -7,12 +7,12 @@ typedef uint8_t input_data; enum { - MOVE_NONE = 0, - MOVE_LEFT = 1, - MOVE_RIGHT = 2, - MOVE_DOWN = 4, - MOVE_ROTLEFT = 8, - MOVE_ROTRIGHT = 16, + MOVE_NONE = 0, + MOVE_LEFT = 1, + MOVE_RIGHT = 2, + MOVE_DOWN = 4, + MOVE_ROTLEFT = 8, + MOVE_ROTRIGHT = 16, }; void place_update(gamedata* game_data, input_data move); diff --git a/src/game/tetromino/shapes.c b/src/game/tetromino/shapes.c index d41feb8..6494dcd 100644 --- a/src/game/tetromino/shapes.c +++ b/src/game/tetromino/shapes.c @@ -36,30 +36,30 @@ #define SHAPE_J_270 ((shape)0x0E20) // 0000 1110 0010 0000 the J tetromino with a 270° rotation shape shape_from_id(shape_id const id) { - static shape const shapes[TETROMINO_COUNT][4] = { - // 0° 90° 180° 170° - {SHAPE_O, SHAPE_O, SHAPE_O, SHAPE_O }, - {SHAPE_I, SHAPE_I_90, SHAPE_I_180, SHAPE_I_270}, - {SHAPE_S, SHAPE_S_90, SHAPE_S_180, SHAPE_S_270}, - {SHAPE_Z, SHAPE_Z_90, SHAPE_Z_180, SHAPE_Z_270}, - {SHAPE_T, SHAPE_T_90, SHAPE_T_180, SHAPE_T_270}, - {SHAPE_L, SHAPE_L_90, SHAPE_L_180, SHAPE_L_270}, - {SHAPE_J, SHAPE_J_90, SHAPE_J_180, SHAPE_J_270}, - }; + static shape const shapes[TETROMINO_COUNT][4] = { + // 0° 90° 180° 170° + {SHAPE_O, SHAPE_O, SHAPE_O, SHAPE_O }, + {SHAPE_I, SHAPE_I_90, SHAPE_I_180, SHAPE_I_270}, + {SHAPE_S, SHAPE_S_90, SHAPE_S_180, SHAPE_S_270}, + {SHAPE_Z, SHAPE_Z_90, SHAPE_Z_180, SHAPE_Z_270}, + {SHAPE_T, SHAPE_T_90, SHAPE_T_180, SHAPE_T_270}, + {SHAPE_L, SHAPE_L_90, SHAPE_L_180, SHAPE_L_270}, + {SHAPE_J, SHAPE_J_90, SHAPE_J_180, SHAPE_J_270}, + }; - // first 3 bits is the shape type, the rest is rotation data - return shapes[id & 7][id >> 3]; + // first 3 bits is the shape type, the rest is rotation data + return shapes[id & 7][id >> 3]; } colour8 colour_from_id(shape_id const id) { - switch (id & 7) { - case TETROMINO_O: return COLOUR8_YELLOW; - case TETROMINO_I: return COLOUR8_CYAN; - case TETROMINO_S: return COLOUR8_GREEN; - case TETROMINO_Z: return COLOUR8_RED; - case TETROMINO_T: return COLOUR8_MAGENTA; - case TETROMINO_L: return COLOUR8_ORANGE; - case TETROMINO_J: return COLOUR8_BLUE; - default: return COLOUR8_BLACK; - } + switch (id & 7) { + case TETROMINO_O: return COLOUR8_YELLOW; + case TETROMINO_I: return COLOUR8_CYAN; + case TETROMINO_S: return COLOUR8_GREEN; + case TETROMINO_Z: return COLOUR8_RED; + case TETROMINO_T: return COLOUR8_MAGENTA; + case TETROMINO_L: return COLOUR8_ORANGE; + case TETROMINO_J: return COLOUR8_BLUE; + default: return COLOUR8_BLACK; + } } diff --git a/src/game/tetromino/shapes.h b/src/game/tetromino/shapes.h index 21865d6..f7add24 100644 --- a/src/game/tetromino/shapes.h +++ b/src/game/tetromino/shapes.h @@ -9,16 +9,16 @@ typedef uint8_t shape_row; typedef uint8_t shape_id; enum { - TETROMINO_O = 0, - TETROMINO_I = 1, - TETROMINO_S = 2, - TETROMINO_Z = 3, - TETROMINO_T = 4, - TETROMINO_L = 5, - TETROMINO_J = 6, - TETROMINO_ROTATED_90 = 8, - TETROMINO_ROTATED_180 = 16, - TETROMINO_ROTATED_270 = 24, + TETROMINO_O = 0, + TETROMINO_I = 1, + TETROMINO_S = 2, + TETROMINO_Z = 3, + TETROMINO_T = 4, + TETROMINO_L = 5, + TETROMINO_J = 6, + TETROMINO_ROTATED_90 = 8, + TETROMINO_ROTATED_180 = 16, + TETROMINO_ROTATED_270 = 24, }; #define SHAPE_WIDTH 4 @@ -28,11 +28,11 @@ enum { static inline shape_row shape_get_row(shape const shape, uint8_t const index) { - return shape >> (((SHAPE_HEIGHT - 1) - index) * SHAPE_WIDTH) & 0xF; + return shape >> (((SHAPE_HEIGHT - 1) - index) * SHAPE_WIDTH) & 0xF; } static inline bool shape_is_set(shape_row const row, uint8_t const index) { - return (row >> ((SHAPE_WIDTH - 1) - index) & 1) != 0; + return (row >> ((SHAPE_WIDTH - 1) - index) & 1) != 0; } shape shape_from_id(shape_id id); diff --git a/src/io/audio.c b/src/io/audio.c index 5dc4ac6..131759f 100644 --- a/src/io/audio.c +++ b/src/io/audio.c @@ -11,179 +11,179 @@ #include "../util/compat.h" static void audiomixer(void* const userdata, uint8_t* const stream, int const len) { - memset(stream, 0, len); // clear the playing audio - audiodevice* const dev = userdata; // retreive the callback data + memset(stream, 0, len); // clear the playing audio + audiodevice* const dev = userdata; // retreive the callback data - // return if dev is null, since it can fail to initialize - if (dev == NULL) return; + // return if dev is null, since it can fail to initialize + if (dev == NULL) return; - struct audioplayer* prev = NULL; - struct audioplayer* curr = dev->audio_players; - while (curr != NULL) { - // if the current audio fragment has reached the end of their data - if (curr->len == 0) { - struct audioplayer* ncurr = curr->nxt; + struct audioplayer* prev = NULL; + struct audioplayer* curr = dev->audio_players; + while (curr != NULL) { + // if the current audio fragment has reached the end of their data + if (curr->len == 0) { + struct audioplayer* ncurr = curr->nxt; - // free the memory allocated to it and assign the next to to the currently playing - free(curr); - curr = ncurr; + // free the memory allocated to it and assign the next to to the currently playing + free(curr); + curr = ncurr; - // write to the audio device if prev hasn't been set yet - if (prev == NULL) - dev->audio_players = curr; - else - prev->nxt = curr; + // write to the audio device if prev hasn't been set yet + if (prev == NULL) + dev->audio_players = curr; + else + prev->nxt = curr; - // continue so if curr is now NULL, the loop stops - continue; - } + // continue so if curr is now NULL, the loop stops + continue; + } - // calculate how much of the current audio player we should mix into the stream - int const mixlen = SDL_min(curr->len, (unsigned)len); + // calculate how much of the current audio player we should mix into the stream + int const mixlen = SDL_min(curr->len, (unsigned)len); - // mix the current buffer into the stream, and update the audio player values accordingly - SDL_MixAudioFormat(stream, curr->buf, dev->fmt, mixlen, SDL_MIX_MAXVOLUME); - curr->buf += mixlen; - curr->len -= mixlen; + // mix the current buffer into the stream, and update the audio player values accordingly + SDL_MixAudioFormat(stream, curr->buf, dev->fmt, mixlen, SDL_MIX_MAXVOLUME); + curr->buf += mixlen; + curr->len -= mixlen; - // increment the current node - prev = curr; - curr = curr->nxt; - } + // increment the current node + prev = curr; + curr = curr->nxt; + } } // converts the inputted audio to the format of dev // returns 1 upon failure, 0 upon success. When 1 is returned *bufptr will be freed. Otherwise *bufptr is reallocated static int8_t audio_cvt(audiodevice const* dev, SDL_AudioSpec const* spec, uint8_t** bufptr, unsigned* len) { - // init the converter - SDL_AudioCVT cvt; - if (SDL_BuildAudioCVT(&cvt, spec->format, spec->channels, spec->freq, dev->fmt, dev->channels, dev->freq) < 0) { - error("%s:%u could not build the audio converter! SDL Error: %s", __FILE_NAME__, __LINE__, SDL_GetError()); - free(*bufptr); // free the buffer upon an error, as we won't be using this - return 1; - } else if (!cvt.needed) { // ensure the conversion is necessary - return 0; - } - cvt.len = (*len); // specify the length of the source data buffer in bytes (warn: uint32_t -> int32_t) - cvt.buf = realloc(*bufptr, cvt.len * cvt.len_mult); // grow the inputted buffer for the conversion + // init the converter + SDL_AudioCVT cvt; + if (SDL_BuildAudioCVT(&cvt, spec->format, spec->channels, spec->freq, dev->fmt, dev->channels, dev->freq) < 0) { + error("%s:%u could not build the audio converter! SDL Error: %s", __FILE_NAME__, __LINE__, SDL_GetError()); + free(*bufptr); // free the buffer upon an error, as we won't be using this + return 1; + } else if (!cvt.needed) { // ensure the conversion is necessary + return 0; + } + cvt.len = (*len); // specify the length of the source data buffer in bytes (warn: uint32_t -> int32_t) + cvt.buf = realloc(*bufptr, cvt.len * cvt.len_mult); // grow the inputted buffer for the conversion - // ensure the conversion buffer reallocation goes correctly - if (cvt.buf == NULL) { - error("%s:%u failed to reallocate the audio buffer to the new size of %u bytes!", __FILE_NAME__, __LINE__, cvt.len); - free(*bufptr); // free the inputted pointer, as realloc doesn't clear this address if it fails - return 1; - } + // ensure the conversion buffer reallocation goes correctly + if (cvt.buf == NULL) { + error("%s:%u failed to reallocate the audio buffer to the new size of %u bytes!", __FILE_NAME__, __LINE__, cvt.len); + free(*bufptr); // free the inputted pointer, as realloc doesn't clear this address if it fails + return 1; + } - // converts the audio to the new format - if (SDL_ConvertAudio(&cvt)) { - error("%s:%u something went wrong when loading/converting an audio buffer! SDL Error: %s", __FILE_NAME__, __LINE__, SDL_GetError()); - free(cvt.buf); // free the conversion buffer if it fails, as realloc moved the data to this adress; old adress is no longer valid - return 1; - } + // converts the audio to the new format + if (SDL_ConvertAudio(&cvt)) { + error("%s:%u something went wrong when loading/converting an audio buffer! SDL Error: %s", __FILE_NAME__, __LINE__, SDL_GetError()); + free(cvt.buf); // free the conversion buffer if it fails, as realloc moved the data to this adress; old adress is no longer valid + return 1; + } - // update output - *len = cvt.len_cvt; // set the length to the new length after the conversion - *bufptr = realloc(cvt.buf, cvt.len_cvt); // reallocate the buffer to the new size - if (*bufptr == NULL) { - warn("%s:%u something went wrong whilst shrinking the audio buffer whilst converting!", __FILE_NAME__, __LINE__); - *bufptr = cvt.buf; // use the conversion buffer, as this one will be valid if realloc fails - } + // update output + *len = cvt.len_cvt; // set the length to the new length after the conversion + *bufptr = realloc(cvt.buf, cvt.len_cvt); // reallocate the buffer to the new size + if (*bufptr == NULL) { + warn("%s:%u something went wrong whilst shrinking the audio buffer whilst converting!", __FILE_NAME__, __LINE__); + *bufptr = cvt.buf; // use the conversion buffer, as this one will be valid if realloc fails + } - return 0; + return 0; } audiodevice* audio_device_init(int freq, SDL_AudioFormat fmt, uint8_t channels, uint16_t samples) { - audiodevice* dev = malloc(sizeof(audiodevice)); + audiodevice* dev = malloc(sizeof(audiodevice)); - if (dev == NULL) { - error("%s:%u null pointer when allocating memory for the audio device!", __FILE_NAME__, __LINE__); - return NULL; - } + if (dev == NULL) { + error("%s:%u null pointer when allocating memory for the audio device!", __FILE_NAME__, __LINE__); + return NULL; + } - // define the audio specification - SDL_AudioSpec spec = {freq, fmt, channels, 0, samples, 0, 0, NULL, NULL}; - spec.callback = audiomixer; - spec.userdata = dev; + // define the audio specification + SDL_AudioSpec spec = {freq, fmt, channels, 0, samples, 0, 0, NULL, NULL}; + spec.callback = audiomixer; + spec.userdata = dev; - // create the audio device - *dev = (audiodevice){ - NULL, - SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0), - freq, - fmt, - channels, - }; + // create the audio device + *dev = (audiodevice){ + NULL, + SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0), + freq, + fmt, + channels, + }; - if (dev->id < 1) { - error("%s:%u audio device failed to open! SDL Error: %s", __FILE_NAME__, __LINE__, SDL_GetError()); - free(dev); - return NULL; - } + if (dev->id < 1) { + error("%s:%u audio device failed to open! SDL Error: %s", __FILE_NAME__, __LINE__, SDL_GetError()); + free(dev); + return NULL; + } - // default state of the device is paused, so we unpause it here - SDL_PauseAudioDevice(dev->id, 0); - return dev; + // default state of the device is paused, so we unpause it here + SDL_PauseAudioDevice(dev->id, 0); + return dev; } void audio_play(audiodevice* dev, audiodata const* audio) { - if (dev == NULL) return; // dev might fail to initialize - if (audio->len == 0) return; // audio might fail to initialize + if (dev == NULL) return; // dev might fail to initialize + if (audio->len == 0) return; // audio might fail to initialize - // create an audio player - struct audioplayer* player = malloc(sizeof(struct audioplayer)); - *player = (struct audioplayer){ - dev->audio_players, // set nxt to the first item in dev (can be NULL, this is fine) - audio->buf, - audio->len, - }; + // create an audio player + struct audioplayer* player = malloc(sizeof(struct audioplayer)); + *player = (struct audioplayer){ + dev->audio_players, // set nxt to the first item in dev (can be NULL, this is fine) + audio->buf, + audio->len, + }; - // assign ourselves to the first item - dev->audio_players = player; + // assign ourselves to the first item + dev->audio_players = player; } void audio_device_free(audiodevice* dev) { - if (dev == NULL) return; - SDL_CloseAudioDevice(dev->id); + if (dev == NULL) return; + SDL_CloseAudioDevice(dev->id); - struct audioplayer* curr = dev->audio_players; + struct audioplayer* curr = dev->audio_players; - // free all audio players - while (curr != NULL) { - dev->audio_players = curr->nxt; // use audio_players in dev as a cache - free(curr); - curr = dev->audio_players; - } + // free all audio players + while (curr != NULL) { + dev->audio_players = curr->nxt; // use audio_players in dev as a cache + free(curr); + curr = dev->audio_players; + } - // free the audio device itself - free(dev); + // free the audio device itself + free(dev); } audiodata audio_wav_load(audiodevice const* dev, char const* fpath) { - if (dev == NULL) return (audiodata){0}; - SDL_AudioSpec spec; - audiodata audio; + if (dev == NULL) return (audiodata){0}; + SDL_AudioSpec spec; + audiodata audio; - debug("loading audio file '%s'...", fpath); + debug("loading audio file '%s'...", fpath); - if (faccess(fpath, FA_R)) { - error("%s:%u audio file either isn't readable or doesn't exist. path: '%s'!", __FILE_NAME__, __LINE__, fpath); - return (audiodata){0}; - } + if (faccess(fpath, FA_R)) { + error("%s:%u audio file either isn't readable or doesn't exist. path: '%s'!", __FILE_NAME__, __LINE__, fpath); + return (audiodata){0}; + } - // load and parse the audio to the correct format - SDL_LoadWAV(fpath, &spec, &audio.buf, &audio.len); - if (audio_cvt(dev, &spec, &audio.buf, &audio.len)) { - return (audiodata){0}; - } + // load and parse the audio to the correct format + SDL_LoadWAV(fpath, &spec, &audio.buf, &audio.len); + if (audio_cvt(dev, &spec, &audio.buf, &audio.len)) { + return (audiodata){0}; + } - // calculate the time in milliseconds of the audio fragment - // by dividing the audio bytelength by the format's bitsize, by the audio device's channels and the audio device's frequency - audio.ms = (((1000 * audio.len) / (SDL_AUDIO_BITSIZE(dev->fmt) / 8)) / dev->channels / dev->freq); + // calculate the time in milliseconds of the audio fragment + // by dividing the audio bytelength by the format's bitsize, by the audio device's channels and the audio device's frequency + audio.ms = (((1000 * audio.len) / (SDL_AUDIO_BITSIZE(dev->fmt) / 8)) / dev->channels / dev->freq); - return audio; + return audio; } void audio_wav_unload(audiodata* audio) { - free(audio->buf); - *audio = (audiodata){0}; // zero out all audio data + free(audio->buf); + *audio = (audiodata){0}; // zero out all audio data } diff --git a/src/io/audio.h b/src/io/audio.h index 87c5b7a..ed86912 100644 --- a/src/io/audio.h +++ b/src/io/audio.h @@ -4,24 +4,24 @@ #include struct audiodata { - uint8_t* buf; // pointer to the audio buffer - uint32_t len; // length in bytes of the audio buffer - uint32_t ms; // length in miliseconds of the audio buffer + uint8_t* buf; // pointer to the audio buffer + uint32_t len; // length in bytes of the audio buffer + uint32_t ms; // length in miliseconds of the audio buffer }; // contains the data of the audio fragments to be played struct audioplayer { - struct audioplayer* nxt; // pointer to the next audioplayer (may be null) - uint8_t* buf; // pointer to the current item in the buffer to be played - uint32_t len; // the length in bytes that the buffer has remaining + struct audioplayer* nxt; // pointer to the next audioplayer (may be null) + uint8_t* buf; // pointer to the current item in the buffer to be played + uint32_t len; // the length in bytes that the buffer has remaining }; struct audiodevice { - struct audioplayer* audio_players; - SDL_AudioDeviceID id; - int freq; - SDL_AudioFormat fmt; - uint8_t channels; + struct audioplayer* audio_players; + SDL_AudioDeviceID id; + int freq; + SDL_AudioFormat fmt; + uint8_t channels; }; typedef struct audiodata audiodata; diff --git a/src/io/colour/colour32.h b/src/io/colour/colour32.h index dbe25fe..dd2fa1d 100644 --- a/src/io/colour/colour32.h +++ b/src/io/colour/colour32.h @@ -5,13 +5,13 @@ // stores colour in a rgba format, each channel being a 8 bits wide. typedef union { - uint32_t packed; - struct { - uint8_t a; - uint8_t b; - uint8_t g; - uint8_t r; - }; + uint32_t packed; + struct { + uint8_t a; + uint8_t b; + uint8_t g; + uint8_t r; + }; } colour32; #define COLOUR32_BLACK ((colour32){0x000000FF}) @@ -26,7 +26,7 @@ typedef union { // sets the render colour to a colour32 value static inline void set_colour32(SDL_Renderer* const renderer, colour32 const c) { - (void)SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, c.a); + (void)SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, c.a); } // american macros: diff --git a/src/io/colour/colour8.h b/src/io/colour/colour8.h index b3a8678..b62ce7a 100644 --- a/src/io/colour/colour8.h +++ b/src/io/colour/colour8.h @@ -19,22 +19,22 @@ typedef uint8_t colour8; // gets the red channel in 32 bit colour space static inline uint8_t colour8_red32(colour8 const colour) { - return (colour >> 5) * (255 / 7); + return (colour >> 5) * (255 / 7); } // gets the green channel in 32 bit colour space static inline uint8_t colour8_green32(colour8 const colour) { - return ((colour >> 2) & 7) * (255 / 7); + return ((colour >> 2) & 7) * (255 / 7); } // gets the blue channel in 32 bit colour space static inline uint8_t colour8_blue32(colour8 const colour) { - return (colour & 3) * (255 / 3); + return (colour & 3) * (255 / 3); } // sets the render colour to a colour8 value static inline void set_colour8(SDL_Renderer* const renderer, colour8 const c) { - (void)SDL_SetRenderDrawColor(renderer, colour8_red32(c), colour8_green32(c), colour8_blue32(c), 0xFF); + (void)SDL_SetRenderDrawColor(renderer, colour8_red32(c), colour8_green32(c), colour8_blue32(c), 0xFF); } // american macros: diff --git a/src/io/render.c b/src/io/render.c index 1d07143..575687a 100644 --- a/src/io/render.c +++ b/src/io/render.c @@ -21,141 +21,141 @@ #define COLOUR_SCORE COLOUR32_YELLOW void render_init(renderdata* const render_dat, gamedata const* const game_dat) { - SDL_Window* const window = SDL_CreateWindow("tetris clone", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); - if (window == NULL) fatal(ERROR_SDL_RENDERING_INIT, "Window failed to be created! SDL Error: %s", SDL_GetError()); + SDL_Window* const window = SDL_CreateWindow("tetris clone", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); + if (window == NULL) fatal(ERROR_SDL_RENDERING_INIT, "Window failed to be created! SDL Error: %s", SDL_GetError()); - SDL_Renderer* const renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); - if (renderer == NULL) fatal(ERROR_SDL_RENDERING_INIT, "Renderer failed to be created! SDL Error: %s", SDL_GetError()); + SDL_Renderer* const renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); + if (renderer == NULL) fatal(ERROR_SDL_RENDERING_INIT, "Renderer failed to be created! SDL Error: %s", SDL_GetError()); - TTF_Font* const font = TTF_OpenFont("pixeldroid_botic-regular.ttf", PX_DENS); - if (font == NULL) error("Failed to open font! TTF Error: %s", TTF_GetError()); + TTF_Font* const font = TTF_OpenFont("pixeldroid_botic-regular.ttf", PX_DENS); + if (font == NULL) error("Failed to open font! TTF Error: %s", TTF_GetError()); - // initialize the render data - *render_dat = (renderdata){ - game_dat, - window, - renderer, - font, - calloc(1, sizeof(struct render_cache)), // zero-initialize the memory as we read from it - }; + // initialize the render data + *render_dat = (renderdata){ + game_dat, + window, + renderer, + font, + calloc(1, sizeof(struct render_cache)), // zero-initialize the memory as we read from it + }; } static inline int32_t get_column_pos(uint8_t column) { - return column * BLOCK_WIDTH + 1 + TET_PADDING; + return column * BLOCK_WIDTH + 1 + TET_PADDING; } static inline int32_t get_row_pos(uint8_t row) { - return row * BLOCK_HEIGHT + 1 + TET_PADDING; + return row * BLOCK_HEIGHT + 1 + TET_PADDING; } static void draw_score_text(renderdata const* dat) { - struct render_cache* const cache = dat->cache; - uint16_t const score = dat->game_dat->score; + struct render_cache* const cache = dat->cache; + uint16_t const score = dat->game_dat->score; - SDL_Renderer* const renderer = dat->renderer; - TTF_Font* const font = dat->font; + SDL_Renderer* const renderer = dat->renderer; + TTF_Font* const font = dat->font; - if (cache->prevscore != score || cache->score_texture == NULL) { - char score_text[6]; // max digits of a uint16 + \0 terminator - if (!score) sprintf(score_text, "0"); - else sprintf(score_text, "%hu0", score); + if (cache->prevscore != score || cache->score_texture == NULL) { + char score_text[6]; // max digits of a uint16 + \0 terminator + if (!score) sprintf(score_text, "0"); + else sprintf(score_text, "%hu0", score); - SDL_Surface* const txt_surface = TTF_RenderText_Solid(font, score_text, (SDL_Colour){COLOUR_SCORE.r, COLOUR_SCORE.g, COLOUR_SCORE.b, COLOUR_SCORE.a}); - SDL_Texture* const txt_texture = SDL_CreateTextureFromSurface(renderer, txt_surface); + SDL_Surface* const txt_surface = TTF_RenderText_Solid(font, score_text, (SDL_Colour){COLOUR_SCORE.r, COLOUR_SCORE.g, COLOUR_SCORE.b, COLOUR_SCORE.a}); + SDL_Texture* const txt_texture = SDL_CreateTextureFromSurface(renderer, txt_surface); - if (cache->score_texture != NULL || cache->score_surface != NULL) { - // free old data - SDL_FreeSurface(cache->score_surface); - SDL_DestroyTexture(cache->score_texture); - } + if (cache->score_texture != NULL || cache->score_surface != NULL) { + // free old data + SDL_FreeSurface(cache->score_surface); + SDL_DestroyTexture(cache->score_texture); + } - // write data to cache - cache->score_surface = txt_surface; - cache->score_texture = txt_texture; - } + // write data to cache + cache->score_surface = txt_surface; + cache->score_texture = txt_texture; + } - if (cache->score_surface == NULL || cache->score_texture == NULL) { - error("the score texture was unavailable!",); - return; - } + if (cache->score_surface == NULL || cache->score_texture == NULL) { + error("the score texture was unavailable!", ); + return; + } - SDL_Rect text_rect = {get_column_pos(COLUMNS + 1), get_row_pos(0), cache->score_surface->w, cache->score_surface->h}; - SDL_RenderCopy(renderer, cache->score_texture, NULL, &text_rect); + SDL_Rect text_rect = {get_column_pos(COLUMNS + 1), get_row_pos(0), cache->score_surface->w, cache->score_surface->h}; + SDL_RenderCopy(renderer, cache->score_texture, NULL, &text_rect); } // draws a block at the specified position static inline int draw_block(SDL_Renderer* const renderer, int8_t const x, int8_t const y) { - SDL_Rect const block = {get_column_pos(x), get_row_pos(y), BLOCK_WIDTH - 1, BLOCK_HEIGHT - 1}; - return SDL_RenderFillRect(renderer, &block); + SDL_Rect const block = {get_column_pos(x), get_row_pos(y), BLOCK_WIDTH - 1, BLOCK_HEIGHT - 1}; + return SDL_RenderFillRect(renderer, &block); } // draws a shape at the specified position static void draw_shape(SDL_Renderer* const renderer, shape_id const id, int8_t const pos_x, int8_t const pos_y) { - shape const shape = shape_from_id(id); - set_colour8(renderer, colour_from_id(id)); + shape const shape = shape_from_id(id); + set_colour8(renderer, colour_from_id(id)); - for (int8_t y = 0; y < SHAPE_HEIGHT; y++) { - shape_row const shape_row = shape_get_row(shape, y); + for (int8_t y = 0; y < SHAPE_HEIGHT; y++) { + shape_row const shape_row = shape_get_row(shape, y); - if (shape_row == 0) - continue; + if (shape_row == 0) + continue; - for (int8_t x = 0; x < SHAPE_WIDTH; x++) - if (shape_is_set(shape_row, x)) - draw_block(renderer, pos_x + x, pos_y + y); - } + for (int8_t x = 0; x < SHAPE_WIDTH; x++) + if (shape_is_set(shape_row, x)) + draw_block(renderer, pos_x + x, pos_y + y); + } } // draw the block data in the level static void render_level(SDL_Renderer* const renderer, gamedata const* const data) { - for (int8_t y = 0; y < ROWS; y++) { - row_const const row = data->rows[y]; + for (int8_t y = 0; y < ROWS; y++) { + row_const const row = data->rows[y]; - for (int8_t x = 0; x < COLUMNS; x++) { - if (row[x] != 0) { - set_colour8(renderer, row[x]); - draw_block(renderer, x, y); - } - } - } + for (int8_t x = 0; x < COLUMNS; x++) { + if (row[x] != 0) { + set_colour8(renderer, row[x]); + draw_block(renderer, x, y); + } + } + } } void render_update(renderdata const* const dat) { - SDL_Renderer* const renderer = dat->renderer; - gamedata const* const game_data = dat->game_dat; + SDL_Renderer* const renderer = dat->renderer; + gamedata const* const game_data = dat->game_dat; - int success = 0; // if an error occurs, this value is <0 + int success = 0; // if an error occurs, this value is <0 - // clear render - set_colour32(renderer, COLOUR32_BLACK); // using colour32 is more efficient, as it sets the colours directly - success |= SDL_RenderClear(renderer); + // clear render + set_colour32(renderer, COLOUR32_BLACK); // using colour32 is more efficient, as it sets the colours directly + success |= SDL_RenderClear(renderer); - set_colour32(renderer, COLOUR32_WHITE); + set_colour32(renderer, COLOUR32_WHITE); - static SDL_Rect const field_size = {TET_PADDING, TET_PADDING, TET_WIDTH + 1, TET_HEIGHT + 1}; - SDL_RenderDrawRect(renderer, &field_size); - draw_shape(renderer, game_data->nxt[game_data->curr_idx + 1], COLUMNS + 1, 3); // draw the next shape + static SDL_Rect const field_size = {TET_PADDING, TET_PADDING, TET_WIDTH + 1, TET_HEIGHT + 1}; + SDL_RenderDrawRect(renderer, &field_size); + draw_shape(renderer, game_data->nxt[game_data->curr_idx + 1], COLUMNS + 1, 3); // draw the next shape - if (dat->font) - draw_score_text(dat); + if (dat->font) + draw_score_text(dat); - render_level(renderer, dat->game_dat); - draw_shape(renderer, game_data->nxt[game_data->curr_idx], game_data->sel_x, game_data->sel_y); // draw the current shape + render_level(renderer, dat->game_dat); + draw_shape(renderer, game_data->nxt[game_data->curr_idx], game_data->sel_x, game_data->sel_y); // draw the current shape - if (success < 0) { - warn("something went wrong whilst renderering! SDL Error: %s\n", SDL_GetError()); - return; - } + if (success < 0) { + warn("something went wrong whilst renderering! SDL Error: %s\n", SDL_GetError()); + return; + } - SDL_RenderPresent(renderer); + SDL_RenderPresent(renderer); } void render_free(renderdata* const render_data) { - SDL_DestroyRenderer(render_data->renderer); - SDL_DestroyWindow(render_data->window); - TTF_CloseFont(render_data->font); - SDL_FreeSurface(render_data->cache->score_surface); - SDL_DestroyTexture(render_data->cache->score_texture); - free(render_data->cache); - *render_data = (renderdata){0}; + SDL_DestroyRenderer(render_data->renderer); + SDL_DestroyWindow(render_data->window); + TTF_CloseFont(render_data->font); + SDL_FreeSurface(render_data->cache->score_surface); + SDL_DestroyTexture(render_data->cache->score_texture); + free(render_data->cache); + *render_data = (renderdata){0}; } diff --git a/src/io/render.h b/src/io/render.h index 5b69851..2aa610e 100644 --- a/src/io/render.h +++ b/src/io/render.h @@ -19,18 +19,18 @@ // contains the data that's cached between renders struct render_cache { - SDL_Texture* score_texture; - SDL_Surface* score_surface; - uint16_t prevscore; + SDL_Texture* score_texture; + SDL_Surface* score_surface; + uint16_t prevscore; }; // contains the data necessary for rendering typedef struct { - gamedata const* game_dat; - SDL_Window* window; - SDL_Renderer* renderer; - TTF_Font* font; - struct render_cache* cache; + gamedata const* game_dat; + SDL_Window* window; + SDL_Renderer* renderer; + TTF_Font* font; + struct render_cache* cache; } renderdata; void render_init(renderdata*, gamedata const*); // initializes the renderer, outputs to render_data diff --git a/src/main.c b/src/main.c index 68c5cd5..8d4823f 100644 --- a/src/main.c +++ b/src/main.c @@ -14,49 +14,49 @@ static renderdata rdat; // initialize the game static void init(void) { - // initialize SDL - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) fatal(ERROR_SDL_INIT, "SDL could not initialize! SDL Error: %s", SDL_GetError()); - if (TTF_Init() != 0) fatal(ERROR_SDL_FONT_INIT, "the TTF module of SDL could not initialize! TTF Error: %s", TTF_GetError()); + // initialize SDL + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) fatal(ERROR_SDL_INIT, "SDL could not initialize! SDL Error: %s", SDL_GetError()); + if (TTF_Init() != 0) fatal(ERROR_SDL_FONT_INIT, "the TTF module of SDL could not initialize! TTF Error: %s", TTF_GetError()); - // initialize other game components - paths_init(); - game_init(&gdat); - render_init(&rdat, &gdat); + // initialize other game components + paths_init(); + game_init(&gdat); + render_init(&rdat, &gdat); } // perform the updates to the game static void update(void) { - // update the input - { - SDL_Event e; - while (SDL_PollEvent(&e)) { - switch (e.type) { - case SDL_QUIT: - gdat.run = false; - break; - } - } - } + // update the input + { + SDL_Event e; + while (SDL_PollEvent(&e)) { + switch (e.type) { + case SDL_QUIT: + gdat.run = false; + break; + } + } + } - // perform updates - game_update(&gdat); - render_update(&rdat); + // perform updates + game_update(&gdat); + render_update(&rdat); } // entry-point of the application int main(int argc, char** argv) { - (void)argc, (void)argv; + (void)argc, (void)argv; - init(); - debug("successfully initialized!", ); + init(); + debug("successfully initialized!", ); - while (gdat.run == true) - update(); + while (gdat.run == true) + update(); - debug("done! starting to free resources...", ); - game_free(&gdat); - render_free(&rdat); - paths_free(); - SDL_Quit(); - return 0; + debug("done! starting to free resources...", ); + game_free(&gdat); + render_free(&rdat); + paths_free(); + SDL_Quit(); + return 0; } diff --git a/src/util/compat.h b/src/util/compat.h index 5ff785f..05edc90 100644 --- a/src/util/compat.h +++ b/src/util/compat.h @@ -38,19 +38,19 @@ #endif enum faccess_perms { - FA_F = F_OK, // test for file's existence - FA_X = X_OK, // test for executing permission - FA_W = W_OK, // test for write permissions - FA_R = R_OK, // test for read permissions + FA_F = F_OK, // test for file's existence + FA_X = X_OK, // test for executing permission + FA_W = W_OK, // test for write permissions + FA_R = R_OK, // test for read permissions }; /* tests a files access with F_OK, X_OK, R_OK, W_OK OR'd together returns 0 upon success. -1 when errno is set and anything else when one or more of the permissions isn't set */ static inline int faccess(char const* restrict fname, int perms) { #if defined __unix__ && _POSIX_C_SOURCE >= 200809L - return access(fname, perms); + return access(fname, perms); #elif defined _WIN32 - return _access(fname, perms); + return _access(fname, perms); #else #error platform unsupported! #endif