From 344d070dfbfe4bbde93708a0c14436b57f487007 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sun, 18 Apr 2021 14:21:50 +0200 Subject: Add initial sprite tests --- src/main.c | 191 +++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 129 insertions(+), 62 deletions(-) diff --git a/src/main.c b/src/main.c index b09d54f..07c809e 100644 --- a/src/main.c +++ b/src/main.c @@ -25,23 +25,29 @@ #define DISP_STATUS *((vu32*)(MEM_IO + 0x0004)) #define DISP_VCOUNT *((vu32*)(MEM_IO + 0x0006)) -// Bits for display control. -#define DISP_CTRL_PAGE (1 << 4) - -// Display modes. -#define DISP_MODE_0 0x0000 -#define DISP_MODE_1 0x0001 -#define DISP_MODE_2 0x0002 -#define DISP_MODE_3 0x0003 -#define DISP_MODE_4 0x0004 -#define DISP_MODE_5 0x0005 - -// Layers. -#define DISP_BG_0 0x0100 -#define DISP_BG_1 0x0200 -#define DISP_BG_2 0x0400 -#define DISP_BG_3 0x0800 -#define DISP_OBJ 0x1000 +// The first three bits in the DISP_CTRL are used to control the video mode. +#define DISP_MODE_0 0x0000 +#define DISP_MODE_1 0x0001 +#define DISP_MODE_2 0x0002 +#define DISP_MODE_3 0x0003 +#define DISP_MODE_4 0x0004 +#define DISP_MODE_5 0x0005 +#define DISP_GB (1 << 3) +#define DISP_PAGE (1 << 4) +#define DISP_OAM_HBLANK (1 << 5) +#define DISP_OBJ_1D (1 << 6) +#define DISP_BLANK (1 << 7) +#define DISP_BG_0 (1 << 8) +#define DISP_BG_1 (1 << 9) +#define DISP_BG_2 (1 << 10) +#define DISP_BG_3 (1 << 11) +#define DISP_OBJ (1 << 12) + +// Registers to control of BG layers. +#define BG_CTRL_0 *((vu16*)(0x04000008 + 0x0000)) +#define BG_CTRL_1 *((vu16*)(0x04000008 + 0x0002)) +#define BG_CTRL_2 *((vu16*)(0x04000008 + 0x0004)) +#define BG_CTRL_3 *((vu16*)(0x04000008 + 0x0006)) // Screen settings. #define SCREEN_WIDTH 240 @@ -51,6 +57,19 @@ // (RGB) have a 0--31 range. For example, pure red would be rgb15(31, 0, 0). typedef u16 Color; +// +// Tile memory access. +// + +// NOTE: Only defining 4bpp tiles for now. +typedef struct Tile { + u32 data[8]; +} Tile; + +typedef Tile TileBlock[512]; + +#define TILE_MEM ((TileBlock*) MEM_VRAM) + // We can treat the screen as a HxW matrix. With the following macro we can // write a pixel to the screen at the (x, y) position using: // @@ -59,7 +78,8 @@ typedef u16 Color; typedef Color Scanline[SCREEN_WIDTH]; #define FRAMEBUFFER ((Scanline*)MEM_VRAM) #define SCREEN_BUFFER ((vu16*) MEM_VRAM) -#define PAL_BUFFER ((vu16*) MEM_PAL) +#define PAL_BUFFER_BG ((vu16*) MEM_PAL) +#define PAL_BUFFER_SPRITES ((vu16*) 0x05000200) // // Colors. @@ -271,7 +291,7 @@ draw_fill_rect_m4(int x0, int y0, int x1, int y1, u8 col_index, vu16 *buffer) { static inline void flip_page() { - DISP_CTRL ^= DISP_CTRL_PAGE; + DISP_CTRL ^= DISP_PAGE; } #define SCREEN_PAGE_1 ((vu16*) MEM_VRAM) @@ -367,33 +387,8 @@ key_hold(u32 key) { // Check if the given key/button is currently pressed. #define KEY_PRESSED(key) (~(KEY_INPUTS) & key) -int main(void) { - DISP_CTRL = DISP_MODE_3 | DISP_BG_2; - - // Test setting OBJ parameters for sprite N with my custom macros. - OBJ_ATTR_0(0) = 0xBADD; - OBJ_ATTR_1(0) = 0x10DE; - OBJ_ATTR_2(0) = 0xAC1D; - OBJ_ATTR_0(1) = 0xFA7E; - OBJ_ATTR_1(1) = 0xD15E; - OBJ_ATTR_2(1) = 0xA5ED; - OBJ_ATTR_0(2) = 0xBADD; - OBJ_ATTR_1(2) = 0x10DE; - OBJ_ATTR_2(2) = 0xAC1D; - OBJ_ATTR_0(3) = 0xFA7E; - OBJ_ATTR_1(3) = 0xD15E; - OBJ_ATTR_2(3) = 0xA5ED; - OBJ_AFFINE_PA(0) = 0x0011; - OBJ_AFFINE_PB(0) = 0x2233; - OBJ_AFFINE_PC(0) = 0x4455; - OBJ_AFFINE_PD(0) = 0x6677; - OBJ_AFFINE_PA(1) = 0xAABB; - OBJ_AFFINE_PB(1) = 0xCCDD; - OBJ_AFFINE_PC(1) = 0xEEFF; - OBJ_AFFINE_PD(1) = 0x0101; - - // draw_fill_rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, COLOR_GREY); - +void +draw_logo() { int side = 60; int line = 35; int height = side * 0.5; @@ -425,31 +420,103 @@ int main(void) { draw_line(x + height, y, x + height + line, y, COLOR_WHITE); draw_line(x - line, y + 1, x, y + 1, COLOR_WHITE); draw_line(x + height, y + 1, x + height + line, y + 1, COLOR_WHITE); +} + +int main(void) { + // Configure the display in mode 0 to show OBJs, where tile memory is + // sequential. + DISP_CTRL = DISP_MODE_0 | DISP_OBJ | DISP_OBJ_1D; + + // Create two 4bpp tiles, one filled with color 1 and another with color 2. + Tile *tile_mem = &TILE_MEM[4][0]; + for (size_t i = 0; i < 8; ++i) { + tile_mem->data[i] = 0x11111111; + } + for (size_t i = 8; i < 16; ++i) { + tile_mem->data[i] = 0x22222222; + } + + // Add colors to the sprite color palette. Tiles with color number 0 are + // treated as transparent. + PAL_BUFFER_SPRITES[1] = COLOR_WHITE; + PAL_BUFFER_SPRITES[2] = COLOR_RED; + PAL_BUFFER_SPRITES[3] = COLOR_CYAN; + PAL_BUFFER_SPRITES[4] = COLOR_GREY; + PAL_BUFFER_SPRITES[5] = COLOR_BLACK; + PAL_BUFFER_SPRITES[15] = COLOR_RED; + + int x_a = 100; + int y_a = 100; + int tile_id_a = 0; + int x_b = 50; + int y_b = 50; + int tile_id_b = 1; + + OBJ_ATTR_0(0) = y_a; + OBJ_ATTR_1(0) = x_a; + OBJ_ATTR_2(0) = tile_id_a; + + OBJ_ATTR_0(1) = y_b; + OBJ_ATTR_1(1) = x_b; + OBJ_ATTR_2(1) = tile_id_b; + + // for (size_t i = 0; i < 16; ++i) { + // PAL_BUFFER_SPRITES[i] = COLOR_RED; + // } + // PAL_BUFFER_SPRITES[0] = COLOR_RED; + // PAL_BUFFER_BG[0] = COLOR_WHITE; + + // for (size_t i = 0; i < sizeof(tile_mem->data); ++i) { + // tile_mem->data[i] = COLOR_WHITE; + // } + int frame_counter = 0; - bool toggle_key_down = false; + int active_sprite = 0; while(true) { wait_vsync(); - if (frame_counter++ > 30) { - frame_counter = 0; - } poll_keys(); // Toggle frame counter when we press down. - if (key_pressed(KEY_DOWN)) { - toggle_key_down ^= 1; + if (key_pressed(KEY_DOWN) || key_hold(KEY_DOWN)) { + if (active_sprite == 0) { + y_a += 3; + } else { + y_b += 3; + } } - if (toggle_key_down) { - put_text(8, 8, COLOR_GREY, "TOGGLE: OFF"); - put_text(8, 8, COLOR_RED, "TOGGLE: ON"); - } else { - put_text(8, 8, COLOR_GREY, "TOGGLE: ON"); - put_text(8, 8, COLOR_RED, "TOGGLE: OFF"); + if (key_pressed(KEY_UP) || key_hold(KEY_UP)) { + if (active_sprite == 0) { + y_a -= 3; + } else { + y_b -= 3; + } + } + if (key_pressed(KEY_LEFT) || key_hold(KEY_LEFT)) { + if (active_sprite == 0) { + x_a -= 3; + } else { + x_b -= 3; + } } - if (key_hold(KEY_DOWN)) { - put_text(8, 24, COLOR_RED, "HOLDING"); - } else { - put_text(8, 24, COLOR_GREY, "HOLDING"); + if (key_pressed(KEY_RIGHT) || key_hold(KEY_RIGHT)) { + if (active_sprite == 0) { + x_a += 3; + } else { + x_b += 3; + } } + if (key_pressed(KEY_B)) { + if (active_sprite == 0) { + active_sprite = 1; + } else { + active_sprite = 0; + } + } + + OBJ_ATTR_0(0) = y_a & 0xFF; + OBJ_ATTR_1(0) = x_a & 0xFF; + OBJ_ATTR_0(1) = y_b & 0xFF; + OBJ_ATTR_1(1) = x_b & 0xFF; }; return 0; -- cgit v1.2.1