From cbc1b9d92c85615b4ea3a7a5ae36105c807934d2 Mon Sep 17 00:00:00 2001 From: Lorenzooone Date: Thu, 16 Feb 2023 02:08:49 +0100 Subject: [PATCH] Implement trading animation --- .gitignore | 2 + include/animations_handler.h | 8 ++++ include/graphics_handler.h | 7 +++ include/menu_text_handler.h | 2 + include/party_handler.h | 2 +- include/print_system.h | 3 ++ include/sprite_handler.h | 38 +++++++++++------ include/window_handler.h | 18 ++++++++ source/animations_handler.c | 83 ++++++++++++++++++++++++++++++++++++ source/graphics_handler.c | 4 -- source/main.c | 35 +++++++++++++-- source/menu_text_handler.c | 54 ++++++++++++++++++++--- source/party_handler.c | 6 +-- source/print_system.c | 7 +++ source/sprite_handler.c | 51 +++++++++++++--------- source/window_handler.c | 16 +++++++ 16 files changed, 288 insertions(+), 48 deletions(-) create mode 100644 include/animations_handler.h create mode 100644 source/animations_handler.c diff --git a/.gitignore b/.gitignore index 4f1e92b..af75ca4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ build/ *.elf *.gba +*.GBA *.sav +*.SAV *.py settings.sh __pycache__/ diff --git a/include/animations_handler.h b/include/animations_handler.h new file mode 100644 index 0000000..d93afd8 --- /dev/null +++ b/include/animations_handler.h @@ -0,0 +1,8 @@ +#ifndef ANIMATIONS_HANDLER__ +#define ANIMATIONS_HANDLER__ + +void setup_trade_animation(struct gen3_mon_data_unenc*, struct gen3_mon_data_unenc*, u8, u8); +void advance_trade_animation(void); +u8 get_trade_animation_state(void); + +#endif diff --git a/include/graphics_handler.h b/include/graphics_handler.h index 2c1f1ba..5fd766a 100644 --- a/include/graphics_handler.h +++ b/include/graphics_handler.h @@ -3,6 +3,13 @@ #include +#define NUM_POKEMON_SPRITES 2 +#define POKEMON_SPRITE_X_TILES 4 +#define POKEMON_SPRITE_Y_TILES 4 + +#define ITEM_SPRITE_X_TILES 1 +#define ITEM_SPRITE_Y_TILES 1 + void load_pokemon_sprite_gfx(const u32*, u32*, u8, u8, u8, u8*); void convert_xbpp(u8*, u32*, size_t, u8*, u8, u8); diff --git a/include/menu_text_handler.h b/include/menu_text_handler.h index e9b54c5..6cc25a6 100644 --- a/include/menu_text_handler.h +++ b/include/menu_text_handler.h @@ -8,6 +8,8 @@ void print_game_info(struct game_data_t*, int); void print_trade_menu(struct game_data_t*, u8, u8, u8, u8); void print_trade_menu_cancel(u8); +void print_trade_animation_send(struct gen3_mon_data_unenc*); +void print_trade_animation_recv(struct gen3_mon_data_unenc*); void print_set_nature(u8, struct gen3_mon_data_unenc*); void print_iv_fix(struct gen3_mon_data_unenc*); void print_pokemon_pages(u8, u8, struct gen3_mon_data_unenc*, u8); diff --git a/include/party_handler.h b/include/party_handler.h index 0184d9e..8a2cd29 100644 --- a/include/party_handler.h +++ b/include/party_handler.h @@ -353,7 +353,7 @@ const u8* get_pokeball_base_name_gen3_raw(struct gen3_mon_data_unenc*); u8 get_trainer_gender_char_raw(struct gen3_mon_data_unenc*); u8 is_egg_gen3_raw(struct gen3_mon_data_unenc*); u8 has_pokerus_gen3_raw(struct gen3_mon_data_unenc*); -void load_pokemon_sprite_raw(struct gen3_mon_data_unenc*, u16, u16); +void load_pokemon_sprite_raw(struct gen3_mon_data_unenc*, u8, u16, u16); u8 get_pokemon_gender_raw(struct gen3_mon_data_unenc*); char get_pokemon_gender_char_raw(struct gen3_mon_data_unenc*); u8 is_shiny_gen3_raw(struct gen3_mon_data_unenc*, u32); diff --git a/include/print_system.h b/include/print_system.h index fbf398c..aa58db0 100644 --- a/include/print_system.h +++ b/include/print_system.h @@ -9,6 +9,8 @@ #define X_SIZE (SCREEN_REAL_WIDTH>>3) #define Y_SIZE (SCREEN_REAL_HEIGHT>>3) +#define SCREEN_HALF_X (X_LIMIT>>1) + #define PALETTE 0xF #define HSWAP_TILE 0x400 @@ -35,6 +37,7 @@ void default_reset_screen(void); void reset_screen(u8); void set_text_x(u8); void set_text_y(u8); +void swap_screen_enabled_state(u8); void enable_screen(u8); void disable_screen(u8); void disable_all_screens_but_current(void); diff --git a/include/sprite_handler.h b/include/sprite_handler.h index 013e1e2..c0bb05a 100644 --- a/include/sprite_handler.h +++ b/include/sprite_handler.h @@ -1,26 +1,38 @@ #ifndef SPRITE_HANDLER__ #define SPRITE_HANDLER__ +#include "print_system.h" +#include "graphics_handler.h" + +#define TOP_SCREEN_SPRITE_POS SCREEN_REAL_HEIGHT +#define LEFT_SCREEN_SPRITE_POS SCREEN_REAL_WIDTH + #define BASE_Y_SPRITE_INFO_PAGE 0 #define BASE_X_SPRITE_INFO_PAGE 0 -#define BASE_Y_SPRITE_NATURE_PAGE 248 +#define BASE_Y_SPRITE_TRADE_ANIMATION_SEND ((SCREEN_HEIGHT>>1)-((POKEMON_SPRITE_Y_TILES<<3)>>1)) +#define BASE_X_SPRITE_TRADE_ANIMATION ((SCREEN_WIDTH>>1)-((POKEMON_SPRITE_X_TILES<<3)>>1)) +#define BASE_Y_SPRITE_TRADE_ANIMATION_RECV (TOP_SCREEN_SPRITE_POS-(POKEMON_SPRITE_Y_TILES<<3)) +#define BASE_Y_SPRITE_TRADE_ANIMATION_END_RUN_INC (TOP_SCREEN_SPRITE_POS-BASE_Y_SPRITE_TRADE_ANIMATION_RECV) + +#define BASE_Y_SPRITE_NATURE_PAGE (TOP_SCREEN_SPRITE_POS-8) #define BASE_X_SPRITE_NATURE_PAGE 0 -#define BASE_Y_SPRITE_IV_FIX_PAGE 248 +#define BASE_Y_SPRITE_IV_FIX_PAGE (TOP_SCREEN_SPRITE_POS-8) #define BASE_X_SPRITE_IV_FIX_PAGE 0 #define X_OFFSET_TRADE_MENU 0 #define Y_OFFSET_TRADE_MENU -3 #define Y_OFFSET_TRADE_MENU_SPRITES (Y_OFFSET_TRADE_MENU + 2) -#define BASE_Y_CURSOR_TRADING_MENU (16 - Y_OFFSET_TRADE_MENU_SPRITES + 1) -#define BASE_X_CURSOR_TRADING_MENU (1 - X_OFFSET_TRADE_MENU) -#define BASE_Y_CURSOR_INCREMENT_TRADING_MENU 24 -#define BASE_X_CURSOR_INCREMENT_TRADING_MENU 120 #define BASE_Y_SPRITE_TRADE_MENU (0 - Y_OFFSET_TRADE_MENU_SPRITES) -#define BASE_Y_SPRITE_INCREMENT_TRADE_MENU 24 +#define BASE_Y_SPRITE_INCREMENT_TRADE_MENU (3*8) #define BASE_X_SPRITE_TRADE_MENU (8 - X_OFFSET_TRADE_MENU) -#define CURSOR_Y_POS_CANCEL 152 +#define BASE_X_SPRITE_INCREMENT_TRADE_MENU (SCREEN_HALF_X << 3) +#define BASE_Y_CURSOR_TRADING_MENU (16 + BASE_Y_SPRITE_TRADE_MENU + 1) +#define BASE_X_CURSOR_TRADING_MENU (1 - X_OFFSET_TRADE_MENU) +#define BASE_Y_CURSOR_INCREMENT_TRADING_MENU BASE_Y_SPRITE_INCREMENT_TRADE_MENU +#define BASE_X_CURSOR_INCREMENT_TRADING_MENU BASE_X_SPRITE_INCREMENT_TRADE_MENU +#define CURSOR_Y_POS_CANCEL (SCREEN_HEIGHT-8) #define CURSOR_X_POS_CANCEL 2 #define BASE_X_CURSOR_MAIN_MENU 2 @@ -28,15 +40,15 @@ #define BASE_Y_CURSOR_INCREMENT_MAIN_MENU 16 #define BASE_X_CURSOR_TRADE_OPTIONS 2 -#define BASE_X_CURSOR_INCREMENT_TRADE_OPTIONS 120 -#define BASE_Y_CURSOR_TRADE_OPTIONS 152 +#define BASE_X_CURSOR_INCREMENT_TRADE_OPTIONS (SCREEN_HALF_X << 3) +#define BASE_Y_CURSOR_TRADE_OPTIONS (SCREEN_HEIGHT-8) #define BASE_Y_SPRITE_OFFER_MENU 0 #define BASE_X_SPRITE_OFFER_MENU 0 -#define BASE_X_CURSOR_OFFER_OPTIONS 10 -#define BASE_Y_CURSOR_OFFER_OPTIONS 128 #define BASE_X_CURSOR_INCREMENT_OFFER_OPTIONS 64 #define BASE_Y_CURSOR_INCREMENT_OFFER_OPTIONS 16 +#define BASE_X_CURSOR_OFFER_OPTIONS 10 +#define BASE_Y_CURSOR_OFFER_OPTIONS (SCREEN_HEIGHT-16-(BASE_Y_CURSOR_INCREMENT_OFFER_OPTIONS*(2-1))) void init_sprites(void); void init_sprite_counter(void); @@ -47,10 +59,12 @@ void set_party_sprite_counter(void); void init_cursor(void); void update_cursor_y(u16); void update_cursor_base_x(u16); +void raw_update_sprite_y(u8, u8); void move_sprites(u8 counter); void move_cursor_x(u8 counter); void disable_cursor(void); void disable_all_cursors(void); +u8 get_next_sprite_index(void); void reset_sprites(u8); void disable_all_sprites(void); void enable_all_sprites(void); diff --git a/include/window_handler.h b/include/window_handler.h index bbf15ea..e044eb5 100644 --- a/include/window_handler.h +++ b/include/window_handler.h @@ -10,6 +10,18 @@ #define TRADE_OPTIONS_WINDOW_X_SIZE TOTAL_X_SIZE #define TRADE_OPTIONS_WINDOW_Y_SIZE 1 +#define TRADE_ANIMATION_SEND_WINDOW_SCREEN 1 +#define TRADE_ANIMATION_SEND_WINDOW_X 1 +#define TRADE_ANIMATION_SEND_WINDOW_Y_SIZE 3 +#define TRADE_ANIMATION_SEND_WINDOW_Y (TOTAL_Y_SIZE-1-TRADE_ANIMATION_SEND_WINDOW_Y_SIZE) +#define TRADE_ANIMATION_SEND_WINDOW_X_SIZE (TOTAL_X_SIZE-TRADE_ANIMATION_SEND_WINDOW_X-1) + +#define TRADE_ANIMATION_RECV_WINDOW_SCREEN 2 +#define TRADE_ANIMATION_RECV_WINDOW_X 1 +#define TRADE_ANIMATION_RECV_WINDOW_Y_SIZE 3 +#define TRADE_ANIMATION_RECV_WINDOW_Y (TOTAL_Y_SIZE-1-TRADE_ANIMATION_RECV_WINDOW_Y_SIZE) +#define TRADE_ANIMATION_RECV_WINDOW_X_SIZE (TOTAL_X_SIZE-TRADE_ANIMATION_RECV_WINDOW_X-1) + #define WAITING_WINDOW_SCREEN 3 #define WAITING_WINDOW_X_SIZE 10 #define WAITING_WINDOW_Y_SIZE 1 @@ -55,6 +67,12 @@ void clear_offer_options_window(void); void init_waiting_window(void); void clear_waiting_window(void); +void init_trade_animation_send_window(void); +void clear_trade_animation_send_window(void); + +void init_trade_animation_recv_window(void); +void clear_trade_animation_recv_window(void); + void init_saving_window(void); void clear_saving_window(void); diff --git a/source/animations_handler.c b/source/animations_handler.c new file mode 100644 index 0000000..ddd9b68 --- /dev/null +++ b/source/animations_handler.c @@ -0,0 +1,83 @@ +#include +#include "party_handler.h" +#include "sprite_handler.h" +#include "animations_handler.h" +#include "graphics_handler.h" +#include + +#define OWN_SPRITE_INDEX 0 +#define OTHER_SPRITE_INDEX 1 +#define EVOLUTION_SPRITE_INDEX 0 +#define TOTAL_SPRITES 2 + +#define FIRST_SPEEDUP_THRESHOLD (BASE_Y_SPRITE_TRADE_ANIMATION_SEND+BASE_Y_SPRITE_TRADE_ANIMATION_END_RUN_INC-8) +#define SECOND_SPEEDUP_THRESHOLD (FIRST_SPEEDUP_THRESHOLD-16) +#define THIRD_SPEEDUP_THRESHOLD (SECOND_SPEEDUP_THRESHOLD-32) + +u8 sprite_indexes[TOTAL_SPRITES]; +u8 sprite_ys[TOTAL_SPRITES]; +u8 screen_nums[TOTAL_SPRITES]; +u8 trade_animation_counter; +u8 trade_animation_completed; + +void setup_trade_animation(struct gen3_mon_data_unenc* own_mon, struct gen3_mon_data_unenc* other_mon, u8 own_screen, u8 other_screen) { + sprite_indexes[OWN_SPRITE_INDEX] = get_next_sprite_index(); + sprite_ys[OWN_SPRITE_INDEX] = BASE_Y_SPRITE_TRADE_ANIMATION_SEND; + screen_nums[OWN_SPRITE_INDEX] = own_screen; + load_pokemon_sprite_raw(own_mon, 0, BASE_Y_SPRITE_TRADE_ANIMATION_SEND, BASE_X_SPRITE_TRADE_ANIMATION); + sprite_indexes[OTHER_SPRITE_INDEX] = get_next_sprite_index(); + sprite_ys[OTHER_SPRITE_INDEX] = BASE_Y_SPRITE_TRADE_ANIMATION_RECV; + screen_nums[OTHER_SPRITE_INDEX] = other_screen; + load_pokemon_sprite_raw(other_mon, 0, BASE_Y_SPRITE_TRADE_ANIMATION_RECV, BASE_X_SPRITE_TRADE_ANIMATION); + trade_animation_counter = 0; + trade_animation_completed = 0; +} + +u8 get_trade_animation_state() { + return trade_animation_completed; +} + +void advance_trade_animation() { + u8 index = OWN_SPRITE_INDEX; + s32 inc_type = -1; + if(sprite_ys[OWN_SPRITE_INDEX] == BASE_Y_SPRITE_TRADE_ANIMATION_RECV) { + index = OTHER_SPRITE_INDEX; + inc_type = +1; + } + + if(trade_animation_completed) + return; + + u8 curr_y = sprite_ys[index] + BASE_Y_SPRITE_TRADE_ANIMATION_END_RUN_INC; + u8 scheduled_change = 0; + trade_animation_counter++; + + if(curr_y < THIRD_SPEEDUP_THRESHOLD) + scheduled_change = 1; + else if(curr_y < SECOND_SPEEDUP_THRESHOLD) { + if(trade_animation_counter == 2) + scheduled_change = 1; + } + else if(curr_y < FIRST_SPEEDUP_THRESHOLD) { + if(trade_animation_counter == 4) + scheduled_change = 1; + } + else { + if(trade_animation_counter == 8) + scheduled_change = 1; + } + + if((scheduled_change) && (curr_y == THIRD_SPEEDUP_THRESHOLD)) { + swap_screen_enabled_state(screen_nums[index]); + prepare_flush(); + } + + if(scheduled_change) { + sprite_ys[index] += inc_type; + trade_animation_counter = 0; + raw_update_sprite_y(sprite_indexes[index], sprite_ys[index]); + } + + if(sprite_ys[OTHER_SPRITE_INDEX] == BASE_Y_SPRITE_TRADE_ANIMATION_SEND) + trade_animation_completed = 1; +} diff --git a/source/graphics_handler.c b/source/graphics_handler.c index e215d62..79a6a06 100644 --- a/source/graphics_handler.c +++ b/source/graphics_handler.c @@ -4,10 +4,6 @@ #include "print_system.h" #include -#define NUM_POKEMON_SPRITES 2 - -#define POKEMON_SPRITE_X_TILES 4 -#define POKEMON_SPRITE_Y_TILES 4 #define POKEMON_SPRITE_ROW_SIZE (TILE_SIZE*POKEMON_SPRITE_X_TILES) #define SINGLE_POKEMON_SPRITE_SIZE (POKEMON_SPRITE_ROW_SIZE*POKEMON_SPRITE_Y_TILES) #define TOTAL_POKEMON_SPRITE_SIZE (SINGLE_POKEMON_SPRITE_SIZE*NUM_POKEMON_SPRITES) diff --git a/source/main.c b/source/main.c index 43f2c1c..d59ca12 100644 --- a/source/main.c +++ b/source/main.c @@ -18,6 +18,7 @@ #include "gen_converter.h" #include "sio.h" #include "vcount_basic.h" +#include "animations_handler.h" #include //#include "save.h" @@ -47,6 +48,7 @@ void change_nature(struct game_data_t*, u8, u8, u8*, u8); void check_bad_trade_received(struct game_data_t*, u8, u8, u8, u8, u8, u8*); void trade_cancel_print_screen(u8); void saving_print_screen(void); +void trading_animation_init(struct game_data_t*, u8, u8); void offer_init(struct game_data_t*, u8, u8, u8*, u8*, u8); void waiting_init(void); void invalid_init(u8); @@ -77,6 +79,10 @@ IWRAM_CODE void vblank_update_function() { move_cursor_x(counter); advance_rng(); counter++; + + // Handle trading animation + if(curr_state == TRADING_ANIMATION) + advance_trade_animation(); // Handle slave communications if((REG_SIOCNT & SIO_IRQ) && (!(REG_SIOCNT & SIO_START))) slave_routine(); @@ -210,6 +216,25 @@ void saving_print_screen() { prepare_flush(); } +void trading_animation_init(struct game_data_t* game_data, u8 own_mon, u8 other_mon) { + set_screen(BASE_SCREEN); + reset_sprites_to_party(); + disable_all_screens_but_current(); + disable_all_cursors(); + disable_all_sprites(); + default_reset_screen(); + set_screen(TRADE_ANIMATION_SEND_WINDOW_SCREEN); + print_trade_animation_send(&game_data[0].party_3_undec[own_mon]); + set_screen(TRADE_ANIMATION_RECV_WINDOW_SCREEN); + print_trade_animation_recv(&game_data[1].party_3_undec[other_mon]); + set_screen(BASE_SCREEN); + enable_screen(BASE_SCREEN); + enable_screen(TRADE_ANIMATION_SEND_WINDOW_SCREEN); + setup_trade_animation(&game_data[0].party_3_undec[own_mon], &game_data[1].party_3_undec[other_mon], TRADE_ANIMATION_SEND_WINDOW_SCREEN, TRADE_ANIMATION_RECV_WINDOW_SCREEN); + prepare_flush(); + curr_state = TRADING_ANIMATION; +} + void offer_init(struct game_data_t* game_data, u8 own_mon, u8 other_mon, u8* cursor_y_pos, u8* cursor_x_pos, u8 reset) { curr_state = OFFER_MENU; set_screen(BASE_SCREEN); @@ -421,13 +446,14 @@ int main(void) u8 submenu_cursor_x_pos = 0; u8 prev_val = 0; u8 curr_mon = 0; + u8 success = 0; u8 other_mon = 0; u8 curr_page = 0; const u8* party_selected_mons[2] = {&curr_mon, &other_mon}; main_menu_init(&game_data[0], target, region, master, &cursor_y_pos); - //load_pokemon_sprite_raw(&game_data[1].party_3_undec[0], 0, 0); + //load_pokemon_sprite_raw(&game_data[1].party_3_undec[0], 1, 0, 0); //worst_case_conversion_tester(&counter); //PRINT_FUNCTION("\n\n0x\x0D: 0x\x0D\n", REG_MEMORY_CONTROLLER_ADDR, 8, REG_MEMORY_CONTROLLER, 8); scanKeys(); @@ -475,9 +501,10 @@ int main(void) else if(get_trading_state() == RECEIVED_ACCEPT) { keys = 0; if(has_accepted_offer()) { + trading_animation_init(game_data, curr_mon, other_mon); evolved = trade_mons(game_data, curr_mon, other_mon, learnset_ptr, curr_gen); + success = pre_write_gen_3_data(&game_data[0]); process_party_data(&game_data[0]); - curr_state = TRADING_ANIMATION; } else return_to_trade_menu(game_data, target, region, master, curr_gen, own_menu, &cursor_y_pos, &cursor_x_pos); @@ -610,7 +637,7 @@ int main(void) set_default_gift_ribbons(&game_data[cursor_x_pos]); if(!cursor_x_pos) { saving_print_screen(); - u8 success = pre_write_gen_3_data(&game_data[0]); + success = pre_write_gen_3_data(&game_data[0]); if(success) success = complete_write_gen_3_data(); if(!success) { @@ -636,6 +663,8 @@ int main(void) else cursor_update_offer_options(submenu_cursor_y_pos, submenu_cursor_x_pos); break; + case TRADING_ANIMATION: + break; default: main_menu_init(&game_data[0], target, region, master, &cursor_y_pos); break; diff --git a/source/menu_text_handler.c b/source/menu_text_handler.c index a3356ab..d4b50eb 100644 --- a/source/menu_text_handler.c +++ b/source/menu_text_handler.c @@ -89,7 +89,7 @@ void print_trade_menu(struct game_data_t* game_data, u8 update, u8 curr_gen, u8 PRINT_FUNCTION("\x05 - Gen \x03\n", game_data[0].trainer_name, OT_NAME_GEN3_SIZE+1, game_data[0].game_identifier.game_is_jp, curr_gen); else { for(int i = 0; i < num_parties; i++) { - set_text_x((X_LIMIT>>1) * i); + set_text_x(SCREEN_HALF_X * i); PRINT_FUNCTION("\x05 - \x01", game_data[i].trainer_name, OT_NAME_GEN3_SIZE+1, game_data[i].game_identifier.game_is_jp, person_strings[i]); } } @@ -104,7 +104,7 @@ void print_trade_menu(struct game_data_t* game_data, u8 update, u8 curr_gen, u8 set_text_y(2+(3 * i)); for(int j = 0; j < num_parties; j++) { // These two values are for debug only - They should be j and i - set_text_x(5 + ((X_LIMIT>>1) * j)); + set_text_x(5 + (SCREEN_HALF_X * j)); u8 party_index = j; u8 party_option_index = i; if(options[party_index][party_option_index] != 0xFF) { @@ -112,7 +112,7 @@ void print_trade_menu(struct game_data_t* game_data, u8 update, u8 curr_gen, u8 // I tried just using printf here with left padding, but it's EXTREMELY slow PRINT_FUNCTION("\x01", get_pokemon_name_raw(mon)); if(load_sprites) - load_pokemon_sprite_raw(mon, BASE_Y_SPRITE_TRADE_MENU + (i*BASE_Y_SPRITE_INCREMENT_TRADE_MENU), (((X_LIMIT >> 1) << 3)*j) + BASE_X_SPRITE_TRADE_MENU); + load_pokemon_sprite_raw(mon, 1, BASE_Y_SPRITE_TRADE_MENU + (i*BASE_Y_SPRITE_INCREMENT_TRADE_MENU), (BASE_X_SPRITE_INCREMENT_TRADE_MENU*j) + BASE_X_SPRITE_TRADE_MENU); } } } @@ -146,7 +146,7 @@ void print_offer_screen(struct game_data_t* game_data, u8 own_mon, u8 other_mon) set_text_y(curr_text_y++); set_text_x(3+(OFFER_WINDOW_X*i)); PRINT_FUNCTION("\x01", offer_strings[i]); - load_pokemon_sprite_raw(mon, BASE_Y_SPRITE_OFFER_MENU, (OFFER_WINDOW_X*8*i) + BASE_X_SPRITE_OFFER_MENU); + load_pokemon_sprite_raw(mon, 1, BASE_Y_SPRITE_OFFER_MENU, (OFFER_WINDOW_X*8*i) + BASE_X_SPRITE_OFFER_MENU); if(!is_egg) { set_text_y(curr_text_y++); @@ -254,6 +254,48 @@ void print_waiting(){ PRINT_FUNCTION("Waiting..."); } +void print_trade_animation_send(struct gen3_mon_data_unenc* mon){ + u8 is_jp = mon->src->language == JAPANESE_LANGUAGE; + u8 is_egg = mon->is_egg; + + reset_screen(BLANK_FILL); + init_trade_animation_send_window(); + clear_trade_animation_send_window(); + set_text_y(TRADE_ANIMATION_SEND_WINDOW_Y); + set_text_x(TRADE_ANIMATION_SEND_WINDOW_X); + if(!is_egg) { + PRINT_FUNCTION("Sending \x01 away...\n\n", get_pokemon_name_raw(mon)); + set_text_x(TRADE_ANIMATION_SEND_WINDOW_X); + PRINT_FUNCTION("Goodbye, \x05!", mon->src->nickname, NICKNAME_GEN3_SIZE, is_jp); + } + else { + PRINT_FUNCTION("Sending an Egg away...\n\n"); + set_text_x(TRADE_ANIMATION_SEND_WINDOW_X); + PRINT_FUNCTION("Who knows what's inside..."); + } +} + +void print_trade_animation_recv(struct gen3_mon_data_unenc* mon){ + u8 is_jp = mon->src->language == JAPANESE_LANGUAGE; + u8 is_egg = mon->is_egg; + + reset_screen(BLANK_FILL); + init_trade_animation_recv_window(); + clear_trade_animation_recv_window(); + set_text_y(TRADE_ANIMATION_RECV_WINDOW_Y); + set_text_x(TRADE_ANIMATION_RECV_WINDOW_X); + if(!is_egg) { + PRINT_FUNCTION("Received \x01.\n\n", get_pokemon_name_raw(mon)); + set_text_x(TRADE_ANIMATION_RECV_WINDOW_X); + PRINT_FUNCTION("Welcome, \x05!", mon->src->nickname, NICKNAME_GEN3_SIZE, is_jp); + } + else { + PRINT_FUNCTION("Received an Egg.\n\n"); + set_text_x(TRADE_ANIMATION_SEND_WINDOW_X); + PRINT_FUNCTION("Who knows what's inside!"); + } +} + void print_saving(){ reset_screen(BLANK_FILL); init_saving_window(); @@ -360,7 +402,7 @@ void print_pokemon_base_data(u8 load_sprites, struct gen3_mon_data_unenc* mon, u if(load_sprites) { reset_sprites_to_party(); - load_pokemon_sprite_raw(mon, y, x); + load_pokemon_sprite_raw(mon, 1, y, x); } set_text_y((y>>3) + 2); @@ -490,7 +532,7 @@ void print_pokemon_page5(struct gen3_mon_data_unenc* mon) { set_text_y(6+i); PRINT_FUNCTION(" \x01\x01", get_ribbon_name(&mon->misc, ribbon_print_pos[(i*2)]), get_ribbon_rank_name(&mon->misc, ribbon_print_pos[(i*2)])); if(ribbon_print_pos[(i*2)+1] != 0xFF) { - set_text_x(X_LIMIT>>1); + set_text_x(SCREEN_HALF_X); PRINT_FUNCTION(" \x01\x01", get_ribbon_name(&mon->misc, ribbon_print_pos[(i*2)+1]), get_ribbon_rank_name(&mon->misc, ribbon_print_pos[(i*2)+1])); } } diff --git a/source/party_handler.c b/source/party_handler.c index e870afe..6549931 100644 --- a/source/party_handler.c +++ b/source/party_handler.c @@ -302,11 +302,11 @@ void load_pokemon_sprite(int index, u32 pid, u8 is_egg, u8 deoxys_form, u8 has_i set_pokemon_sprite(get_pokemon_sprite_pointer(index, pid, is_egg, deoxys_form), get_palette_references(index, pid, is_egg, deoxys_form), get_pokemon_sprite_info(index, pid, is_egg, deoxys_form), has_item, has_mail, y, x); } -void load_pokemon_sprite_raw(struct gen3_mon_data_unenc* data_src, u16 y, u16 x){ +void load_pokemon_sprite_raw(struct gen3_mon_data_unenc* data_src, u8 show_item, u16 y, u16 x){ if(!data_src->is_valid_gen3) - load_pokemon_sprite(0, 0, 0, 0, has_item_raw(data_src), has_mail_raw(data_src), y, x); + load_pokemon_sprite(0, 0, 0, 0, has_item_raw(data_src) & show_item, has_mail_raw(data_src) & show_item, y, x); - load_pokemon_sprite(data_src->growth.species, data_src->src->pid, data_src->is_egg, data_src->deoxys_form, has_item_raw(data_src), has_mail_raw(data_src), y, x); + load_pokemon_sprite(data_src->growth.species, data_src->src->pid, data_src->is_egg, data_src->deoxys_form, has_item_raw(data_src) & show_item, has_mail_raw(data_src) & show_item, y, x); } const u8* get_move_name_gen3(struct gen3_mon_attacks* attacks, u8 slot){ diff --git a/source/print_system.c b/source/print_system.c index 390629f..4f223ae 100644 --- a/source/print_system.c +++ b/source/print_system.c @@ -186,6 +186,13 @@ void wait_for_vblank_if_needed() { VBlankIntrWait(); } +void swap_screen_enabled_state(u8 bg_num){ + wait_for_vblank_if_needed(); + if(bg_num >= TOTAL_BG) + bg_num = TOTAL_BG-1; + enabled_screen[bg_num] ^= 1; +} + void enable_screen(u8 bg_num){ wait_for_vblank_if_needed(); if(bg_num >= TOTAL_BG) diff --git a/source/sprite_handler.c b/source/sprite_handler.c index cdd0cdc..7de3193 100644 --- a/source/sprite_handler.c +++ b/source/sprite_handler.c @@ -11,13 +11,15 @@ #define CPUFASTSET_FILL (0x1000000) -#define ITEM_ICON_INC_Y 24 -#define ITEM_ICON_INC_X 24 +#define ITEM_ICON_INC_X ((POKEMON_SPRITE_X_TILES-ITEM_SPRITE_X_TILES)<<3) +#define ITEM_ICON_INC_Y ((POKEMON_SPRITE_Y_TILES-ITEM_SPRITE_Y_TILES)<<3) -#define SPRITE_BASE_TILE_SIZE 0x10 +#define SPRITE_BASE_SIZE_MULTIPLIER NUM_POKEMON_SPRITES +#define SPRITE_BASE_TILE_SIZE (POKEMON_SPRITE_Y_TILES*POKEMON_SPRITE_X_TILES) +#define SPRITE_TILE_SIZE (SPRITE_BASE_SIZE_MULTIPLIER*SPRITE_BASE_TILE_SIZE) #define SPRITE_ALT_DISTANCE (SPRITE_BASE_TILE_SIZE*TILE_SIZE) -#define SPRITE_SIZE (2*SPRITE_ALT_DISTANCE) +#define SPRITE_SIZE (SPRITE_BASE_SIZE_MULTIPLIER*SPRITE_ALT_DISTANCE) #define OVRAM_START ((uintptr_t)OBJ_BASE_ADR) #define OVRAM_SIZE 0x8000 #define OVRAM_END (OVRAM_START+OVRAM_SIZE) @@ -110,6 +112,10 @@ void inc_inner_sprite_counter(){ __inner_sprite_counter++; } +u8 get_next_sprite_index(){ + return __inner_sprite_counter; +} + u8 get_first_variable_palette(){ return ((sprite_palettes_bin_size + item_icon_palette_bin_size)>>5); } @@ -140,14 +146,13 @@ void set_palette_3bpp(u8* colors, int index, int palette) { void init_cursor(){ sprite_pointers[__sprite_counter] = (const u8*)sprite_cursor_gfx; - u16* vram_pos = (u16*)get_vram_pos(); - for(size_t i = 0; i < (sprite_cursor_bin_size>>1); i++) - vram_pos[i] = sprite_cursor_gfx[i]; - vram_pos = (u16*)(get_vram_pos() + SPRITE_ALT_DISTANCE); - for(size_t i = 0; i < (sprite_cursor_bin_size>>1); i++) - vram_pos[i] = sprite_cursor_gfx[i]; + for(int i = 0; i < SPRITE_BASE_SIZE_MULTIPLIER; i++) { + u16* vram_pos = (u16*)(get_vram_pos() + (SPRITE_ALT_DISTANCE*i)); + for(size_t j = 0; j < (sprite_cursor_bin_size>>1); j++) + vram_pos[j] = sprite_cursor_gfx[j]; + } for(int i = 0; i < TOTAL_BG; i++) { - set_attributes(OFF_SCREEN_SPRITE, 0, (32*__sprite_counter) | ((3-i)<<10)); + set_attributes(OFF_SCREEN_SPRITE, 0, (SPRITE_TILE_SIZE*__sprite_counter) | ((3-i)<<10)); if(i < TOTAL_BG-1) inc_inner_sprite_counter(); } @@ -165,16 +170,15 @@ void init_oam_palette(){ } void init_item_icon(){ - u16* vram_pos = (u16*)(get_vram_pos() + sprite_cursor_bin_size); - for(size_t i = 0; i < (item_icon_bin_size>>1); i++) - vram_pos[i] = item_icon_gfx[i]; - vram_pos = (u16*)(get_vram_pos() + SPRITE_ALT_DISTANCE + sprite_cursor_bin_size); - for(size_t i = 0; i < (item_icon_bin_size>>1); i++) - vram_pos[i] = item_icon_gfx[i]; + for(int i = 0; i < SPRITE_BASE_SIZE_MULTIPLIER; i++) { + u16* vram_pos = (u16*)(get_vram_pos() + sprite_cursor_bin_size + (SPRITE_ALT_DISTANCE*i)); + for(size_t j = 0; j < (item_icon_bin_size>>1); j++) + vram_pos[j] = item_icon_gfx[j]; + } } u16 get_item_icon_tile(){ - return (32*cursor_sprite) + (sprite_cursor_bin_size>>5); + return (SPRITE_TILE_SIZE*cursor_sprite) + (sprite_cursor_bin_size>>5); } u16 get_mail_icon_tile(){ @@ -222,7 +226,7 @@ void set_pokemon_sprite(const u8* address, u8 palette, u8 info, u8 display_item, palette = get_3bpp_palette(position-(cursor_sprite+1)); if(position < POSSIBLE_SPRITES) sprite_pointers[position] = address; - set_attributes(y, x|ATTR1_SIZE_32, (32*position)|(get_curr_priority()<<10)|(palette<<12)); + set_attributes(y, x|ATTR1_SIZE_32, (SPRITE_TILE_SIZE*position)|(get_curr_priority()<<10)|(palette<<12)); inc_inner_sprite_counter(); } @@ -236,6 +240,15 @@ void raw_update_cursor_x(u16 cursor_x){ shadow_oam[inner_cursor_sprite-get_loaded_priority()].attr1 = cursor_x; } +void raw_update_sprite_y(u8 index, u8 new_y){ + if(index >= OAM_ENTITIES) + index = OAM_ENTITIES-1; + OAM[index].attr0 &= ~0xFF; + OAM[index].attr0 |= new_y; + shadow_oam[index].attr0 &= ~0xFF; + shadow_oam[index].attr0 |= new_y; +} + void update_cursor_base_x(u16 cursor_x){ wait_for_vblank_if_needed(); cursor_base_x = cursor_x; diff --git a/source/window_handler.c b/source/window_handler.c index 8262fe6..71cc07c 100644 --- a/source/window_handler.c +++ b/source/window_handler.c @@ -33,6 +33,22 @@ void clear_waiting_window() { reset_window(WAITING_WINDOW_X, WAITING_WINDOW_Y, WAITING_WINDOW_X_SIZE, WAITING_WINDOW_Y_SIZE, WAITING_WINDOW_SCREEN); } +void init_trade_animation_send_window() { + create_window(TRADE_ANIMATION_SEND_WINDOW_X, TRADE_ANIMATION_SEND_WINDOW_Y, TRADE_ANIMATION_SEND_WINDOW_X_SIZE, TRADE_ANIMATION_SEND_WINDOW_Y_SIZE, TRADE_ANIMATION_SEND_WINDOW_SCREEN); +} + +void clear_trade_animation_send_window() { + reset_window(TRADE_ANIMATION_SEND_WINDOW_X, TRADE_ANIMATION_SEND_WINDOW_Y, TRADE_ANIMATION_SEND_WINDOW_X_SIZE, TRADE_ANIMATION_SEND_WINDOW_Y_SIZE, TRADE_ANIMATION_SEND_WINDOW_SCREEN); +} + +void init_trade_animation_recv_window() { + create_window(TRADE_ANIMATION_RECV_WINDOW_X, TRADE_ANIMATION_RECV_WINDOW_Y, TRADE_ANIMATION_RECV_WINDOW_X_SIZE, TRADE_ANIMATION_RECV_WINDOW_Y_SIZE, TRADE_ANIMATION_RECV_WINDOW_SCREEN); +} + +void clear_trade_animation_recv_window() { + reset_window(TRADE_ANIMATION_RECV_WINDOW_X, TRADE_ANIMATION_RECV_WINDOW_Y, TRADE_ANIMATION_RECV_WINDOW_X_SIZE, TRADE_ANIMATION_RECV_WINDOW_Y_SIZE, TRADE_ANIMATION_RECV_WINDOW_SCREEN); +} + void init_saving_window() { create_window(SAVING_WINDOW_X, SAVING_WINDOW_Y, SAVING_WINDOW_X_SIZE, SAVING_WINDOW_Y_SIZE, SAVING_WINDOW_SCREEN); }