diff --git a/graphics/affine_main_menu_background_gfx.grit b/graphics/affine_main_menu_background_gfx.grit new file mode 100644 index 0000000..3205289 --- /dev/null +++ b/graphics/affine_main_menu_background_gfx.grit @@ -0,0 +1 @@ +-gt -gB8 -mLa -mRa \ No newline at end of file diff --git a/graphics/affine_main_menu_background_gfx.png b/graphics/affine_main_menu_background_gfx.png new file mode 100644 index 0000000..74b938a Binary files /dev/null and b/graphics/affine_main_menu_background_gfx.png differ diff --git a/graphics/background_main_menu_gfx.grit b/graphics/background_main_menu_gfx.grit new file mode 100644 index 0000000..f57bef6 --- /dev/null +++ b/graphics/background_main_menu_gfx.grit @@ -0,0 +1 @@ +-gB8 -mR8 -mLs -mRtf \ No newline at end of file diff --git a/graphics/background_main_menu_gfx.png b/graphics/background_main_menu_gfx.png new file mode 100644 index 0000000..0464650 Binary files /dev/null and b/graphics/background_main_menu_gfx.png differ diff --git a/include/affine_background.h b/include/affine_background.h index 8e5f78f..31a5b65 100644 --- a/include/affine_background.h +++ b/include/affine_background.h @@ -5,13 +5,20 @@ #include "graphic_utils.h" -#define AFFINE_BG_PAL_LEN 5 -#define AFFINE_BG_PB (PAL_ROW_LEN * 15) // This isn't really a palette bank, just the starting index of the palette +#define AFFINE_BG_PAL_LEN 16 +#define AFFINE_BG_PB (PAL_ROW_LEN * 10) // This isn't really a palette bank, just the starting index of the palette + +enum AffineBackgroundID +{ + AFFINE_BG_MAIN_MENU, + AFFINE_BG_GAME, +}; void affine_background_init(); void affine_background_update(); void affine_background_set_color(COLOR color); // Must be called with an array of size at least AFFINE_BG_PAL_LEN void affine_background_load_palette(const u16 *src); +void affine_background_change_background(enum AffineBackgroundID new_bg); #endif // AFFINE_BACKGROUND_H diff --git a/include/game.h b/include/game.h index 55e8730..b6063ff 100644 --- a/include/game.h +++ b/include/game.h @@ -16,6 +16,7 @@ #define BG_ID_ROUND_END 3 #define BG_ID_SHOP 4 #define BG_ID_BLIND_SELECT 5 +#define BG_ID_MAIN_MENU 6 // Input bindings #define SELECT_CARD KEY_A @@ -26,6 +27,7 @@ enum GameState { + GAME_MAIN_MENU, GAME_PLAYING, GAME_ROUND_END, GAME_SHOP, diff --git a/include/graphic_utils.h b/include/graphic_utils.h index 2e80828..dd90ace 100644 --- a/include/graphic_utils.h +++ b/include/graphic_utils.h @@ -138,4 +138,10 @@ void memcpy16_tile8_with_palette_offset(u16* dst, const u16* src, uint hwcount, */ void memcpy32_tile8_with_palette_offset(u32* dst, const u32* src, uint wcount, u8 palette_offset); +/* Toggles the visibility of the window layers. + * win0 and win1 are the visibility states for the two windows. + * These windows are primarily used for the shadows on held jokers, consumables and cards. + */ +void toggle_windows(bool win0, bool win1); + #endif //GRAPHIC_UTILS_H diff --git a/source/affine_background.c b/source/affine_background.c index f9e15e7..b61be78 100644 --- a/source/affine_background.c +++ b/source/affine_background.c @@ -1,16 +1,17 @@ #include "affine_background.h" #include "affine_background_gfx.h" +#include "affine_main_menu_background_gfx.h" #include "graphic_utils.h" BG_AFFINE bgaff; -AFF_SRC_EX asx = {32<<8, 64<<8, 120, 80, 0x0100, 0x0100, 0}; +AFF_SRC_EX asx = {0}; + +enum AffineBackgroundID background = AFFINE_BG_MAIN_MENU; void affine_background_init() -{ - memcpy32_tile8_with_palette_offset((u32*)&tile8_mem[AFFINE_BG_CBB], (const u32*)affine_background_gfxTiles, affine_background_gfxTilesLen/4, AFFINE_BG_PB); - GRIT_CPY(&se_mem[AFFINE_BG_SBB], affine_background_gfxMap); - affine_background_load_palette(affine_background_gfxPal); +{ + affine_background_change_background(background); bgaff = bg_aff_default; } @@ -20,20 +21,37 @@ void affine_background_update() static uint timer = 0; timer++; - // These values are not permament, just the current configuration for the affine background - asx.tex_x += 5; - asx.tex_y += 12; - asx.sx = (lu_sin(timer * 100)) >> 8; // Scale the sine value to fit in a s16 - asx.sx += 256; // Add 256 to the sine value to make it positive - asx.sy = (lu_sin(timer * 100 + 0x4000)) >> 8; // Scale the sine value to fit in a s16 - asx.sy += 256; // Add 256 to the sine value to make it positive + switch (background) + { + case AFFINE_BG_MAIN_MENU: + asx.scr_x = SCREEN_WIDTH / 2; + asx.scr_y = SCREEN_HEIGHT / 2; + asx.tex_x = 16560; + asx.tex_y = 14400; + asx.sx = 128; + asx.sy = 128; + asx.alpha = 1000; // This slightly rotates it which increases the percieved resolution of the background + break; + case AFFINE_BG_GAME: + asx.scr_x = 0; + asx.scr_y = 0; + asx.tex_x += 5; + asx.tex_y += 12; + asx.sx = (lu_sin(timer * 100)) >> 8; // Scale the sine value to fit in a s16 + asx.sx += 256; // Add 256 to the sine value to make it positive + asx.sy = (lu_sin(timer * 100 + 0x4000)) >> 8; // Scale the sine value to fit in a s16 + asx.sy += 256; // Add 256 to the sine value to make it positive + asx.alpha = 0; + break; + } + bg_rotscale_ex(&bgaff, &asx); REG_BG_AFFINE[2] = bgaff; } void affine_background_set_color(COLOR color) { - memcpy16(&pal_bg_mem[AFFINE_BG_PB], affine_background_gfxPal, AFFINE_BG_PAL_LEN); + memcpy16(&pal_bg_mem[AFFINE_BG_PB], affine_main_menu_background_gfxPal, AFFINE_BG_PAL_LEN); for (int i = 0; i < AFFINE_BG_PAL_LEN; i++) { clr_rgbscale(&pal_bg_mem[AFFINE_BG_PB] + i, &pal_bg_mem[AFFINE_BG_PB] + i, 1, color); @@ -43,4 +61,29 @@ void affine_background_set_color(COLOR color) void affine_background_load_palette(const u16 *src) { memcpy16(&pal_bg_mem[AFFINE_BG_PB], src, AFFINE_BG_PAL_LEN); +} + +void affine_background_change_background(enum AffineBackgroundID new_bg) +{ + background = new_bg; + + switch (background) + { + case AFFINE_BG_MAIN_MENU: + REG_BG2CNT &= ~BG_AFF_32x32; + REG_BG2CNT |= BG_AFF_16x16; + + memcpy32_tile8_with_palette_offset((u32*)&tile8_mem[AFFINE_BG_CBB], (const u32*)affine_main_menu_background_gfxTiles, affine_main_menu_background_gfxTilesLen/4, AFFINE_BG_PB); + GRIT_CPY(&se_mem[AFFINE_BG_SBB], affine_main_menu_background_gfxMap); + affine_background_load_palette(affine_main_menu_background_gfxPal); + break; + case AFFINE_BG_GAME: + REG_BG2CNT &= ~BG_AFF_16x16; + REG_BG2CNT |= BG_AFF_32x32; + + memcpy32_tile8_with_palette_offset((u32*)&tile8_mem[AFFINE_BG_CBB], (const u32*)affine_background_gfxTiles, affine_background_gfxTilesLen/4, AFFINE_BG_PB); + GRIT_CPY(&se_mem[AFFINE_BG_SBB], affine_background_gfxMap); + affine_background_load_palette(affine_background_gfxPal); + break; + } } \ No newline at end of file diff --git a/source/game.c b/source/game.c index f58d644..9d3d73a 100644 --- a/source/game.c +++ b/source/game.c @@ -20,6 +20,8 @@ #include "background_shop_gfx.h" #include "background_blind_select_gfx.h" #include "affine_background_gfx.h" +#include "background_main_menu_gfx.h" +#include "affine_main_menu_background_gfx.h" #include "soundbank.h" @@ -33,7 +35,7 @@ static uint timer = 0; // This might already exist in libtonc but idk so i'm jus static int game_speed = 1; static int background = 0; -static enum GameState game_state = GAME_BLIND_SELECT; // The current game state, this is used to determine what the game is doing at any given time +static enum GameState game_state = GAME_MAIN_MENU; // The current game state, this is used to determine what the game is doing at any given time static enum HandState hand_state = HAND_DRAW; static enum PlayState play_state = PLAY_PLAYING; static int state = 0; // General state variable, used for switch statements in each game state related function @@ -241,6 +243,8 @@ static const Rect CASHOUT_RECT = {88, 72, UNDEFINED, UNDEF static const Rect SHOP_REROLL_RECT = {88, 96, UNDEFINED, UNDEFINED }; //TODO: Properly define and use +#define MAIN_MENU_BUTTONS 4 + #define MENU_POP_OUT_ANIM_FRAMES 20 #define SCORED_CARD_TEXT_Y 48 @@ -429,7 +433,8 @@ void change_background(int id) } else { - REG_DISPCNT |= DCNT_WIN0; // Enable window 0 to make hand background transparent + toggle_windows(true, true); // Enable window 0 for the hand shadow + // Load the tiles and palette // Background memcpy(pal_bg_mem, background_gfxPal, 64); // This '64" isn't a specific number, I'm just using it to prevent the text colors from being overridden @@ -484,16 +489,16 @@ void change_background(int id) background = BG_ID_ROUND_END; } - REG_DISPCNT &= ~DCNT_WIN0; // Disable window 0 so it doesn't make the cashout menu transparent + toggle_windows(false, true); // Disable window 0 so it doesn't make the cashout menu transparent main_bg_se_clear_rect(ROUND_END_MENU_RECT); tte_erase_rect_wrapper(HAND_SIZE_RECT); } else if (id == BG_ID_SHOP) { - REG_DISPCNT &= ~DCNT_WIN0; + toggle_windows(false, true); - memcpy(pal_bg_mem, background_shop_gfxPal, 64); + memcpy16(pal_bg_mem, background_shop_gfxPal, 64); GRIT_CPY(&tile_mem[MAIN_BG_CBB], background_shop_gfxTiles); GRIT_CPY(&se_mem[MAIN_BG_SBB], background_shop_gfxMap); @@ -520,7 +525,7 @@ void change_background(int id) sprite_position(blind_select_tokens[BIG_BLIND], 120, default_y); sprite_position(blind_select_tokens[BOSS_BLIND], 160, default_y); - REG_DISPCNT &= ~DCNT_WIN0; + toggle_windows(false, true); memcpy16(pal_bg_mem, background_blind_select_gfxPal, 64); GRIT_CPY(&tile_mem[MAIN_BG_CBB], background_blind_select_gfxTiles); @@ -619,6 +624,21 @@ void change_background(int id) } } } + else if (id == BG_ID_MAIN_MENU) + { + toggle_windows(false, false); + + tte_erase_screen(); + memcpy16(pal_bg_mem, background_main_menu_gfxPal, PAL_ROW_LEN * 9); + GRIT_CPY(&tile_mem[MAIN_BG_CBB], background_main_menu_gfxTiles); + GRIT_CPY(&se_mem[MAIN_BG_SBB], background_main_menu_gfxMap); + + // Disable the button highlight colors + // Select button PID is 5 and the outline is 3 + memcpy16(&pal_bg_mem[3], &pal_bg_mem[5], 1); + + affine_background_change_background(AFFINE_BG_MAIN_MENU); + } else { return; // Invalid background ID @@ -1015,10 +1035,7 @@ void jokers_avialable_to_shop_init() void game_init() { - jokers_avialable_to_shop_init(); - - hands = max_hands; - discards = max_discards; + change_background(BG_ID_MAIN_MENU); blind_select_tokens[SMALL_BLIND] = blind_token_new(SMALL_BLIND, 8, 18, MAX_SELECTION_SIZE + MAX_HAND_SIZE + 3); blind_select_tokens[BIG_BLIND] = blind_token_new(BIG_BLIND, 8, 18, MAX_SELECTION_SIZE + MAX_HAND_SIZE + 4); @@ -1037,8 +1054,26 @@ void game_init() deck_push(card); } } +} - change_background(BG_ID_BLIND_SELECT); +void game_start() +{ + affine_background_change_background(AFFINE_BG_GAME); + + jokers_avialable_to_shop_init(); + + hands = max_hands; + discards = max_discards; + + // Fill the deck with all the cards. Later on this can be replaced with a more dynamic system that allows for different decks and card types. + for (int suit = 0; suit < NUM_SUITS; suit++) + { + for (int rank = 0; rank < NUM_RANKS; rank++) + { + Card *card = card_new(suit, rank); + deck_push(card); + } + } tte_printf("#{P:%d,%d; cx:0xF000}%d/%d", DECK_SIZE_RECT.left, DECK_SIZE_RECT.top, deck_get_size(), deck_get_max_size()); // Deck size/max size @@ -1055,6 +1090,9 @@ void game_init() display_money(money); // Set the money display tte_printf("#{P:%d,%d; cx:0xC000}%d#{cx:0xF000}/%d", ANTE_TEXT_RECT.left, ANTE_TEXT_RECT.top, ante, MAX_ANTE); // Ante + + change_background(BG_ID_BLIND_SELECT); + game_set_state(GAME_BLIND_SELECT); } static void game_playing_process_hand_select_input() @@ -2375,7 +2413,6 @@ static void game_shop_lights_anim_frame() memcpy16(&pal_bg_mem[8], &shifted_palette[3], 1); } - void game_shop() { change_background(BG_ID_SHOP); @@ -2473,8 +2510,6 @@ void game_shop() } } - - void game_blind_select() { switch (state) // I'm only using magic numbers here for the sake of simplicity since it's just sequential, but you can replace them with named constants or enums if it makes it clearer @@ -2639,6 +2674,48 @@ void game_blind_select() } } +void game_main_menu() +{ + change_background(BG_ID_MAIN_MENU); + + if (key_hit(KEY_LEFT)) + { + if (selection_x > 0) + { + selection_x--; + } + } + else if (key_hit(KEY_RIGHT)) + { + // TODO: Don't allow cursor on sold items + if (selection_x < MAIN_MENU_BUTTONS) + { + selection_x++; + } + else if (selection_x < MAIN_MENU_BUTTONS) + { + selection_x++; + } + } + + if (selection_x == 0) // Play button + { + // Select button PID is 5 and the outline is 3 + memset16(&pal_bg_mem[3], CLR_WHITE, 1); + + if (key_hit(KEY_A)) + { + // Start the game + game_start(); + } + } + else + { + // Select button PID is 5 and the outline is 3 + memcpy16(&pal_bg_mem[3], &pal_bg_mem[5], 1); + } +} + void game_update() { timer++; @@ -2656,6 +2733,9 @@ void game_update() switch (game_state) { + case GAME_MAIN_MENU: + game_main_menu(); + break; case GAME_PLAYING: game_playing(); break; diff --git a/source/graphic_utils.c b/source/graphic_utils.c index b568442..2c64e88 100644 --- a/source/graphic_utils.c +++ b/source/graphic_utils.c @@ -186,4 +186,34 @@ void memcpy32_tile8_with_palette_offset(u32* dst, const u32* src, uint wcount, u // Copying u8 data 4 times across u32 data dst[i] = src[i] + offset; } +} + +void toggle_windows(bool win0, bool win1) +{ + if (win0) + { + REG_DISPCNT |= DCNT_WIN0; + } + else + { + REG_DISPCNT &= ~DCNT_WIN0; + } + + if (win1) + { + REG_DISPCNT |= DCNT_WIN1; + } + else + { + REG_DISPCNT &= ~DCNT_WIN1; + } + + if (win0 || win1) + { + REG_BLDCNT = BLD_BUILD(BLD_BG1, BLD_BG2, 1); + } + else + { + REG_BLDCNT = 0; + } } \ No newline at end of file diff --git a/source/main.c b/source/main.c index 76abc07..bbee8aa 100644 --- a/source/main.c +++ b/source/main.c @@ -44,7 +44,7 @@ void init() // BG1 is the main background layer REG_BG1CNT = BG_PRIO(1) | BG_CBB(MAIN_BG_CBB) | BG_SBB(MAIN_BG_SBB) | BG_8BPP; // BG2 is the affine background layer - REG_BG2CNT = BG_PRIO(2) | BG_CBB(AFFINE_BG_CBB) | BG_SBB(AFFINE_BG_CBB) | BG_8BPP | BG_WRAP | BG_AFF_32x32; + REG_BG2CNT = BG_PRIO(2) | BG_CBB(AFFINE_BG_CBB) | BG_SBB(AFFINE_BG_CBB) | BG_8BPP | BG_WRAP | BG_AFF_16x16; int win1_left = 72; int win1_top = 44;