diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 191 |
1 files changed, 129 insertions, 62 deletions
@@ -25,23 +25,29 @@ | |||
25 | #define DISP_STATUS *((vu32*)(MEM_IO + 0x0004)) | 25 | #define DISP_STATUS *((vu32*)(MEM_IO + 0x0004)) |
26 | #define DISP_VCOUNT *((vu32*)(MEM_IO + 0x0006)) | 26 | #define DISP_VCOUNT *((vu32*)(MEM_IO + 0x0006)) |
27 | 27 | ||
28 | // Bits for display control. | 28 | // The first three bits in the DISP_CTRL are used to control the video mode. |
29 | #define DISP_CTRL_PAGE (1 << 4) | 29 | #define DISP_MODE_0 0x0000 |
30 | 30 | #define DISP_MODE_1 0x0001 | |
31 | // Display modes. | 31 | #define DISP_MODE_2 0x0002 |
32 | #define DISP_MODE_0 0x0000 | 32 | #define DISP_MODE_3 0x0003 |
33 | #define DISP_MODE_1 0x0001 | 33 | #define DISP_MODE_4 0x0004 |
34 | #define DISP_MODE_2 0x0002 | 34 | #define DISP_MODE_5 0x0005 |
35 | #define DISP_MODE_3 0x0003 | 35 | #define DISP_GB (1 << 3) |
36 | #define DISP_MODE_4 0x0004 | 36 | #define DISP_PAGE (1 << 4) |
37 | #define DISP_MODE_5 0x0005 | 37 | #define DISP_OAM_HBLANK (1 << 5) |
38 | 38 | #define DISP_OBJ_1D (1 << 6) | |
39 | // Layers. | 39 | #define DISP_BLANK (1 << 7) |
40 | #define DISP_BG_0 0x0100 | 40 | #define DISP_BG_0 (1 << 8) |
41 | #define DISP_BG_1 0x0200 | 41 | #define DISP_BG_1 (1 << 9) |
42 | #define DISP_BG_2 0x0400 | 42 | #define DISP_BG_2 (1 << 10) |
43 | #define DISP_BG_3 0x0800 | 43 | #define DISP_BG_3 (1 << 11) |
44 | #define DISP_OBJ 0x1000 | 44 | #define DISP_OBJ (1 << 12) |
45 | |||
46 | // Registers to control of BG layers. | ||
47 | #define BG_CTRL_0 *((vu16*)(0x04000008 + 0x0000)) | ||
48 | #define BG_CTRL_1 *((vu16*)(0x04000008 + 0x0002)) | ||
49 | #define BG_CTRL_2 *((vu16*)(0x04000008 + 0x0004)) | ||
50 | #define BG_CTRL_3 *((vu16*)(0x04000008 + 0x0006)) | ||
45 | 51 | ||
46 | // Screen settings. | 52 | // Screen settings. |
47 | #define SCREEN_WIDTH 240 | 53 | #define SCREEN_WIDTH 240 |
@@ -51,6 +57,19 @@ | |||
51 | // (RGB) have a 0--31 range. For example, pure red would be rgb15(31, 0, 0). | 57 | // (RGB) have a 0--31 range. For example, pure red would be rgb15(31, 0, 0). |
52 | typedef u16 Color; | 58 | typedef u16 Color; |
53 | 59 | ||
60 | // | ||
61 | // Tile memory access. | ||
62 | // | ||
63 | |||
64 | // NOTE: Only defining 4bpp tiles for now. | ||
65 | typedef struct Tile { | ||
66 | u32 data[8]; | ||
67 | } Tile; | ||
68 | |||
69 | typedef Tile TileBlock[512]; | ||
70 | |||
71 | #define TILE_MEM ((TileBlock*) MEM_VRAM) | ||
72 | |||
54 | // We can treat the screen as a HxW matrix. With the following macro we can | 73 | // We can treat the screen as a HxW matrix. With the following macro we can |
55 | // write a pixel to the screen at the (x, y) position using: | 74 | // write a pixel to the screen at the (x, y) position using: |
56 | // | 75 | // |
@@ -59,7 +78,8 @@ typedef u16 Color; | |||
59 | typedef Color Scanline[SCREEN_WIDTH]; | 78 | typedef Color Scanline[SCREEN_WIDTH]; |
60 | #define FRAMEBUFFER ((Scanline*)MEM_VRAM) | 79 | #define FRAMEBUFFER ((Scanline*)MEM_VRAM) |
61 | #define SCREEN_BUFFER ((vu16*) MEM_VRAM) | 80 | #define SCREEN_BUFFER ((vu16*) MEM_VRAM) |
62 | #define PAL_BUFFER ((vu16*) MEM_PAL) | 81 | #define PAL_BUFFER_BG ((vu16*) MEM_PAL) |
82 | #define PAL_BUFFER_SPRITES ((vu16*) 0x05000200) | ||
63 | 83 | ||
64 | // | 84 | // |
65 | // Colors. | 85 | // Colors. |
@@ -271,7 +291,7 @@ draw_fill_rect_m4(int x0, int y0, int x1, int y1, u8 col_index, vu16 *buffer) { | |||
271 | 291 | ||
272 | static inline void | 292 | static inline void |
273 | flip_page() { | 293 | flip_page() { |
274 | DISP_CTRL ^= DISP_CTRL_PAGE; | 294 | DISP_CTRL ^= DISP_PAGE; |
275 | } | 295 | } |
276 | 296 | ||
277 | #define SCREEN_PAGE_1 ((vu16*) MEM_VRAM) | 297 | #define SCREEN_PAGE_1 ((vu16*) MEM_VRAM) |
@@ -367,33 +387,8 @@ key_hold(u32 key) { | |||
367 | // Check if the given key/button is currently pressed. | 387 | // Check if the given key/button is currently pressed. |
368 | #define KEY_PRESSED(key) (~(KEY_INPUTS) & key) | 388 | #define KEY_PRESSED(key) (~(KEY_INPUTS) & key) |
369 | 389 | ||
370 | int main(void) { | 390 | void |
371 | DISP_CTRL = DISP_MODE_3 | DISP_BG_2; | 391 | draw_logo() { |
372 | |||
373 | // Test setting OBJ parameters for sprite N with my custom macros. | ||
374 | OBJ_ATTR_0(0) = 0xBADD; | ||
375 | OBJ_ATTR_1(0) = 0x10DE; | ||
376 | OBJ_ATTR_2(0) = 0xAC1D; | ||
377 | OBJ_ATTR_0(1) = 0xFA7E; | ||
378 | OBJ_ATTR_1(1) = 0xD15E; | ||
379 | OBJ_ATTR_2(1) = 0xA5ED; | ||
380 | OBJ_ATTR_0(2) = 0xBADD; | ||
381 | OBJ_ATTR_1(2) = 0x10DE; | ||
382 | OBJ_ATTR_2(2) = 0xAC1D; | ||
383 | OBJ_ATTR_0(3) = 0xFA7E; | ||
384 | OBJ_ATTR_1(3) = 0xD15E; | ||
385 | OBJ_ATTR_2(3) = 0xA5ED; | ||
386 | OBJ_AFFINE_PA(0) = 0x0011; | ||
387 | OBJ_AFFINE_PB(0) = 0x2233; | ||
388 | OBJ_AFFINE_PC(0) = 0x4455; | ||
389 | OBJ_AFFINE_PD(0) = 0x6677; | ||
390 | OBJ_AFFINE_PA(1) = 0xAABB; | ||
391 | OBJ_AFFINE_PB(1) = 0xCCDD; | ||
392 | OBJ_AFFINE_PC(1) = 0xEEFF; | ||
393 | OBJ_AFFINE_PD(1) = 0x0101; | ||
394 | |||
395 | // draw_fill_rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, COLOR_GREY); | ||
396 | |||
397 | int side = 60; | 392 | int side = 60; |
398 | int line = 35; | 393 | int line = 35; |
399 | int height = side * 0.5; | 394 | int height = side * 0.5; |
@@ -425,31 +420,103 @@ int main(void) { | |||
425 | draw_line(x + height, y, x + height + line, y, COLOR_WHITE); | 420 | draw_line(x + height, y, x + height + line, y, COLOR_WHITE); |
426 | draw_line(x - line, y + 1, x, y + 1, COLOR_WHITE); | 421 | draw_line(x - line, y + 1, x, y + 1, COLOR_WHITE); |
427 | draw_line(x + height, y + 1, x + height + line, y + 1, COLOR_WHITE); | 422 | draw_line(x + height, y + 1, x + height + line, y + 1, COLOR_WHITE); |
423 | } | ||
424 | |||
425 | int main(void) { | ||
426 | // Configure the display in mode 0 to show OBJs, where tile memory is | ||
427 | // sequential. | ||
428 | DISP_CTRL = DISP_MODE_0 | DISP_OBJ | DISP_OBJ_1D; | ||
429 | |||
430 | // Create two 4bpp tiles, one filled with color 1 and another with color 2. | ||
431 | Tile *tile_mem = &TILE_MEM[4][0]; | ||
432 | for (size_t i = 0; i < 8; ++i) { | ||
433 | tile_mem->data[i] = 0x11111111; | ||
434 | } | ||
435 | for (size_t i = 8; i < 16; ++i) { | ||
436 | tile_mem->data[i] = 0x22222222; | ||
437 | } | ||
438 | |||
439 | // Add colors to the sprite color palette. Tiles with color number 0 are | ||
440 | // treated as transparent. | ||
441 | PAL_BUFFER_SPRITES[1] = COLOR_WHITE; | ||
442 | PAL_BUFFER_SPRITES[2] = COLOR_RED; | ||
443 | PAL_BUFFER_SPRITES[3] = COLOR_CYAN; | ||
444 | PAL_BUFFER_SPRITES[4] = COLOR_GREY; | ||
445 | PAL_BUFFER_SPRITES[5] = COLOR_BLACK; | ||
446 | PAL_BUFFER_SPRITES[15] = COLOR_RED; | ||
447 | |||
448 | int x_a = 100; | ||
449 | int y_a = 100; | ||
450 | int tile_id_a = 0; | ||
451 | int x_b = 50; | ||
452 | int y_b = 50; | ||
453 | int tile_id_b = 1; | ||
454 | |||
455 | OBJ_ATTR_0(0) = y_a; | ||
456 | OBJ_ATTR_1(0) = x_a; | ||
457 | OBJ_ATTR_2(0) = tile_id_a; | ||
458 | |||
459 | OBJ_ATTR_0(1) = y_b; | ||
460 | OBJ_ATTR_1(1) = x_b; | ||
461 | OBJ_ATTR_2(1) = tile_id_b; | ||
462 | |||
463 | // for (size_t i = 0; i < 16; ++i) { | ||
464 | // PAL_BUFFER_SPRITES[i] = COLOR_RED; | ||
465 | // } | ||
466 | // PAL_BUFFER_SPRITES[0] = COLOR_RED; | ||
467 | // PAL_BUFFER_BG[0] = COLOR_WHITE; | ||
468 | |||
469 | // for (size_t i = 0; i < sizeof(tile_mem->data); ++i) { | ||
470 | // tile_mem->data[i] = COLOR_WHITE; | ||
471 | // } | ||
472 | |||
428 | int frame_counter = 0; | 473 | int frame_counter = 0; |
429 | bool toggle_key_down = false; | 474 | int active_sprite = 0; |
430 | while(true) { | 475 | while(true) { |
431 | wait_vsync(); | 476 | wait_vsync(); |
432 | if (frame_counter++ > 30) { | ||
433 | frame_counter = 0; | ||
434 | } | ||
435 | poll_keys(); | 477 | poll_keys(); |
436 | 478 | ||
437 | // Toggle frame counter when we press down. | 479 | // Toggle frame counter when we press down. |
438 | if (key_pressed(KEY_DOWN)) { | 480 | if (key_pressed(KEY_DOWN) || key_hold(KEY_DOWN)) { |
439 | toggle_key_down ^= 1; | 481 | if (active_sprite == 0) { |
482 | y_a += 3; | ||
483 | } else { | ||
484 | y_b += 3; | ||
485 | } | ||
440 | } | 486 | } |
441 | if (toggle_key_down) { | 487 | if (key_pressed(KEY_UP) || key_hold(KEY_UP)) { |
442 | put_text(8, 8, COLOR_GREY, "TOGGLE: OFF"); | 488 | if (active_sprite == 0) { |
443 | put_text(8, 8, COLOR_RED, "TOGGLE: ON"); | 489 | y_a -= 3; |
444 | } else { | 490 | } else { |
445 | put_text(8, 8, COLOR_GREY, "TOGGLE: ON"); | 491 | y_b -= 3; |
446 | put_text(8, 8, COLOR_RED, "TOGGLE: OFF"); | 492 | } |
493 | } | ||
494 | if (key_pressed(KEY_LEFT) || key_hold(KEY_LEFT)) { | ||
495 | if (active_sprite == 0) { | ||
496 | x_a -= 3; | ||
497 | } else { | ||
498 | x_b -= 3; | ||
499 | } | ||
447 | } | 500 | } |
448 | if (key_hold(KEY_DOWN)) { | 501 | if (key_pressed(KEY_RIGHT) || key_hold(KEY_RIGHT)) { |
449 | put_text(8, 24, COLOR_RED, "HOLDING"); | 502 | if (active_sprite == 0) { |
450 | } else { | 503 | x_a += 3; |
451 | put_text(8, 24, COLOR_GREY, "HOLDING"); | 504 | } else { |
505 | x_b += 3; | ||
506 | } | ||
452 | } | 507 | } |
508 | if (key_pressed(KEY_B)) { | ||
509 | if (active_sprite == 0) { | ||
510 | active_sprite = 1; | ||
511 | } else { | ||
512 | active_sprite = 0; | ||
513 | } | ||
514 | } | ||
515 | |||
516 | OBJ_ATTR_0(0) = y_a & 0xFF; | ||
517 | OBJ_ATTR_1(0) = x_a & 0xFF; | ||
518 | OBJ_ATTR_0(1) = y_b & 0xFF; | ||
519 | OBJ_ATTR_1(1) = x_b & 0xFF; | ||
453 | }; | 520 | }; |
454 | 521 | ||
455 | return 0; | 522 | return 0; |