From 5d818cc411016c58a4f2209e8a02889ed4327ec2 Mon Sep 17 00:00:00 2001 From: jeffman Date: Sun, 20 Jan 2019 00:55:47 -0500 Subject: [PATCH] Add BF858 goods code --- src/c/goods.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++-- src/c/goods.h | 20 +++++ src/m2-hack.asm | 9 +++ 3 files changed, 232 insertions(+), 6 deletions(-) diff --git a/src/c/goods.c b/src/c/goods.c index 9cda7f8..d32aa58 100644 --- a/src/c/goods.c +++ b/src/c/goods.c @@ -2,26 +2,223 @@ #include "vwf.h" #include "locs.h" #include "pc.h" +#include "input.h" // Process the outer Goods window (i.e. character selection) // Called every frame. Replaces $80BF858 fully. int goods_outer_process(WINDOW* window) { - // Copied from assembly: get the weird signed parity value + // Get the weird signed parity value short unknown = window->unknown6; bool is_even = (unknown & 1) == 0; short signed_parity; if (is_even) - { signed_parity = 0; + else + signed_parity = (unknown < 0) ? -1 : 1; + + // Get pointer to current PC items + short current_pc = *active_window_party_member; + short original_pc = current_pc; + unsigned short *current_items = (*pc_stats)[current_pc].goods; + + // Count number of items in first and second display columns + int item_counts[2]; + for (int i = 0; i < 14; i += 2) + { + if (current_items[i] != 0) + item_counts[0]++; + + if (current_items[i + 1] != 0) + item_counts[1]++; + } + + // Check for pressing left or right + PAD_STATE state = *pad_state; + MOVED moved = DIRECTION_NONE; + + if (!window->flags_unknown2) + { + if (state.right) + { + current_pc++; + moved = DIRECTION_RIGHT; + } + else if (state.left) + { + current_pc--; + moved = DIRECTION_LEFT; + } + } + + // Clear window field if moving + if (moved != DIRECTION_NONE) + { + window->unknown7 = 0; + window->vwf_skip = false; + } + + // We moved; find the nearest active party character + bool found = false; + if (moved == DIRECTION_RIGHT) + { + for (int i = 0; i < 4; i++) + { + if (current_pc > 3) + current_pc = 0; + + if ((*pc_flags)[current_pc]) + { + found = true; + break; + } + + current_pc++; + } + } + else if (moved == DIRECTION_LEFT) + { + for (int i = 0; i < 4; i++) + { + if (current_pc < 0) + current_pc = 3; + + if ((*pc_flags)[current_pc]) + { + found = true; + break; + } + + current_pc--; + } + } + + if (found) + { + current_items = (*pc_stats)[current_pc].goods; + window->unknown7 = 0; + window->cursor_x = window->page; + window->cursor_y = 0; + window->unknown6 = 0; + window->unknown6a = 0; + } + + *active_window_party_member = current_pc; + m2_hpwindow_up(current_pc); + clear_name_header(window); + copy_name_header(window, current_pc); + + // Print item names + if (!window->vwf_skip) + { + goods_print_items(window, current_items); + window->vwf_skip = true; + } + + // Play sound effect if we're moving + PAD_STATE state_shadow = *pad_state_shadow; + if (state_shadow.left || state_shadow.right || state_shadow.up || state_shadow.down) + { + if (state.left || state.right) + { + if (current_pc != original_pc) + { + if (*window_flags & 0x800) + m2_soundeffect(0x131); + else + m2_soundeffect(0x12E); + } + } + + window->flags_unknown2 = true; } else { - signed_parity = (unknown < 0) ? -1 : 1; + window->flags_unknown2 = false; } - int current_pc = *active_window_party_member; - int first_item = pc_stats[current_pc]->goods[0]; - return first_item; + // Check if we're exiting + if (state.b || state.select) + { + m2_soundeffect(0x12E); + window->counter = 0; + return ACTION_STEPOUT; + } + + // Check if we're descending + if (state.a || state.l) + { + m2_soundeffect(0x12D); + window->counter = 0; + + unsigned short first_item = current_items[0]; + if (first_item > 0) + { + // If the first item isn't null, erase the arrow border tiles + clear_window_arrows(window); + } + + return signed_parity + 1; + } + + window->counter++; + + if (*pc_count > 1) + { + // We're doing a bit of simplification here. + // The Japanese version tries to highlight the arrow you pressed. + // It only shows for a couple frames and it looks weird, so we're + // just going to show the arrows and not bother with the direction indicator. + draw_window_arrows(window, window->counter < 8); + } + + if (window->counter > 16) + window->counter = 0; + + return ACTION_NONE; +} + +// Converts a pad state to a window action. +GOODS_ACTION goods_get_action(PAD_STATE *state) +{ + if (state->a || state->l) + return ACTION_STEPIN; + + else if (state->b || state->select) + return ACTION_STEPOUT; + + else + return ACTION_NONE; +} + +// Prints all 14 items to a goods window. +// Erases the slot before printing. Prints blanks for null items. +void goods_print_items(WINDOW *window, unsigned short *items) +{ + int item_x = (window->window_x << 3) + 8; + int item_y = window->window_y << 3; + + for (int i = 0; i < 14; i++) + { + int item = items[i]; + int x = item_x + ((i & 1) * 88); + int y = item_y + ((i >> 1) * 16); + + print_blankstr(x >> 3, y >> 3, 11); + + if (item > 0) + { + int x_offset = 0; + + if (m2_isequipped(i + 1)) + { + x_offset = 8; + map_special_character(0x1DE, x >> 3, y >> 3); + } + + byte *item_str = m2_strlookup(m2_items_offsets, m2_items_strings, item); + print_string(item_str, x + x_offset, y); + } + } } diff --git a/src/c/goods.h b/src/c/goods.h index 0c394eb..9d0131d 100644 --- a/src/c/goods.h +++ b/src/c/goods.h @@ -2,7 +2,27 @@ #define HEADER_GOODS_INCLUDED #include "window.h" +#include "input.h" + +typedef enum DIRECTION_MOVED +{ + DIRECTION_NONE, + DIRECTION_RIGHT, + DIRECTION_LEFT +} MOVED; + +typedef enum GOODS_ACTION +{ + ACTION_NONE = 0, + ACTION_STEPIN = 1, + ACTION_STEPOUT = -1 +} GOODS_ACTION; int goods_outer_process(WINDOW* window); +GOODS_ACTION goods_get_action(PAD_STATE *state); +void goods_print_items(WINDOW *window, unsigned short *items); + +extern bool m2_isequipped(int item_index); +extern void m2_soundeffect(int index); #endif diff --git a/src/m2-hack.asm b/src/m2-hack.asm index e9af7da..406b19f 100644 --- a/src/m2-hack.asm +++ b/src/m2-hack.asm @@ -620,6 +620,15 @@ pop {r4,pc} .org 0x80BF14C :: nop // Don't print upper equip tile .org 0x80BF15C :: nop // Don't print lower equip tile +//--------------------------------------------------------- +// BF858 hacks (Goods outer menu) +//--------------------------------------------------------- + +.org 0x80BF858 +push {lr} +bl goods_outer_process +pop {pc} + //--------------------------------------------------------- // C1C98 hacks (menu selection) //---------------------------------------------------------