diff --git a/game/BUILD b/game/BUILD index 5fb7a5b..c0eeff6 100644 --- a/game/BUILD +++ b/game/BUILD @@ -3,5 +3,5 @@ cc_library( srcs = glob(["*.c"]), hdrs = glob(["*.h"]), visibility = ["//visibility:public"], - deps = ["//device:device"] + deps = ["//device:device", "//sys:sys"] ) \ No newline at end of file diff --git a/game/game.c b/game/game.c index ad4c617..cc31113 100644 --- a/game/game.c +++ b/game/game.c @@ -1,23 +1,36 @@ #include "device/device.h" #include "game.h" +#include "sys/sys.h" uint32_t game_frame; +const char* game_title() { + return "Croc Party!"; +} + void game_init() { + sys_init(); + game_frame = 0; for (uint32_t x = 0; x < 8; x++) { for (uint32_t y = 0; y < 8; y++) { for (uint32_t z = 0; z < 4; z++) { - device_palette[ - (x << 5)|(y << 2)|(z) - ] = + sys_spal_set( + (x << 5)|(y << 2)|(z), + ((x * 255)/7) << 24 | ((y * 255)/7) << 16 | - ((z * 255)/3) << 8; + ((z * 255)/3) << 8 + ); } } } + sys_spal_set(0xfe, 0xffffffff); +} + +void game_destroy() { + sys_destroy(); } void game_update() { @@ -25,6 +38,8 @@ void game_update() { } void game_draw() { + sys_dpal_set(0xff, 0xfe); // map to a non-transparent color + for (int x = 0; x < DEVICE_W; x++) { for (int y = 0; y < DEVICE_H; y++) { uint32_t r = (x * 255)/(DEVICE_W - 1); @@ -35,12 +50,12 @@ void game_draw() { g = 255 - g; b = 255 - b; } - uint8_t color = (r >> 5) << 5 | (g >> 5) << 2 | (b >> 6); - device_pixels[y][x] = color; + sys_color color = (r >> 5) << 5 | (g >> 5) << 2 | (b >> 6); + sys_pixel_set(x, y, color); } } for (int i = 0; i < DEVICE_BUTTON_N; i++) { - device_pixels[0][i] = device_buttons[i] ? 0x00 : 0xff; + sys_pixel_set(i, 0, device_buttons[i] ? 0x00 : 0xff); } } diff --git a/game/game.h b/game/game.h index f4c7b99..9f223a0 100644 --- a/game/game.h +++ b/game/game.h @@ -1,7 +1,10 @@ #ifndef CROCPARTY_GAME_H #define CROCPARTY_GAME_H +const char* game_title(); void game_init(); +void game_destroy(); + void game_update(); void game_draw(); diff --git a/sdl_host/main.c b/sdl_host/main.c index 2883ded..747716f 100644 --- a/sdl_host/main.c +++ b/sdl_host/main.c @@ -28,7 +28,7 @@ int main(int argc, char** argv) { // create window sdl_host_window = SDL_CreateWindow( - "Croc Party!", + game_title(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int) window_w, (int) window_h, diff --git a/sys/BUILD b/sys/BUILD new file mode 100644 index 0000000..32e66ed --- /dev/null +++ b/sys/BUILD @@ -0,0 +1,7 @@ +cc_library( + name = "sys", + srcs = glob(["*.c"]), + hdrs = glob(["*.h"]), + visibility = ["//visibility:public"], + deps = ["//device:device"] +) \ No newline at end of file diff --git a/sys/sys.c b/sys/sys.c new file mode 100644 index 0000000..3d806af --- /dev/null +++ b/sys/sys.c @@ -0,0 +1,25 @@ +#include +#include +#include "sys.h" + +bool sys_initialized = false; + +void sys_init() { + assert(!sys_get_initialized()); + sys_initialized = true; + + // reset graphics + sys_clip_reset(); + sys_camera_reset(); + sys_spal_reset(); + sys_dpal_reset(); +} + +bool sys_get_initialized() { + return sys_initialized; +} + +void sys_destroy() { + assert(sys_get_initialized()); + sys_initialized = false; +} \ No newline at end of file diff --git a/sys/sys.h b/sys/sys.h index ae85494..9987f51 100644 --- a/sys/sys.h +++ b/sys/sys.h @@ -4,4 +4,19 @@ #include "sys_data.h" #include "sys_graphics.h" +/** + * Initialize sys. + */ +void sys_init(); + +/** + * Return whether sys was initialized. + */ +bool sys_get_initialized(); + +/** + * Destroy sys. + */ +void sys_destroy(); + #endif // CROCPARTY_SYS_H \ No newline at end of file diff --git a/sys/sys_data.c b/sys/sys_data.c new file mode 100644 index 0000000..c719bb3 --- /dev/null +++ b/sys/sys_data.c @@ -0,0 +1,9 @@ +#include "sys_data.h" + +sys_i32 sys_max_i32(sys_i32 x, sys_i32 y) { + return x > y ? x : y; +} + +sys_i32 sys_min_i32(sys_i32 x, sys_i32 y) { + return x < y ? x : y; +} \ No newline at end of file diff --git a/sys/sys_data.h b/sys/sys_data.h index 7fce79b..5479ed3 100644 --- a/sys/sys_data.h +++ b/sys/sys_data.h @@ -7,7 +7,12 @@ typedef int32_t sys_i32; typedef uint8_t sys_color; typedef uint32_t sys_screen_color; - sys_screen_color sys_make_screen_color(uint8_t r, uint8_t g, uint8_t b); +sys_i32 sys_max_i32(sys_i32 x, sys_i32 y); +sys_i32 sys_min_i32(sys_i32 x, sys_i32 y); + +#define SYS_COLOR_TRANSPARENT 255 +#define SYS_COLOR_N 256 + #endif // CROCPARTY_SYS_DATA_H \ No newline at end of file diff --git a/sys/sys_graphics.c b/sys/sys_graphics.c index e69de29..8d3239f 100644 --- a/sys/sys_graphics.c +++ b/sys/sys_graphics.c @@ -0,0 +1,126 @@ +#include +#include "sys.h" +#include "device/device.h" + +sys_i32 sys_cam_dx, sys_cam_dy; +sys_i32 sys_clip_x0, sys_clip_y0, sys_clip_x1, sys_clip_y1; +sys_color sys_dpal[256]; + +// primitives (forward declare) +void sys_pixel_internal_set(sys_i32 x, sys_i32 y, sys_color c); + +// == public == +void sys_clip_set(sys_i32 x0, sys_i32 y0, sys_i32 x1, sys_i32 y1) { + assert(sys_get_initialized()); + + sys_clip_set_ext(x0, y0, x1, y1, false); +} + +void sys_clip_reset() { + assert(sys_get_initialized()); + + sys_clip_set(0, 0, DEVICE_W, DEVICE_H); +} + +void sys_clip_set_ext(sys_i32 x0, sys_i32 y0, sys_i32 x1, sys_i32 y1, bool clip_previous) { + assert(sys_get_initialized()); + sys_clip_x0 = sys_max_i32(x0, clip_previous ? sys_clip_x0 : 0); + sys_clip_y0 = sys_max_i32(y0, clip_previous ? sys_clip_y0 : 0); + sys_clip_x1 = sys_min_i32(x1, clip_previous ? sys_clip_x1 : DEVICE_W); + sys_clip_y1 = sys_min_i32(y1, clip_previous ? sys_clip_y1 : DEVICE_H); +} + +void sys_pixel_set(sys_i32 x, sys_i32 y, sys_color c) { + assert(sys_get_initialized()); + + x += sys_cam_dx; + y += sys_cam_dy; + + sys_pixel_internal_set(x, y, c); +} + +sys_color sys_pixel_get(sys_i32 x, sys_i32 y) { + assert(sys_get_initialized()); + + x += sys_cam_dx; + y += sys_cam_dy; + + if (x < 0 || y < 0 || x >= DEVICE_W || y >= DEVICE_H) { + return SYS_COLOR_TRANSPARENT; + } + + return device_pixels[y][x]; +} + +void sys_cls(sys_color c) { + assert(sys_get_initialized()); + + for (int x = 0; x < DEVICE_W; x++) { + for (int y = 0; y < DEVICE_W; y++) { + sys_pixel_internal_set(x, y, c); + } + } +} + +void sys_camera_set(sys_i32 x, sys_i32 y) { + assert(sys_get_initialized()); + + sys_cam_dx = -x; + sys_cam_dy = -y; +} + +void sys_camera_reset() { + assert(sys_get_initialized()); + + sys_camera_set(0, 0); +} + +// TODO: Continue from sys_circ_draw_ext + +void sys_spal_set(sys_color c0, sys_screen_color rc1) { + assert(sys_get_initialized()); + + device_palette[c0] = rc1; +} + +void sys_spal_reset() { + assert(sys_get_initialized()); + + for (int i = 0; i < SYS_COLOR_N; i++) { + sys_spal_set(i, 0x000000ff); + } +} + +void sys_dpal_set(sys_color c0, sys_color c1) { + assert(sys_get_initialized()); + + sys_dpal[c0] = c1; +} + +void sys_dpal_reset() { + assert(sys_get_initialized()); + + for (int i = 0; i < SYS_COLOR_N; i++) { + sys_dpal_set(i, i); + } +} + +// == internal primitives == +void sys_pixel_internal_set(sys_i32 x, sys_i32 y, sys_color c) { + sys_color realc = sys_dpal[c]; + if (realc == SYS_COLOR_TRANSPARENT) { return; } + + if ( + x < sys_clip_x0 || y < sys_clip_y0 || + x >= sys_clip_x1 || y >= sys_clip_y1 + ) { + return; + } + + assert(x >= 0); + assert(y >= 0); + assert(x < DEVICE_W); + assert(y < DEVICE_H); + + device_pixels[y][x] = realc; +} \ No newline at end of file diff --git a/sys/sys_graphics.h b/sys/sys_graphics.h index 1c5e779..ccc0526 100644 --- a/sys/sys_graphics.h +++ b/sys/sys_graphics.h @@ -19,6 +19,11 @@ */ void sys_clip_set(sys_i32 x0, sys_i32 y0, sys_i32 x1, sys_i32 y1); +/** + * Reset the clipping rectangle. + */ +void sys_clip_reset(); + /** * Set the clipping rectangle in pixels. * @@ -41,7 +46,7 @@ void sys_pixel_set( /** * Get the color of the pixel `(x, y)`. * - * Returns 0 if the pixel is out of bounds. + * Returns SYS_COLOR_TRANSPARENT if the pixel is out of bounds. */ sys_color sys_pixel_get( sys_i32 x, sys_i32 y @@ -115,7 +120,7 @@ void sys_rect_fill(sys_i32 x0, sys_i32 y0, sys_i32 x1, sys_i32 y1, sys_color c); * After calling this function, virtual color `c0` will be rendered as * real color `rc1`. */ -void sys_spal_set(uint8_t c0, uint32_t rc1); +void sys_spal_set(sys_color c0, sys_screen_color rc1); /** * Reset screen palette. @@ -130,14 +135,14 @@ void sys_spal_reset(); * After calling this function, draws using color `c0` will be performed * using color `c1` instead. * - * Any color mapped to `255` will not actually be drawn. + * Any color mapped to `SYS_COLOR_TRANSPARENT` will not actually be drawn. */ -void sys_dpal_set(uint8_t c0, uint8_t c1); +void sys_dpal_set(sys_color c0, sys_color c1); /** * Reset draw palette. * - * All colors are mapped to themselves. Color 255 is transparent. + * All colors are mapped to themselves. SYS_COLOR_TRANSPARENT is transparent. */ void sys_dpal_reset();