diff --git a/build.ps1 b/build.ps1 index 5132d0a..85ff8a9 100644 --- a/build.ps1 +++ b/build.ps1 @@ -15,7 +15,9 @@ $input_c_files = "src/c/vwf.c", "src/c/locs.c", "src/c/goods.c", - "src/c/fileselect.c" + "src/c/fileselect.c", + "src/c/status.c", + "src/c/psi.c" $base_c_address = 0x8100000; $scripttool_cmd = "bin/ScriptTool/ScriptTool.dll" diff --git a/src/c/ext.c b/src/c/ext.c index ae0abfd..1c5046b 100644 --- a/src/c/ext.c +++ b/src/c/ext.c @@ -13,6 +13,8 @@ int __attribute__((naked)) m2_remainder(int dividend, int divisor) {} void __attribute__((naked)) m2_formatnumber(int value, byte* strDest, int length) {} int __attribute__((naked)) m2_sub_a334c(int value) {} int __attribute__((naked)) m2_sub_a3384(int value) {} +void __attribute__((naked)) m2_sub_d3c50() {} +void __attribute__((naked)) m2_sub_d6844() {} int __attribute__((naked)) m2_clearwindowtiles(WINDOW* window) {} int __attribute__((naked)) customcodes_parse_generic(int code, char* parserAddress, WINDOW* window, int* dest) {} void __attribute__((naked)) m2_printstr(WINDOW* window, byte* str, unsigned short x, unsigned short y, bool highlight) {} diff --git a/src/c/fileselect.c b/src/c/fileselect.c index a6d7f3b..b95dd77 100644 --- a/src/c/fileselect.c +++ b/src/c/fileselect.c @@ -189,7 +189,7 @@ void print_file_string(int x, int y, int length, byte *str, int window_selector, fileselect_pixels_location, &get_tile_number_file_select, tilesetDestPtr, - width); + width, 0x10); pixelX += pixels; } diff --git a/src/c/goods.h b/src/c/goods.h index cf55c64..7c188eb 100644 --- a/src/c/goods.h +++ b/src/c/goods.h @@ -12,13 +12,6 @@ typedef enum DIRECTION_MOVED DIRECTION_LEFT } MOVED; -typedef enum GOODS_ACTION -{ - ACTION_NONE = 0, - ACTION_STEPIN = 1, - ACTION_STEPOUT = -1 -} GOODS_ACTION; - int goods_outer_process(WINDOW* window, int y_offset, bool give); int goods_inner_process(WINDOW *window, unsigned short *items); void goods_print_items(WINDOW *window, unsigned short *items, int y_offset); diff --git a/src/c/locs.c b/src/c/locs.c index 7ce4e65..146d60c 100644 --- a/src/c/locs.c +++ b/src/c/locs.c @@ -1,22 +1,27 @@ #include "locs.h" -int *fileselect_pixels_location = (int*) 0x2015000; -int *window_flags = (int*) 0x300130C; -PC (*pc_stats)[4] = (PC(*)[4]) 0x3001D54; -byte *pc_count = (byte*) 0x3001F0B; -bool (*pc_flags)[4] = (bool(*)[4]) 0x3001F0C; -byte *pc_names = (byte*) 0x3001F10; -PAD_STATE *pad_state = (PAD_STATE*) 0x3002500; -PAD_STATE *pad_state_shadow = (PAD_STATE*) 0x3002504; -unsigned short *tile_offset = (unsigned short*) 0x30051EC; -int *first_window_flag = (int*) 0x30051F0; -unsigned short *palette_mask = (unsigned short*) 0x3005228; -WINDOW **window_pointers = (WINDOW**) 0x3005230; -short *active_window_party_member = (short*) 0x3005264; -unsigned short **tilemap_pointer = (unsigned short**)0x3005270; -int *vram = (int*) 0x6000000; -int *m2_misc_offsets = (int*) 0x8B17EE4; -byte *m2_misc_strings = (byte*) 0x8B17424; -int *m2_items_offsets = (int*) 0x8B1AF94; -byte *m2_items_strings = (byte*) 0x8B1A694; -unsigned short *name_header_tiles = (unsigned short*) 0x8B1B8B0; +int *fileselect_pixels_location = (int*) 0x2015000; +int *window_flags = (int*) 0x300130C; +byte *character_general_data = (byte*) 0x3001D40; +PC (*pc_stats)[4] = (PC(*)[4]) 0x3001D54; +int *cash_on_hand = (int*) 0x30023D0; +byte *pc_count = (byte*) 0x3001F0B; +bool (*pc_flags)[4] = (bool(*)[4]) 0x3001F0C; +byte *pc_names = (byte*) 0x3001F10; +PAD_STATE *pad_state = (PAD_STATE*) 0x3002500; +PAD_STATE *pad_state_shadow = (PAD_STATE*) 0x3002504; +byte *script_readability = (byte*) 0x3004F08; +unsigned short *tile_offset = (unsigned short*) 0x30051EC; +int *first_window_flag = (int*) 0x30051F0; +byte **free_strings_pointers = (byte**) 0x3005200; +unsigned short *palette_mask = (unsigned short*) 0x3005228; +WINDOW **window_pointers = (WINDOW**) 0x3005230; +short *active_window_party_member = (short*) 0x3005264; +unsigned short **tilemap_pointer = (unsigned short**) 0x3005270; +int *vram = (int*) 0x6000000; +int *m2_misc_offsets = (int*) 0x8B17EE4; +byte *m2_misc_strings = (byte*) 0x8B17424; +int *m2_items_offsets = (int*) 0x8B1AF94; +byte *m2_items_strings = (byte*) 0x8B1A694; +unsigned short *name_header_tiles = (unsigned short*) 0x8B1B8B0; +PSIPrintInfo *psi_print_info = (PSIPrintInfo*) 0x8B2A9C0; diff --git a/src/c/locs.h b/src/c/locs.h index 7b6ccad..e3d7783 100644 --- a/src/c/locs.h +++ b/src/c/locs.h @@ -5,16 +5,20 @@ #include "pc.h" #include "input.h" #include "window.h" +#include "psi.h" extern int *window_flags; extern PC (*pc_stats)[4]; +extern int *cash_on_hand; extern byte *pc_count; extern bool (*pc_flags)[4]; extern byte *pc_names; extern PAD_STATE *pad_state; extern PAD_STATE *pad_state_shadow; +extern byte *script_readability; extern unsigned short *tile_offset; extern int *first_window_flag; +extern byte **free_strings_pointers; extern unsigned short *palette_mask; extern WINDOW **window_pointers; extern short *active_window_party_member; @@ -26,5 +30,7 @@ extern byte *m2_misc_strings; extern int *m2_items_offsets; extern byte *m2_items_strings; extern unsigned short *name_header_tiles; +extern byte *character_general_data; +extern PSIPrintInfo *psi_print_info; #endif diff --git a/src/c/pc.h b/src/c/pc.h index 0b6e537..6348b34 100644 --- a/src/c/pc.h +++ b/src/c/pc.h @@ -12,17 +12,37 @@ typedef enum AILMENT NAUSEOUS = 4, POISONED = 5, SUNSTROKE = 6, - SNIFFLING = 7, - MASHROOMIZED = 8, - POSSESSED = 9, - HOMESICK = 0xA, + SNIFFLING = 7 } AILMENT; +typedef enum AILMENT2 +{ + MASHROOMIZED = 1, + POSSESSED = 2 +} AILMENT2; + +typedef enum AILMENT3 +{ + SLEEP = 1, + CRYING = 2 +} AILMENT3; + +typedef enum CHARACTER +{ + NESS = 0, + PAULA = 1, + JEFF = 2, + POO = 3 +} CHARACTER; + typedef struct PC { unsigned short goods[14]; int experience; + //0x20 byte unknown[12]; - int level; + short level; + short unknown2a; + //0x30 unsigned short hp_max; unsigned short hp_current; byte hp_unknown[2]; // possibly a rolling flag + a fractional value @@ -31,13 +51,14 @@ typedef struct PC { unsigned short pp_current; byte pp_unknown[2]; unsigned short pp_rolling; + //0x40 AILMENT ailment; - bool mashroomized; - bool sleep; + AILMENT2 ailment2; + AILMENT3 ailment3; bool strange; bool cant_concentrate; bool homesick; - byte unknown2[2]; + bool unknown2[2]; byte offense_base; byte defense_base; byte speed_base; @@ -46,6 +67,7 @@ typedef struct PC { byte vitality_base; byte iq_base; byte offense_effective; + //0x50 byte defense_effective; byte speed_effective; byte guts_effective; @@ -53,6 +75,7 @@ typedef struct PC { byte vitality_effective; byte iq_effective; byte unknown3[11]; + //0x61 byte equipment[4]; byte unknown4[7]; } PC; diff --git a/src/c/psi.c b/src/c/psi.c new file mode 100644 index 0000000..77536bf --- /dev/null +++ b/src/c/psi.c @@ -0,0 +1,145 @@ +#include "window.h" +#include "psi.h" +#include "number-selector.h" +#include "locs.h" + +void psiWindow_buffer(CHARACTER psiCharacter, PSIWindow typeOfWindow, PSIClasses printableClasses) +{ + PC *char_data = &(m2_ness_data[psiCharacter]); + PSIPrintInfo *printInfo; + int level = 0; + int thing2 = 0; + byte *str = 0; + byte *boolCmpWindowType = (byte*)(&(typeOfWindow)); + byte *boolCmpPrintableClasses = (byte*)(&(printableClasses)); + byte *address = (byte*)0x3000A00; + WINDOW *window = getWindow(7); + SpecialPSIFlag *SpecialPSIFlags = (SpecialPSIFlag*)(character_general_data + 0x22A); + bool print[0x11]; + for(int i = 0; i < 0x11; i ++) + print[i] = true; + + for(int i = 0; i < 4; i++) + { + (*(address + i)) = 0; + (*(address + i + 4)) = 0; + (*(address + i + 8)) = 0; + } + + if(psiCharacter == POO && typeOfWindow.Classes_Window && printableClasses.Offense) + { + if(SpecialPSIFlags->Poo_Starstorm_Alpha) + { + printInfo = &(psi_print_info[20]); + psiPrint_buffer(20 + 1, window, print[6 - 1], printInfo); + print[6 - 1] = false; + } + if(SpecialPSIFlags->Poo_Starstorm_Omega) + { + printInfo = &(psi_print_info[21]); + psiPrint_buffer(21 + 1, window, print[6 - 1], printInfo); + print[6 - 1] = false; + } + } + + + printInfo = &(psi_print_info[0]); + for(int i = 0; printInfo->PSIID != 0; i++) + { + if(psiCharacter != JEFF) + { + int val = psiCharacter == POO ? 2 : psiCharacter; + level = printInfo->levelLearnt[val]; + } + + if(level != 0) + { + byte *boolCmpWindowTypePrintInfo = (byte*)(&(printInfo->windowType)); + if((*boolCmpWindowType) & (*boolCmpWindowTypePrintInfo)) + { + if(char_data->level >= level) + { + byte *boolCmpPrintableClassesPrintInfo = (byte*)(&(printInfo->possibleClasses)); + if((*boolCmpPrintableClasses) & (*boolCmpPrintableClassesPrintInfo)) + { + psiPrint_buffer(i + 1, window, print[printInfo->PSIID - 1], printInfo); + print[printInfo->PSIID - 1] = false; + } + } + } + } + printInfo = &(psi_print_info[i + 1]); + } + + if(psiCharacter == NESS && typeOfWindow.Character_Window && printableClasses.Other) + { + if(SpecialPSIFlags->Ness_Teleport_Alpha) + { + printInfo = &(psi_print_info[0x32]); + psiPrint_buffer(0x32 + 1, window, print[0x11 - 1], printInfo); + print[0x11 - 1] = false; + } + if(SpecialPSIFlags->Ness_Teleport_Beta) + { + printInfo = &(psi_print_info[0x33]); + psiPrint_buffer(0x33 + 1, window, print[0x11 - 1], printInfo); + print[0x11 - 1] = false; + } + } +} + +void psiTargetWindow_buffer(byte target) +{ + WINDOW *window = getWindow(0x9); //Target Window + PSIPrintInfo *printInfo = &(psi_print_info[target - 1]); + byte *string_group1 = (byte*)(0x8B204E4); + byte extract = (printInfo->PSIID); + byte value = 0; + byte value2 = 0; + byte *str = 0; + if(extract != 4) + { + value = (*(string_group1 + (printInfo->PSIPrintInfoID * 12))); + value = (value * 0x64); + value2 = (*(string_group1 + (printInfo->PSIPrintInfoID * 12) + 1)); + value2 = (value2 * 0x14); + str = (byte*)(0x8B74390 + value + value2); //It doesn't use the pointer to the description the struct has but it obtains it like this... + } + else + str = (byte*)(0x8B74390); + printstr_hlight_buffer(window, str, 0, 0, 0); + + str = m2_strlookup((int*)0x8B17EE4, (byte*)0x8B17424, 0x1B); + printstr_buffer(window, str, 0, 1, 0); + + value = (*(string_group1 + (printInfo->PSIPrintInfoID * 12) + 3)); + str = (window->number_text_area + 0x12); + m2_formatnumber(value, str, 2); + (*(window->number_text_area + 0x14)) = 0; + (*(window->number_text_area + 0x15)) = 0xFF; + printstr_buffer(window, str, 7, 1, 0); +} + +void psiPrint_buffer(byte value, WINDOW* window, bool printPSILine, PSIPrintInfo *printInfo) +{ + byte *str = 0; + byte *address = (byte*)0x3000A00; + + if(printPSILine) + { + byte PSIID = printInfo->PSIID; + str = (byte*)(0x8B74228 + (PSIID * 0x14)); + printstr_hlight_buffer(window, str, 0, printInfo->YPrinting << 1, 0); + if(PSIID == 1) + { + str = (byte*)(m2_ness_name + (7 * 4) + (8 * 2)); //Go to Rockin's name + print_string_in_buffer(str, 0x71, ((printInfo->YPrinting << 1) + window->window_y) << 3, (int*)(0x2014000 - 0x2000)); + } + } + + byte symbol = printInfo->symbol; + str = (byte*)(0x8B1B904 + (symbol * 3)); + printstr_hlight_buffer(window, str, printInfo->XSymbol + 1, printInfo->YPrinting << 1, 0); + int val = ((((printInfo->XSymbol - 9) >> 0x1F) + printInfo->XSymbol - 9) >> 1) + (printInfo->YPrinting << 2); + (*(address + val)) = value; +} \ No newline at end of file diff --git a/src/c/psi.h b/src/c/psi.h new file mode 100644 index 0000000..577d7dc --- /dev/null +++ b/src/c/psi.h @@ -0,0 +1,46 @@ +#ifndef HEADER_PSI_INCLUDED +#define HEADER_PSI_INCLUDED + +#include "vwf.h" + +typedef struct PSIClasses { + bool Offense : 1; + bool Recover : 1; + bool Assist : 1; + bool Other : 1; +} PSIClasses; + +typedef struct PSIWindow +{ + bool Character_Window : 1; + bool Classes_Window : 1; +} PSIWindow; + +typedef struct PSIPrintInfo { + byte PSIID; + byte symbol; + PSIClasses possibleClasses; + PSIWindow windowType; + unsigned short PSIPrintInfoID; + byte levelLearnt[3]; + byte XSymbol; + unsigned short YPrinting; + byte *description; +} PSIPrintInfo; + +typedef struct SpecialPSIFlag { + bool Ness_Teleport_Alpha : 1; + bool Poo_Starstorm_Alpha : 1; + bool Poo_Starstorm_Omega : 1; + bool Ness_Teleport_Beta : 1; +} SpecialPSIFlag; + + +void psiWindow_buffer(CHARACTER psiCharacter, PSIWindow typeOfWindow, PSIClasses printableClasses); +void psiTargetWindow_buffer(byte target); +void psiPrint_buffer(byte value, WINDOW* window, bool printPSILine, PSIPrintInfo *printInfo); + + +extern PSIPrintInfo m2_psi_print_table[]; + +#endif diff --git a/src/c/status.c b/src/c/status.c new file mode 100644 index 0000000..575ca1c --- /dev/null +++ b/src/c/status.c @@ -0,0 +1,277 @@ +#include "window.h" +#include "status.h" +#include "number-selector.h" +#include "locs.h" + +void printNumberOfStatus(int maxLength, int value, int blankX, int y, int strX, int width) +{ + byte str[0x10]; + int end = setNumber_getLength(value, str, maxLength); + str[end] = 0; + str[end + 1] = 0xFF; + print_blankstr_buffer(blankX, y, width, (int*)(0x2014000 - 0x2000)); + int x = (strX - (end * 6)); + print_string_in_buffer(str, x, y << 3, (int*)(0x2014000 - 0x2000)); +} + +void printStatusSymbolArrangement(unsigned short symbolTile, WINDOW* window) +{ + unsigned short *arrangementBase = ((*tilemap_pointer) + (((window->window_y) + 2) << 5) + window->window_x); + unsigned short ailmentTile = ((*tile_offset) + symbolTile) | (*palette_mask); + (*(arrangementBase + 10)) = ailmentTile; + if(symbolTile == 0x1FF) + ailmentTile -= 0x20; + (*(arrangementBase + 42)) = (ailmentTile + 0x20); +} + +void printStatusString(WINDOW* window, int value) +{ + byte *str = m2_strlookup((int*)0x8B17EE4, (byte*)0x8B17424, value); + printstr_hlight_buffer(window, str, 1, 2, 0); +} + +int statusNumbersPrint(WINDOW* window, bool doNotPrint) +{ + if ((!(window->flags_unknown3a & 0x10)) && !doNotPrint) + { + window->flags_unknown3a |= 0x10; + + // Draw window header + map_tile(0xB3, window->window_x, window->window_y - 1); + clear_name_header(window); + copy_name_header(window, *active_window_party_member); + } + + if(!doNotPrint) + { + m2_hpwindow_up(*active_window_party_member); + PC *character_data = &(m2_ness_data[*active_window_party_member]); + printNumberOfStatus(2, character_data->level, 0x5, 1, 0x38, 3); + printNumberOfStatus(3, character_data->hp_max, 0x10, 7, 0x93, 3); + printNumberOfStatus(3, character_data->hp_rolling, 0xC, 7, 0x78, 3); + printNumberOfStatus(3, character_data->pp_max, 0x10, 9, 0x93, 3); + printNumberOfStatus(3, character_data->pp_rolling, 0xC, 9, 0x78, 3); + printNumberOfStatus(7, character_data->experience, 0xC, 0xB, 0x93, 7); + if(character_data->level < 99) + { + unsigned int *experienceLevelTable = (unsigned int*)0x8B1EC20; + unsigned int experienceLevelUp = *(experienceLevelTable + ((*active_window_party_member) * 100) + character_data->level + 1); + printNumberOfStatus(7, experienceLevelUp - character_data->experience, 2, 0xD, 0x3D, 6); + } + else + print_blankstr_buffer(2, 0xD, 6, (int*)(0x2014000 - 0x2000)); + printNumberOfStatus(3, character_data->offense_effective, 0x19, 0x1, 0xE1, 4); + printNumberOfStatus(3, character_data->defense_effective, 0x19, 0x3, 0xE1, 4); + printNumberOfStatus(3, character_data->speed_effective, 0x19, 0x5, 0xE1, 4); + printNumberOfStatus(3, character_data->guts_effective, 0x19, 0x7, 0xE1, 4); + printNumberOfStatus(3, character_data->vitality_effective, 0x19, 0x9, 0xE1, 4); + printNumberOfStatus(3, character_data->iq_effective, 0x19, 0xB, 0xE1, 4); + printNumberOfStatus(3, character_data->luck_effective, 0x19, 0xD, 0xE1, 4); + print_blankstr_buffer(5, 0xF, 0x14, (int*)(0x2014000 - 0x2000)); + if((*active_window_party_member) != JEFF) + { + byte *str = m2_strlookup((int*)0x8B17EE4, (byte*)0x8B17424, 0x13); + print_string_in_buffer(str, 0x2C, (0xF) << 3, (int*)(0x2014000 - 0x2000)); + } + print_blankstr_buffer(1, 0x3, 0xA, (int*)(0x2014000 - 0x2000)); + unsigned short symbolTile = ailmentTileSetup(character_data, 0); + if(symbolTile == 0) + { + printStatusSymbolArrangement(0x1FF, window); + } + if(character_data->ailment != CONSCIOUS) + printStatusString(window, 0x7F + character_data->ailment); + else if(character_data->ailment2 != CONSCIOUS) + printStatusString(window, 0x86 + character_data->ailment2); + else if(character_data->homesick) + printStatusString(window, 0x89); + if(character_data->ailment != CONSCIOUS || character_data->ailment2 != CONSCIOUS || character_data->ailment3 != CONSCIOUS || character_data->strange || character_data->cant_concentrate || character_data->unknown2[0]) + { + if(symbolTile == 0) + return 0; + printStatusSymbolArrangement(symbolTile, window); + return 0; + } + } + return -1; + +} + +int statusReadInput(WINDOW* window) +{ + unsigned short previousCharacter = *active_window_party_member; + int currentCharacter = previousCharacter; + PAD_STATE state = *pad_state; + PAD_STATE state_shadow = *pad_state_shadow; + + if(state.right && !window->hold) + currentCharacter += 1; + + if(state.left && !window->hold) + currentCharacter -= 1; + + if((state.left || state.right) && !window->hold) + { + window->unknown7 = 0; + if(state.left) + { + if(currentCharacter < 0) + currentCharacter = 3; + int foundChar = currentCharacter; + for(int i = 0; i < 4; i++) + { + if (foundChar < 0) + foundChar = 3; + if ((*pc_flags)[foundChar]) + break; + + foundChar--; + } + currentCharacter = foundChar; + } + else + { + if(currentCharacter > 3) + currentCharacter = 0; + int foundChar = currentCharacter; + for(int i = 0; i < 4; i++) + { + if (foundChar > 3) + foundChar = 0; + if ((*pc_flags)[foundChar]) + break; + + foundChar++; + } + currentCharacter = foundChar; + } + m2_hpwindow_up(currentCharacter); + clear_name_header(window); + copy_name_header(window, currentCharacter); + (*active_window_party_member) = currentCharacter; + if(currentCharacter != previousCharacter) + statusNumbersPrint(window, false); + } + + if(state_shadow.right || state_shadow.left) + { + if(state.right || state.left) + { + int flag = *window_flags; + if(flag & 0x800) + { + if(currentCharacter != previousCharacter) + m2_soundeffect(0x131); + } + else if(currentCharacter != previousCharacter) + m2_soundeffect(0x12E); + } + window->hold = true; + } + else + window->hold = false; + + if(state.b || state.select) + { + m2_soundeffect(0x12E); + window->counter = 0; + return ACTION_STEPOUT; + } + else if(state.a || state.l) + { + m2_soundeffect(0x12D); + if(currentCharacter != JEFF) + { + if((*pc_count) > 1) + { + unsigned short *arrangementBase = (*tilemap_pointer) + (((window->window_y - 1) << 5) + window->window_x + window->window_width - 4); + unsigned short topTile = ((*tile_offset) + 0x96) | (*palette_mask) | 0x800; + (*arrangementBase) = topTile; + (*(arrangementBase + 1)) = topTile; + (*(arrangementBase + 2)) = topTile; + (*(arrangementBase + 3)) = topTile; + } + window->counter = 0; + return 1; + } + else + return 0; + } + + 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; +} + +int statusWindowNumbers(WINDOW* window, bool doNotPrint) +{ + if(statusNumbersPrint(window, doNotPrint) == 0) + return 0; + return statusReadInput(window); +} + +int statusWindowText(WINDOW* window) +{ + if(window->redraw) + buffer_drawwindow(window, (int*)(0x2014000 - 0x2000)); + if(window->loaded_code != 0 && ((*script_readability) == 0)) + { + window->delay = 0; + while(true) + { + while(window->text_y >= window->window_height || window->window_y + window->text_y > 0x1F) + properScroll(window, (int*)(0x2014000 - 0x2000)); + byte *str = window->text_start + window->text_offset; + if((*(str + 1)) == 0xFF) + { + int returnedLength = customcodes_parse_generic(*str, str, window, (int*)(0x2014000 - 0x2000)); + if(returnedLength != 0) + { + if(returnedLength < 0) + returnedLength = 0; + window->text_offset += returnedLength; + } + else + { + if((*str) == 1) + { + window->text_y += 2; + window->text_x = 0; + window->text_offset += 2; + } + else if((*str) == 0) + { + window->loaded_code = 0; + break; + } + else + window->text_offset++; + } + } + else + { + if(window->text_x >= window->window_width || window->window_x + window->text_x > 0x1F) + { + window->text_y += 2; + window->text_x = 0; + } + weld_entry_custom_buffer(window, str, 0, 0xF, (int*)(0x2014000 - 0x2000)); + window->text_offset++; + } + } + } + + return 0; +} \ No newline at end of file diff --git a/src/c/status.h b/src/c/status.h new file mode 100644 index 0000000..8311a45 --- /dev/null +++ b/src/c/status.h @@ -0,0 +1,14 @@ +#ifndef HEADER_STATUS_INCLUDED +#define HEADER_STATUS_INCLUDED + +#include "vwf.h" + +void printNumberOfStatus(int maxLength, int value, int blankX, int y, int strX, int width); +void printStatusSymbolArrangement(unsigned short symbolTile, WINDOW* window); +void printStatusString(WINDOW* window, int value); +int statusNumbersPrint(WINDOW* window, bool doNotPrint); +int statusReadInput(WINDOW* window); +int statusWindowNumbers(WINDOW* window, bool doNotPrint); +int statusWindowText(WINDOW* window); + +#endif \ No newline at end of file diff --git a/src/c/vwf.c b/src/c/vwf.c index 7445507..280165d 100644 --- a/src/c/vwf.c +++ b/src/c/vwf.c @@ -156,12 +156,12 @@ byte print_character_formatted(byte chr, int x, int y, int font, int foreground) return 8; } - return print_character_with_callback(chr, x, y, font, foreground, vram, &get_tile_number_with_offset, *tilemap_pointer, 32); + return print_character_with_callback(chr, x, y, font, foreground, vram, &get_tile_number_with_offset, *tilemap_pointer, 32, 0xC); } byte print_character_to_ram(byte chr, int *dest, int xOffset, int font, int foreground) { - return print_character_with_callback(chr, xOffset, 0, font, foreground, dest, &get_tile_number_grid, NULL, 32); + return print_character_with_callback(chr, xOffset, 0, font, foreground, dest, &get_tile_number_grid, NULL, 32, 0x10); } // Prints a special tile. Pixels are copied to the VWF buffer. @@ -199,7 +199,7 @@ void map_tile(unsigned short tile, int x, int y) } byte print_character_with_callback(byte chr, int x, int y, int font, int foreground, - int *dest, int (*getTileCallback)(int, int), unsigned short *tilemapPtr, int tilemapWidth) + int *dest, int (*getTileCallback)(int, int), unsigned short *tilemapPtr, int tilemapWidth, byte doubleTileHeight) { int tileWidth = m2_font_widths[font]; int tileHeight = m2_font_heights[font]; @@ -215,11 +215,20 @@ byte print_character_with_callback(byte chr, int x, int y, int font, int foregro int tileY = y >> 3; int offsetY = y & 7; + + if((tileY & 1) == 0 && offsetY >= doubleTileHeight - 0x8) + { + tileY++; + offsetY -= (doubleTileHeight - 0x8); + } + int nextY = offsetY; for (int dTileY = 0; dTileY < tileHeight; dTileY++) // dest tile Y { int dTileX = 0; int renderedWidth = widths >> 8; + offsetY = nextY; + bool changed = false; while (renderedWidth > 0) { @@ -228,10 +237,13 @@ byte print_character_with_callback(byte chr, int x, int y, int font, int foregro bool availableSwap = (dTileY != (tileHeight - 1)); int realTileIndex = tileIndex; bool useful = false; //Maybe we go over the maximum tile height, let's make sure the extra tile is properly set IF it's useful + int tmpTileY = dTileY; + int limit = ((tmpTileY + tileY) & 1) == 0 ? doubleTileHeight - 8 - 1: 7; + int sumRemoved = 0; for (int row = 0; row < 8; row++) { - int canvasRow = dest[(realTileIndex * 8) + ((row + offsetY) & 7)]; + int canvasRow = dest[(realTileIndex * 8) + ((row + offsetY - sumRemoved) & 7)]; byte glyphRow = glyphRows[row + (dTileY * 8 * tileWidth) + (dTileX * 8)] & ((1 << leftPortionWidth) - 1); glyphRow <<= (8 - leftPortionWidth); @@ -244,9 +256,21 @@ byte print_character_with_callback(byte chr, int x, int y, int font, int foregro if(!availableSwap && ((row + offsetY) >> 3) == 1 && canvasRow != tmpCanvasRow) //This changed the canvas, then it's useful... IF it's the extra vertical tile useful = true; - dest[(realTileIndex * 8) + ((row + offsetY) & 7)] = canvasRow; - if(offsetY != 0 && ((row + offsetY) == 7)) - realTileIndex = getTileCallback(tileX + dTileX, tileY + dTileY + 1); + dest[(realTileIndex * 8) + ((row + offsetY - sumRemoved) & 7)] = canvasRow; + + if((row + offsetY - sumRemoved) == limit) + { + realTileIndex = getTileCallback(tileX + dTileX, tileY + tmpTileY + 1); + tmpTileY++; + sumRemoved += limit + 1; + if(!changed) + { + nextY = (nextY + limit + 1) & 7; + changed = true; + } + limit = ((tmpTileY + tileY) & 1) == 0 ? doubleTileHeight - 8 - 1: 7; + + } } if (tilemapPtr != NULL) @@ -264,10 +288,13 @@ byte print_character_with_callback(byte chr, int x, int y, int font, int foregro availableSwap = (dTileY != (tileHeight - 1)); realTileIndex = tileIndex; useful = false; //Maybe we go over the maximum tile height, let's make sure the extra tile is properly set IF it's useful + tmpTileY = dTileY; + limit = ((tmpTileY + tileY) & 1) == 0 ? doubleTileHeight - 8 - 1: 7; + sumRemoved = 0; for (int row = 0; row < 8; row++) { - int canvasRow = dest[(realTileIndex * 8) + ((row + offsetY) & 7)]; + int canvasRow = dest[(realTileIndex * 8) + ((row + offsetY - sumRemoved) & 7)]; byte glyphRow = glyphRows[row + (dTileY * 8 * tileWidth) + (dTileX * 8)] >> leftPortionWidth; int expandedGlyphRow = expand_bit_depth(glyphRow, foreground); @@ -279,9 +306,20 @@ byte print_character_with_callback(byte chr, int x, int y, int font, int foregro if(!availableSwap && ((row + offsetY) >> 3) == 1 && canvasRow != tmpCanvasRow) //This changed the canvas, then it's useful... IF it's the extra vertical tile useful = true; - dest[(realTileIndex * 8) + ((row + offsetY) & 7)] = canvasRow; - if(offsetY != 0 && ((row + offsetY) == 7)) - realTileIndex = getTileCallback(tileX + dTileX + 1, tileY + dTileY + 1); + dest[(realTileIndex * 8) + ((row + offsetY - sumRemoved) & 7)] = canvasRow; + + if((row + offsetY - sumRemoved) == limit) + { + realTileIndex = getTileCallback(tileX + 1 + dTileX, tileY + tmpTileY + 1); + tmpTileY++; + sumRemoved += limit + 1; + if(!changed) + { + nextY = (nextY + limit + 1) & 7; + changed = true; + } + limit = ((tmpTileY + tileY) & 1) == 0 ? doubleTileHeight - 8 - 1: 7; + } } if (tilemapPtr != NULL) @@ -291,7 +329,7 @@ byte print_character_with_callback(byte chr, int x, int y, int font, int foregro tilemapPtr[tileX + dTileX + 1 + ((tileY + dTileY + 1) * tilemapWidth)] = paletteMask | realTileIndex; } } - + renderedWidth -= 8; dTileX++; } @@ -768,362 +806,29 @@ void format_cash_window(int value, int padding, byte* str) int player_name_printing_registration(byte* str, WINDOW* window) { - char String[26]; - bool ended = false; - int total = 24; - for(int i = 0; i < 24; i++) - { - if(ended) - { - String[i] = 0x53; - } - else if((i < 23 && str[i + 1] == 0xFF && str[i] == 0) || (i == 23 && str[i] == 0)) - { - String[i] = 0x70; - total = i; - ended = true; - } - else - String[i] = str[i]; - } - String[24] = 0; - String[25] = 0xFF; - print_blankstr_window(0, 2, 24, window); - m2_printstr(window, String, 0, 1, 0); - return total; -} - -int get_pointer_jump_back(byte *character) -{ - byte *address1 = ((byte*)0x3004F24); - byte *address2 = ((byte*)0x3005078); - byte val = (*address1); - byte val2 = (*address2); - if(val != 0 || val2 == 0) - return 0; - val2--; - (*address2) = val2; - int *address3 = ((int*)0x3005080); - byte *str = (byte*)(*(address3 + val2)); - return (str - character - 2); -} - -void print_letter_in_buffer(WINDOW* window, byte* character, int* dest) -{ - m2_cstm_last_printed[0] = (*character); - weld_entry_custom_buffer(window, character, 0, 0xF, dest); - if(window->delay_between_prints == 0) - return; - byte* address = (byte*)0x3005218; - byte counter = (*address); - if(counter == 1) - m2_soundeffect(0x133); -} - -int print_window_with_buffer(WINDOW* window) -{ - int delay = 0; - if((window->loaded_code != 0) && (m2_script_readability == 0)) - { - if(window->delay_between_prints == 0) - delay = 0; - else if(!window->enable && window->flags_unknown1 == 1) - { - - } - else if(window->enable && window->flags_unknown1 == 1) - { - - } - else - return 0; - while(window->loaded_code !=0) - { - window->delay = delay; - print_character_with_codes(window, (int*)(0x2014000 - ((*tile_offset) * 32))); - } - } - return 0; -} - -void scrolltext_buffer(WINDOW* window, int* dest) -{ - unsigned short empty_tile = ((*tile_offset) + 0x1FF) | (*palette_mask); - unsigned short *arrangementBase = (*tilemap_pointer); - int start = (window->window_y * 32) + window->window_x; - if(window->window_height <= 2) - { - if(window->window_area > 0) - { - for(int y = 0; y < window->window_height && y + window->window_y <= 0x1F; y++) - for(int x = 0; x < window->window_width && x + window->window_x <= 0x1F; x++) - { - arrangementBase[start + x + (y * 32)] = empty_tile; - clear_tile_buffer(x + window->window_x, y + window->window_y, 0x44444444, dest); - } - } - } - - if(window->window_area > 0) - { - for(int y = 2; y < window->window_height && y + window->window_y <= 0x1F; y++) - for(int x = 0; x < window->window_width && x + window->window_x <= 0x1F; x++) - { - if(arrangementBase[start + ((y - 2) * 32) + x] == empty_tile) - { - if(arrangementBase[start + (y * 32) + x] != empty_tile) //Non Blank to Blank - { - copy_tile_up_buffer(x, y, dest); - arrangementBase[start + ((y - 2) * 32) + x] = arrangementBase[start + (y * 32) + x]; - } - } - else - { - if(arrangementBase[start + (y * 32) + x] == empty_tile) //Blank to Non Blank - { - arrangementBase[start + ((y - 2) * 32) + x] = empty_tile; - } - copy_tile_up_buffer(x, y, dest); //Non Blank to Non Blank - } - - } - } - - for(int y = window->window_height - 2; y >= 0 && y < window->window_height; y++) - for(int x = 0; x < window->window_width && x + window->window_x <= 0x1F; x++) - { - arrangementBase[start + x + (y * 32)] = empty_tile; - clear_tile_buffer(x + window->window_x, y + window->window_y, 0x44444444, dest); - } -} - -void properScroll(WINDOW* window, int* dest) -{ - scrolltext_buffer(window, dest); - window->text_y = window->text_y - 2; - window->text_x = 0; - window->pixel_x = 0; -} - -void setStuffWindow_Graphics() -{ - int *something = (int*)0x3005220; - unsigned short *address = (unsigned short*)((*something) + 0x4BA); - (*address) = 0; - (*(address + 2)) = 0; - (*(address - 2)) = (*(address - 2)) + 1; - if((*(address - 2)) >= 2) - (*(address + 2)) = 0; -} - -int jumpToOffset(byte* character) -{ - int returnOffset = 0; - int baseOffset = 0; - if((*(character + 1)) != 0xFF) - return 0; - int code = 0xFFFF009F + ((*character) | 0xFF00); - - switch(code) - { - case 0x25: - returnOffset += 2; - baseOffset = returnOffset; - for(int i = 0; i < 4; i++) - returnOffset = returnOffset + ((*(character + baseOffset + i)) << (8 * i)); - byte* totalJumps = (byte*)0x3005078; - byte** oldOffsets = (byte**)0x3005080; - oldOffsets[*totalJumps] = character + 6; - (*totalJumps)++; - break; - default: - return 0; - } - - return returnOffset; -} - -byte print_character_with_codes(WINDOW* window, int* dest) -{ - int delay = window->delay--; - if(delay > 0) - return 0; - bool usingOffset2= false; - int offsetJump = 0; - int returnedLength = 0; - byte *character = window->text_start + window->text_offset; - int y = window->window_y + window->text_y; - int x = window->window_x + window->text_x; - unsigned short *tilesetDest = (unsigned short *)(*tilemap_pointer); - tilesetDest = tilesetDest + (y << 6) + (x << 1); - - - if((*(character + 1)) != 0xFF) - if(window->text_y >= window->window_height || y > 0x1F) - { - properScroll(window, dest); - return 0; - } - - switch(window->loaded_code) - { - case 6: - break; - case 7: - character = m2_ness_name + window->text_offset2; //Ness - usingOffset2 = true; - break; - case 8: - character = (m2_ness_name + 7) + window->text_offset2; //Paula - usingOffset2 = true; - break; - case 9: - character = (m2_ness_name + 14) + window->text_offset2; //Jeff - usingOffset2 = true; - break; - case 10: - character = (m2_ness_name + 21) + window->text_offset2; //Poo - usingOffset2 = true; - break; - case 11: - character = (m2_ness_name + 36) + window->text_offset2; //Food - usingOffset2 = true; - break; - case 12: - character = (m2_ness_name + 44) + window->text_offset2; //Rockin - usingOffset2 = true; - break; - case 20: - character = (m2_ness_name + 28) + window->text_offset2; //King - usingOffset2 = true; - break; - case 13: - break; //User - case 14: - break; //Target - default: - break; - } - - if((*(character + 1)) == 0xFF) - { - byte code = (*character); - switch(code) - { - case 1: - window->text_y += 2; - window->text_x = 0; - window->pixel_x = 0; - if(!usingOffset2) - window->text_offset += 2; - else - window->text_offset2 += 2; - setStuffWindow_Graphics(); - if(window->text_y >= window->window_height || window->text_y + window->window_y > 0x1F) - properScroll(window, dest); - break; - case 2: - window->text_y += 2; - window->text_x = 0; - window->pixel_x = 0; - if(!usingOffset2) - window->text_offset += 2; - else - window->text_offset2 += 2; - window->counter = 0; - window->loaded_code = 2; - setStuffWindow_Graphics(); - return 2; - case 0xD: - case 0xE: - case 0xF: - case 0x10: - window->text_offset += 2; - window->text_offset2 = 0; - window->loaded_code = 7 + code - 0xD; - break; - case 0: - if(window->loaded_code >= 6 && window->loaded_code <= 0x20) - { - window->loaded_code = 1; - return 1; - } - else - { - offsetJump = get_pointer_jump_back(character); - if(offsetJump != 0) - window->text_offset += 2 + offsetJump; - else - { - window->loaded_code = 0; - return 1; - } - } - break; - default: - if(code >= 0x60) - window->text_offset += jumpToOffset(character); - else - { - returnedLength = customcodes_parse_generic(code, character, window, dest); - if(returnedLength == 0) - returnedLength = 2; - else if(returnedLength < 0) - returnedLength = 0; - window->text_offset += returnedLength; - } - break; - } - } - else - { - handle_first_window_buffer(window, (int*)(0x2014000 - ((*tile_offset) * 32))); - window->delay = window->delay_between_prints; - if(x > 0x1F) - { - window->text_y += 2; - window->text_x = 0; - window->pixel_x = 0; - } - print_letter_in_buffer(window, character, dest); - if(!usingOffset2) - window->text_offset += 1; - else - window->text_offset2 += 1; - } - return 0; -} - -byte print_character_formatted_buffer(byte chr, int x, int y, int font, int foreground, int *dest) -{ - // 0x64 to 0x6C (inclusive) is YOU WON - if ((chr >= YOUWON_START) && (chr <= YOUWON_END)) + char String[26]; + bool ended = false; + int total = 24; + for(int i = 0; i < 24; i++) { - print_special_character(chr + 0xF0, x, y); - return 8; + if(ended) + { + String[i] = 0x53; + } + else if((i < 23 && str[i + 1] == 0xFF && str[i] == 0) || (i == 23 && str[i] == 0)) + { + String[i] = 0x70; + total = i; + ended = true; + } + else + String[i] = str[i]; } - - // 0x6D is an arrow -> - else if (chr == ARROW) - { - print_special_character(ARROW + 0x30, x, y); - return 8; - } - - return print_character_with_callback(chr, x, y, font, foreground, dest, &get_tile_number_with_offset, *tilemap_pointer, 32); -} - -void weld_entry_custom_buffer(WINDOW *window, byte *str, int font, int foreground, int* dest) -{ - int chr = decode_character(*str); - - int x = window->pixel_x + (window->window_x + window->text_x) * 8; - int y = (window->window_y + window->text_y) * 8; - - x += print_character_formatted_buffer(chr, x, y, font, foreground, dest); - - window->pixel_x = x & 7; - window->text_x = (x >> 3) - window->window_x; + String[24] = 0; + String[25] = 0xFF; + print_blankstr_window(0, 2, 24, window); + m2_printstr(window, String, 0, 1, 0); + return total; } // The game draws windows lazily: no window will be drawn to the screen until @@ -1149,6 +854,339 @@ void handle_first_window(WINDOW* window) } } +int get_pointer_jump_back(byte *character) +{ + byte *address1 = ((byte*)0x3004F24); + byte *address2 = ((byte*)0x3005078); + byte val = (*address1); + byte val2 = (*address2); + if(val != 0 || val2 == 0) + return 0; + val2--; + (*address2) = val2; + int *address3 = ((int*)0x3005080); + byte *str = (byte*)(*(address3 + val2)); + return (str - character - 2); +} + +void print_letter_in_buffer(WINDOW* window, byte* character, int* dest) +{ + m2_cstm_last_printed[0] = (*character); + weld_entry_custom_buffer(window, character, 0, 0xF, dest); + if(window->delay_between_prints == 0) + return; + byte* address = (byte*)0x3005218; + byte counter = (*address); + if(counter == 1) + m2_soundeffect(0x133); +} + +int print_window_with_buffer(WINDOW* window) +{ + int delay = 0; + if((window->loaded_code != 0) && ((*script_readability) == 0)) + { + if(window->delay_between_prints == 0) + delay = 0; + else if(!window->enable && window->flags_unknown1 == 1) + { + + } + else if(window->enable && window->flags_unknown1 == 1) + { + + } + else + return 0; + while(window->loaded_code !=0) + { + window->delay = delay; + print_character_with_codes(window, (int*)(0x2014000 - ((*tile_offset) * 32))); + } + } + return 0; +} + +void scrolltext_buffer(WINDOW* window, int* dest) +{ + unsigned short empty_tile = ((*tile_offset) + 0x1FF) | (*palette_mask); + unsigned short *arrangementBase = (*tilemap_pointer); + int start = (window->window_y * 32) + window->window_x; + if(window->window_height <= 2) + { + if(window->window_area > 0) + { + for(int y = 0; y < window->window_height && y + window->window_y <= 0x1F; y++) + for(int x = 0; x < window->window_width && x + window->window_x <= 0x1F; x++) + { + arrangementBase[start + x + (y * 32)] = empty_tile; + clear_tile_buffer(x + window->window_x, y + window->window_y, 0x44444444, dest); + } + } + } + + if(window->window_area > 0) + { + for(int y = 2; y < window->window_height && y + window->window_y <= 0x1F; y++) + for(int x = 0; x < window->window_width && x + window->window_x <= 0x1F; x++) + { + if(arrangementBase[start + ((y - 2) * 32) + x] == empty_tile) + { + if(arrangementBase[start + (y * 32) + x] != empty_tile) //Non Blank to Blank + { + copy_tile_up_buffer(x, y, dest); + arrangementBase[start + ((y - 2) * 32) + x] = arrangementBase[start + (y * 32) + x]; + } + } + else + { + if(arrangementBase[start + (y * 32) + x] == empty_tile) //Blank to Non Blank + { + arrangementBase[start + ((y - 2) * 32) + x] = empty_tile; + } + copy_tile_up_buffer(x, y, dest); //Non Blank to Non Blank + } + + } + } + + for(int y = window->window_height - 2; y >= 0 && y < window->window_height; y++) + for(int x = 0; x < window->window_width && x + window->window_x <= 0x1F; x++) + { + arrangementBase[start + x + (y * 32)] = empty_tile; + clear_tile_buffer(x + window->window_x, y + window->window_y, 0x44444444, dest); + } +} + +void properScroll(WINDOW* window, int* dest) +{ + scrolltext_buffer(window, dest); + window->text_y = window->text_y - 2; + window->text_x = 0; + window->pixel_x = 0; +} + +void setStuffWindow_Graphics() +{ + int *something = (int*)0x3005220; + unsigned short *address = (unsigned short*)((*something) + 0x4BA); + (*address) = 0; + (*(address + 2)) = 0; + (*(address - 2)) = (*(address - 2)) + 1; + if((*(address - 2)) >= 2) + (*(address + 2)) = 0; +} + +int jumpToOffset(byte* character) +{ + int returnOffset = 0; + int baseOffset = 0; + if((*(character + 1)) != 0xFF) + return 0; + int code = 0xFFFF009F + ((*character) | 0xFF00); + + switch(code) + { + case 0x25: + returnOffset += 2; + baseOffset = returnOffset; + for(int i = 0; i < 4; i++) + returnOffset = returnOffset + ((*(character + baseOffset + i)) << (8 * i)); + byte* totalJumps = (byte*)0x3005078; + byte** oldOffsets = (byte**)0x3005080; + oldOffsets[*totalJumps] = character + 6; + (*totalJumps)++; + break; + default: + return 0; + } + + return returnOffset; +} + +byte print_character_with_codes(WINDOW* window, int* dest) +{ + int delay = window->delay--; + if(delay > 0) + return 0; + bool usingOffset2= false; + int offsetJump = 0; + int returnedLength = 0; + byte *character = window->text_start + window->text_offset; + int y = window->window_y + window->text_y; + int x = window->window_x + window->text_x; + unsigned short *tilesetDest = (unsigned short *)(*tilemap_pointer); + tilesetDest = tilesetDest + (y << 6) + (x << 1); + + + if((*(character + 1)) != 0xFF) + if(window->text_y >= window->window_height || y > 0x1F) + { + properScroll(window, dest); + return 0; + } + + switch(window->loaded_code) + { + case 6: + break; + case 7: + character = m2_ness_name + window->text_offset2; //Ness + usingOffset2 = true; + break; + case 8: + character = (m2_ness_name + 7) + window->text_offset2; //Paula + usingOffset2 = true; + break; + case 9: + character = (m2_ness_name + 14) + window->text_offset2; //Jeff + usingOffset2 = true; + break; + case 10: + character = (m2_ness_name + 21) + window->text_offset2; //Poo + usingOffset2 = true; + break; + case 11: + character = (m2_ness_name + 36) + window->text_offset2; //Food + usingOffset2 = true; + break; + case 12: + character = (m2_ness_name + 44) + window->text_offset2; //Rockin + usingOffset2 = true; + break; + case 20: + character = (m2_ness_name + 28) + window->text_offset2; //King + usingOffset2 = true; + break; + case 13: + break; //User + case 14: + break; //Target + default: + break; + } + + if((*(character + 1)) == 0xFF) + { + byte code = (*character); + switch(code) + { + case 1: + window->text_y += 2; + window->text_x = 0; + window->pixel_x = 0; + if(!usingOffset2) + window->text_offset += 2; + else + window->text_offset2 += 2; + setStuffWindow_Graphics(); + if(window->text_y >= window->window_height || window->text_y + window->window_y > 0x1F) + properScroll(window, dest); + break; + case 2: + window->text_y += 2; + window->text_x = 0; + window->pixel_x = 0; + if(!usingOffset2) + window->text_offset += 2; + else + window->text_offset2 += 2; + window->counter = 0; + window->loaded_code = 2; + setStuffWindow_Graphics(); + return 2; + case 0xD: + case 0xE: + case 0xF: + case 0x10: + window->text_offset += 2; + window->text_offset2 = 0; + window->loaded_code = 7 + code - 0xD; + break; + case 0: + if(window->loaded_code >= 6 && window->loaded_code <= 0x20) + { + window->loaded_code = 1; + return 1; + } + else + { + offsetJump = get_pointer_jump_back(character); + if(offsetJump != 0) + window->text_offset += 2 + offsetJump; + else + { + window->loaded_code = 0; + return 1; + } + } + break; + default: + if(code >= 0x60) + window->text_offset += jumpToOffset(character); + else + { + returnedLength = customcodes_parse_generic(code, character, window, dest); + if(returnedLength == 0) + returnedLength = 2; + else if(returnedLength < 0) + returnedLength = 0; + window->text_offset += returnedLength; + } + break; + } + } + else + { + handle_first_window_buffer(window, (int*)(0x2014000 - ((*tile_offset) * 32))); + window->delay = window->delay_between_prints; + if(x > 0x1F) + { + window->text_y += 2; + window->text_x = 0; + window->pixel_x = 0; + } + print_letter_in_buffer(window, character, dest); + if(!usingOffset2) + window->text_offset += 1; + else + window->text_offset2 += 1; + } + return 0; +} + +byte print_character_formatted_buffer(byte chr, int x, int y, int font, int foreground, int *dest) +{ + // 0x64 to 0x6C (inclusive) is YOU WON + if ((chr >= YOUWON_START) && (chr <= YOUWON_END)) + { + print_special_character(chr + 0xF0, x, y); + return 8; + } + + // 0x6D is an arrow -> + else if (chr == ARROW) + { + print_special_character(ARROW + 0x30, x, y); + return 8; + } + + return print_character_with_callback(chr, x, y, font, foreground, dest, &get_tile_number_with_offset, *tilemap_pointer, 32, 0xC); +} + +void weld_entry_custom_buffer(WINDOW *window, byte *str, int font, int foreground, int* dest) +{ + int chr = decode_character(*str); + + int x = window->pixel_x + (window->window_x + window->text_x) * 8; + int y = (window->window_y + window->text_y) * 8; + + x += print_character_formatted_buffer(chr, x, y, font, foreground, dest); + + window->pixel_x = x & 7; + window->text_x = (x >> 3) - window->window_x; +} + void handle_first_window_buffer(WINDOW* window, int* dest) { if (*first_window_flag == 1) @@ -1158,7 +1196,7 @@ void handle_first_window_buffer(WINDOW* window, int* dest) } else if (window->redraw) { - window->pixel_x = 0; + window->pixel_x = 0; buffer_drawwindow(window, dest); } } @@ -1204,95 +1242,87 @@ int print_string_in_buffer(byte *str, int x, int y, int *dest) void printstr_buffer(WINDOW* window, byte* str, unsigned short x, unsigned short y, bool highlight) { - int tmpOffset = window->text_offset; - int tmpOffset2 = window->text_offset2; - byte* tmpTextStart = window->text_start; - unsigned short tmpText_x = window->text_x; - unsigned short tmpText_y = window->text_y; - unsigned short tmpDelayPrints = window->delay_between_prints; - unsigned short tmpPaletteMsk = (*palette_mask); - unsigned short palette_mask_highlight = tmpPaletteMsk; - window->text_start = str; - window->text_offset = 0; - window->text_offset2 = 0; - window->text_x = x; - window->text_y = (y << 1); - if(highlight) - palette_mask_highlight += 0x1000; - (*palette_mask) = palette_mask_highlight; - - window->pixel_x = 0; - unsigned short output = 0; - while(output != 1) - { - window->delay = 0; - output = print_character_with_codes(window, (int*)(0x2014000 - ((*tile_offset) * 32))); - } - - window->text_start = tmpTextStart; - window->text_offset = tmpOffset; - window->text_offset2 = tmpOffset2; - window->text_x = tmpText_x; - window->text_y = tmpText_y; - window->delay_between_prints = tmpDelayPrints; - (*palette_mask) = tmpPaletteMsk; + int tmpOffset = window->text_offset; + int tmpOffset2 = window->text_offset2; + byte* tmpTextStart = window->text_start; + unsigned short tmpText_x = window->text_x; + unsigned short tmpText_y = window->text_y; + unsigned short tmpDelayPrints = window->delay_between_prints; + unsigned short tmpPaletteMsk = (*palette_mask); + unsigned short palette_mask_highlight = tmpPaletteMsk; + window->text_start = str; + window->text_offset = 0; + window->text_offset2 = 0; + window->text_x = x; + window->text_y = (y << 1); + if(highlight) + palette_mask_highlight += 0x1000; + (*palette_mask) = palette_mask_highlight; + + window->pixel_x = 0; + unsigned short output = 0; + while(output != 1) + { + window->delay = 0; + output = print_character_with_codes(window, (int*)(0x2014000 - ((*tile_offset) * 32))); + } + + window->text_start = tmpTextStart; + window->text_offset = tmpOffset; + window->text_offset2 = tmpOffset2; + window->text_x = tmpText_x; + window->text_y = tmpText_y; + window->delay_between_prints = tmpDelayPrints; + (*palette_mask) = tmpPaletteMsk; } unsigned short printstr_hlight_buffer(WINDOW* window, byte* str, unsigned short x, unsigned short y, bool highlight) { - unsigned short printX = (x + window->window_x) << 3; - unsigned short printY = (y + window->window_y) << 3; - unsigned short tmpPaletteMsk = (*palette_mask); - unsigned short palette_mask_highlight = tmpPaletteMsk; - if(highlight) - palette_mask_highlight += 0x1000; - (*palette_mask) = palette_mask_highlight; - - unsigned short printed_Characters = print_string_in_buffer(str, printX, printY, (int*)(0x2014000 - ((*tile_offset) * 32))); - - (*palette_mask) = tmpPaletteMsk; - - return printed_Characters; + unsigned short printX = (x + window->window_x) << 3; + unsigned short printY = (y + window->window_y) << 3; + unsigned short tmpPaletteMsk = (*palette_mask); + unsigned short palette_mask_highlight = tmpPaletteMsk; + if(highlight) + palette_mask_highlight += 0x1000; + (*palette_mask) = palette_mask_highlight; + + unsigned short printed_Characters = print_string_in_buffer(str, printX, printY, (int*)(0x2014000 - ((*tile_offset) * 32))); + + (*palette_mask) = tmpPaletteMsk; + + return printed_Characters; } WINDOW* getWindow(int index) { - return window_pointers[index]; + return window_pointers[index]; } -void psiTargetWindow_buffer(byte target) +int initWindow_buffer(WINDOW* window, byte* text_start, unsigned short delay_between_prints) { - WINDOW *window = getWindow(0x9); //Target Window - byte *string_group = (byte*)(0x8B2A9B0); - byte *string_group1 = (byte*)(0x8B204E4); - byte extract = (*(string_group +(target << 4))); - byte value = 0; - byte value2 = 0; - unsigned short val = 0; - byte *str = 0; - if(extract != 4) - { - val = (*(string_group + (target << 4) + 4)) + ((*(string_group + (target << 4) + 5)) << 8); - value = (*(string_group1 + (val * 12))); - value = (value * 0x64); - value2 = (*(string_group1 + (val * 12) + 1)); - value2 = (value2 * 0x14); - str = (byte*)(0x8B74390 + value + value2); - } - else - str = (byte*)(0x8B74390); - printstr_hlight_buffer(window, str, 0, 0, 0); - - str = m2_strlookup((int*)0x8B17EE4, (byte*)0x8B17424, 0x1B); - printstr_buffer(window, str, 0, 1, 0); - - val = (*(string_group + (target << 4) + 4)) + ((*(string_group + (target << 4) + 5)) << 8); - value = (*(string_group1 + (val * 12) + 3)); - str = (window->number_text_area + 0x12); - m2_formatnumber(value, str, 2); - (*(window->number_text_area + 0x14)) = 0; - (*(window->number_text_area + 0x15)) = 0xFF; - printstr_buffer(window, str, 7, 1, 0); + window->vwf_skip = false; + window->unknown3 = 0; + window->text_x = 0; + window->text_y = 0; + window->text_offset = 0; + window->text_start = text_start; + window->text_start2 = text_start; + window->delay_between_prints = delay_between_prints; + window->delay = 0; + window->loaded_code = 1; + window->enable = true; + window->flags_unknown1 |= 1; + window->redraw = true; + if(text_start == NULL) + buffer_drawwindow(window, (int*)(0x2014000 - 0x2000)); + return 0; +} + +void clearWindowTiles_buffer(WINDOW* window) +{ + clear_window_buffer(window, (int*)(0x2014000 - 0x2000)); + window->text_x = 0; + window->text_y = 0; } // x,y: tile coordinates @@ -1308,92 +1338,193 @@ void clear_tile_buffer(int x, int y, int pixels, int* dest) int buffer_reset_window(WINDOW* window, bool skip_redraw, int* dest) { - window->delay = 0; - byte code = window->loaded_code - 0xD; - if(code >= 1) - window->loaded_code = 1; - window->enable = true; - window->flags_unknown1 = 1; - window->redraw = true; - window->hold = true; - window->flags_unknown3a = window->flags_unknown3a && 0x1C; //The first byte is set to 0x23 - if(!skip_redraw) - buffer_drawwindow(window, dest); - return 0; + window->delay = 0; + byte code = window->loaded_code - 0xD; + if(code >= 1) + window->loaded_code = 1; + window->enable = true; + window->flags_unknown1 = 1; + window->redraw = true; + window->hold = true; + window->flags_unknown3a = window->flags_unknown3a && 0x1C; //The first byte is set to 0x23 + if(!skip_redraw) + buffer_drawwindow(window, dest); + return 0; } int buffer_drawwindow(WINDOW* window, int* dest) { - clear_window_buffer(window, dest); - unsigned short empty_tile = (0x1FF + (*tile_offset)) | (*palette_mask); - int baseOfWindow = ((window->window_y - 1) * 32) + window->window_x - 1; - unsigned short *arrangementBase = (*tilemap_pointer); - - for(int y = 0; y < window->window_height && y + window->window_y <= 0x1F; y++) - for(int x = 0; x < window->window_width && x + window->window_x <= 0x1F; x++) - arrangementBase[baseOfWindow + 1 + x + ((y + 1) * 32)] = empty_tile; - - window->counter = 0; - unsigned short void_tile = (0x1DF + (*tile_offset)) | (*palette_mask); - if((window->window_x - 1 < 0) || (window->window_x - 1 + window->window_width > 0x1F) || (window->window_y - 1 < 0) || (window->window_y - 1 + window->window_height > 0x1F)) - return -1; + clear_window_buffer(window, dest); + unsigned short empty_tile = (0x1FF + (*tile_offset)) | (*palette_mask); + int baseOfWindow = ((window->window_y - 1) * 32) + window->window_x - 1; + unsigned short *arrangementBase = (*tilemap_pointer); + + for(int y = 0; y < window->window_height && y + window->window_y <= 0x1F; y++) + for(int x = 0; x < window->window_width && x + window->window_x <= 0x1F; x++) + arrangementBase[baseOfWindow + 1 + x + ((y + 1) * 32)] = empty_tile; + + window->counter = 0; + unsigned short void_tile = (0x1DF + (*tile_offset)) | (*palette_mask); + if((window->window_x - 1 < 0) || (window->window_x - 1 + window->window_width > 0x1F) || (window->window_y - 1 < 0) || (window->window_y - 1 + window->window_height > 0x1F)) + return -1; - //Tiles - unsigned short bottom_right_corner_void = (0x93 + (*tile_offset)) | (*palette_mask); - unsigned short bottom_right_corner_full = (0x94 + (*tile_offset)) | (*palette_mask); - unsigned short bottom_left_corner_void = 0x400 | bottom_right_corner_void; - unsigned short bottom_left_corner_full = 0x400 | bottom_right_corner_full; - unsigned short top_right_corner_void = 0x800 | bottom_right_corner_void; - unsigned short top_right_corner_full = 0x800 | bottom_right_corner_full; - unsigned short top_left_corner_void = 0xC00 | bottom_right_corner_void; - unsigned short top_left_corner_full = 0xC00 | bottom_right_corner_full; + //Tiles + unsigned short bottom_right_corner_void = (0x93 + (*tile_offset)) | (*palette_mask); + unsigned short bottom_right_corner_full = (0x94 + (*tile_offset)) | (*palette_mask); + unsigned short bottom_left_corner_void = 0x400 | bottom_right_corner_void; + unsigned short bottom_left_corner_full = 0x400 | bottom_right_corner_full; + unsigned short top_right_corner_void = 0x800 | bottom_right_corner_void; + unsigned short top_right_corner_full = 0x800 | bottom_right_corner_full; + unsigned short top_left_corner_void = 0xC00 | bottom_right_corner_void; + unsigned short top_left_corner_full = 0xC00 | bottom_right_corner_full; - //Check which tiles to use for the corners - unsigned short current_top_left_tile = arrangementBase[baseOfWindow]; - if(current_top_left_tile == void_tile) //Top left - arrangementBase[baseOfWindow] = top_left_corner_void; - else if(current_top_left_tile != top_left_corner_void) - arrangementBase[baseOfWindow] = top_left_corner_full; - unsigned short current_top_right_tile = arrangementBase[baseOfWindow + 1 + window->window_width]; - if(current_top_right_tile == void_tile) //Top right - arrangementBase[baseOfWindow + 1 + window->window_width] = top_right_corner_void; - else if(current_top_right_tile != top_right_corner_void) - arrangementBase[baseOfWindow + 1 + window->window_width] = top_right_corner_full; - unsigned short current_bottom_left_tile = arrangementBase[baseOfWindow + (window->window_height * 32)]; - if(current_bottom_left_tile == void_tile) //Bottom left - arrangementBase[baseOfWindow + ((window->window_height + 1) * 32)] = bottom_left_corner_void; - else if(current_bottom_left_tile != bottom_left_corner_void) - arrangementBase[baseOfWindow + ((window->window_height + 1) * 32)] = bottom_left_corner_full; - unsigned short current_bottom_right_tile = arrangementBase[baseOfWindow + (window->window_height * 32) + 1 + window->window_width]; - if(current_bottom_right_tile == void_tile) //Bottom right - arrangementBase[baseOfWindow + ((window->window_height + 1) * 32) + 1 + window->window_width] = bottom_right_corner_void; - else if(current_bottom_right_tile != bottom_right_corner_void) - arrangementBase[baseOfWindow + ((window->window_height + 1) * 32) + 1 + window->window_width] = bottom_right_corner_full; - - //Border tiles - unsigned short *address = (unsigned short*)0x3000A0E; - unsigned short bottom_horizontal = (0x96 + (*tile_offset)) | (*palette_mask); - unsigned short top_horizontal = 0x800 | bottom_horizontal; - unsigned short right_vertical = (0x95 + (*tile_offset)) | (*palette_mask); - unsigned short left_vertical = 0x400 | right_vertical; - - for(int i = 0; i < window->window_width; i++) - { - arrangementBase[baseOfWindow + 1 + i] = top_horizontal; - arrangementBase[baseOfWindow + ((window->window_height + 1) * 32) + 1 + i] = bottom_horizontal; - } - - for(int i = 0; i < window->window_height; i++) - { - arrangementBase[baseOfWindow + ((i + 1) * 32)] = left_vertical; - arrangementBase[baseOfWindow + ((i + 1) * 32) + 1 + window->window_width] = right_vertical; - } - - window->redraw = false; - window->enable = true; - - (*address) = 1; - return 0; + //Check which tiles to use for the corners + unsigned short current_top_left_tile = arrangementBase[baseOfWindow]; + if(current_top_left_tile == void_tile) //Top left + arrangementBase[baseOfWindow] = top_left_corner_void; + else if(current_top_left_tile != top_left_corner_void) + arrangementBase[baseOfWindow] = top_left_corner_full; + unsigned short current_top_right_tile = arrangementBase[baseOfWindow + 1 + window->window_width]; + if(current_top_right_tile == void_tile) //Top right + arrangementBase[baseOfWindow + 1 + window->window_width] = top_right_corner_void; + else if(current_top_right_tile != top_right_corner_void) + arrangementBase[baseOfWindow + 1 + window->window_width] = top_right_corner_full; + unsigned short current_bottom_left_tile = arrangementBase[baseOfWindow + ((window->window_height + 1) * 32)]; + if(current_bottom_left_tile == void_tile) //Bottom left + arrangementBase[baseOfWindow + ((window->window_height + 1) * 32)] = bottom_left_corner_void; + else if(current_bottom_left_tile != bottom_left_corner_void) + arrangementBase[baseOfWindow + ((window->window_height + 1) * 32)] = bottom_left_corner_full; + unsigned short current_bottom_right_tile = arrangementBase[baseOfWindow + ((window->window_height + 1) * 32) + 1 + window->window_width]; + if(current_bottom_right_tile == void_tile) //Bottom right + arrangementBase[baseOfWindow + ((window->window_height + 1) * 32) + 1 + window->window_width] = bottom_right_corner_void; + else if(current_bottom_right_tile != bottom_right_corner_void) + arrangementBase[baseOfWindow + ((window->window_height + 1) * 32) + 1 + window->window_width] = bottom_right_corner_full; + + //Border tiles + unsigned short *address = (unsigned short*)0x3000A0E; + unsigned short bottom_horizontal = (0x96 + (*tile_offset)) | (*palette_mask); + unsigned short top_horizontal = 0x800 | bottom_horizontal; + unsigned short right_vertical = (0x95 + (*tile_offset)) | (*palette_mask); + unsigned short left_vertical = 0x400 | right_vertical; + + for(int i = 0; i < window->window_width; i++) + { + arrangementBase[baseOfWindow + 1 + i] = top_horizontal; + arrangementBase[baseOfWindow + ((window->window_height + 1) * 32) + 1 + i] = bottom_horizontal; + } + + for(int i = 0; i < window->window_height; i++) + { + arrangementBase[baseOfWindow + ((i + 1) * 32)] = left_vertical; + arrangementBase[baseOfWindow + ((i + 1) * 32) + 1 + window->window_width] = right_vertical; + } + + window->redraw = false; + window->enable = true; + + (*address) = 1; + return 0; +} + +int setNumber_getLength(int value, byte *str, int maxLength) +{ + if(value <= 0) + { + str[0] = ZERO; + return 1; + } + unsigned int *upperValuesTable = (unsigned int*)0x8B1C064; + unsigned int upperValue = *(upperValuesTable + maxLength); + if(value >= upperValue) + { + for(int i = 0; i < maxLength; i++) + str[i] = ZERO + 9; + return maxLength; + } + int pos = 0; + int tmpValue = value; + for(int i=0; i < maxLength + 1; i++) + { + if(value >= upperValue) + { + byte digit; + if(upperValue == 0) + digit = tmpValue; + else + { + digit = m2_div(tmpValue, upperValue); + tmpValue -= (digit * upperValue); + } + str[pos++] = ZERO + digit; + } + upperValue = *(upperValuesTable + maxLength - i - 1); + } + return pos; +} + +unsigned short ailmentTileSetup(PC *character, unsigned short defaultVal) +{ + int value = defaultVal; + byte flagValue = 0; + if(character->ailment == CONSCIOUS) + { + if(character->ailment2 != CONSCIOUS) + { + flagValue = character->ailment2; + value = 1; + } + else if(character->ailment3 != CONSCIOUS) + { + flagValue = character->ailment3; + value = 2; + } + else if(character->strange) + { + flagValue = character->strange; + value = 3; + } + else if(character->cant_concentrate) + { + flagValue = character->cant_concentrate; + value = 4; + } + else if(character->homesick) + { + flagValue = character->homesick; + value = 5; + } + else if(character->unknown2[0]) + { + flagValue = character->unknown2[0]; + value = 6; + } + else + return 0; + } + else + { + value = 0; + flagValue = character->ailment; + } + unsigned short *returnValues = (unsigned short*)0x8B1F2E4; + return (*(returnValues + (value * 7) + flagValue - 1)); +} + +void printCashWindow() +{ + (*window_flags) |= 2; + byte *str = (*free_strings_pointers); + format_cash_window(*cash_on_hand, 0x30, str); + initWindow_buffer(getWindow(1), str, 0); + print_window_with_buffer(getWindow(1)); + m2_sub_d6844(); + m2_sub_d3c50(); +} + +// x, y, width: tile coordinates +void print_blankstr_buffer(int x, int y, int width, int *dest) +{ + clear_rect_buffer(x, y, width, 2, WINDOW_AREA_BG, dest); } // x,y: tile coordinates diff --git a/src/c/vwf.h b/src/c/vwf.h index f401b2e..609d24d 100644 --- a/src/c/vwf.h +++ b/src/c/vwf.h @@ -39,7 +39,7 @@ void print_special_character(int tile, int x, int y); void map_special_character(unsigned short tile, int x, int y); void map_tile(unsigned short tile, int x, int y); byte print_character_with_callback(byte chr, int x, int y, int font, int foreground, - int *dest, int (*getTileCallback)(int, int), unsigned short *tilemapPtr, int tilemapWidth); + int *dest, int (*getTileCallback)(int, int), unsigned short *tilemapPtr, int tilemapWidth, byte doubleTileHeight); byte print_character_to_ram(byte chr, int *dest, int xOffset, int font, int foreground); int print_window_header_string(int *dest, byte *str, int x, int y); void clear_window_header(int *dest, int length, int x, int y); @@ -92,6 +92,16 @@ int jumpToOffset(byte* character); void copy_tile_buffer(int xSource, int ySource, int xDest, int yDest, int *dest); void copy_tile_up_buffer(int x, int y, int *dest); void setStuffWindow_Graphics(); +void clearWindowTiles_buffer(WINDOW* window); +int initWindow_buffer(WINDOW* window, byte* text_start, unsigned short delay_between_prints); +void print_blankstr_buffer(int x, int y, int width, int *dest); +unsigned short ailmentTileSetup(PC *character, unsigned short defaultVal); +int setNumber_getLength(int value, byte *str, int maxLength); +int print_string_in_buffer(byte *str, int x, int y, int *dest); +void printCashWindow(); +WINDOW* getWindow(int index); +void printstr_buffer(WINDOW* window, byte* str, unsigned short x, unsigned short y, bool highlight); +unsigned short printstr_hlight_buffer(WINDOW* window, byte* str, unsigned short x, unsigned short y, bool highlight); extern unsigned short m2_coord_table[]; extern byte m2_ness_name[]; @@ -107,6 +117,7 @@ extern byte m12_other_str7[]; extern byte m12_other_str8[]; extern byte m2_cstm_last_printed[]; extern byte *m2_script_readability; +extern PC m2_ness_data[]; extern void cpufastset(void *source, void *dest, int mode); extern byte* m2_strlookup(int *offset_table, byte *strings, int index); @@ -119,4 +130,6 @@ extern int m2_div(int dividend, int divisor); extern int m2_remainder(int dividend, int divisor); extern void m2_soundeffect(int index); extern void m2_printstr(WINDOW* window, byte* str, unsigned short x, unsigned short y, bool highlight); -extern int customcodes_parse_generic(int code, char* parserAddress, WINDOW* window, int* dest); \ No newline at end of file +extern int customcodes_parse_generic(int code, char* parserAddress, WINDOW* window, int* dest); +extern void m2_sub_d3c50(); +extern void m2_sub_d6844(); \ No newline at end of file diff --git a/src/c/window.h b/src/c/window.h index 1bfc999..1451525 100644 --- a/src/c/window.h +++ b/src/c/window.h @@ -3,6 +3,13 @@ #include "types.h" +typedef enum WINDOW_ACTION +{ + ACTION_NONE = 0, + ACTION_STEPIN = 1, + ACTION_STEPOUT = -1 +} WINDOW_ACTION; + typedef struct WINDOW { // 0x00 bool enable : 1; // 0x0001 Indicates that the window is enabled. @@ -52,8 +59,8 @@ typedef struct WINDOW { unsigned short cursor_x_base; byte cursor_x_delta; byte unknown9a; - byte loaded_code; - byte unknown9[3]; + byte loaded_code; + byte unknown9[3]; int unknown10; int unknown11; } WINDOW; diff --git a/src/data/m2-status-symbols.bin b/src/data/m2-status-symbols.bin new file mode 100644 index 0000000..e55ad0d Binary files /dev/null and b/src/data/m2-status-symbols.bin differ diff --git a/src/m2-hack.asm b/src/m2-hack.asm index 37d9660..d322136 100644 --- a/src/m2-hack.asm +++ b/src/m2-hack.asm @@ -14,6 +14,7 @@ //============================================================================== .org 0x8AFED84 :: .incbin "data/m2-mainfont1-empty.bin" +.org 0x8B03DE4 :: .incbin "data/m2-status-symbols.bin" .org 0x8B0F424 :: .incbin "data/m2-mainfont2-empty.bin" .org 0x8B13424 :: .incbin "data/m2-mainfont3-empty.bin" .org 0x8B088A4 :: .incbin "data/m2-shifted-cursor.bin" @@ -49,17 +50,47 @@ mov r3,6 .include "m2-status-initial.asm" .include "m2-status-switch.asm" +//--------------------------------------------------------- +// Main window hacks +//--------------------------------------------------------- + +.org 0x80B7D9A :: bl b7d9a_main_window_manage_input +//.org 0x80B8A36 :: bl initWindow_buffer //Money window +//.org 0x80B8A3C :: bl print_window_with_buffer +.org 0x80B8890 :: bl print_window_with_buffer :: bl b8894_printCashWindowAndStore //Main window + Cash Window out of Status menu +.org 0x80B831A :: bl initWindow_buffer +.org 0x80B8320 :: bl b8320_statusWindowTextStore + //--------------------------------------------------------- // BAC18 hacks (status window) //--------------------------------------------------------- -.org 0x80BACFC :: bl bac18_redraw_status +.org 0x80BAC46 :: nop :: nop +.org 0x80BAC6E :: bl bac6e_statusWindowNumbersInputManagement +.org 0x80BAD7E :: bl printstr_buffer +.org 0x80BAD88 :: bl initWindow_buffer +.org 0x80BAD92 :: bl initWindow_buffer +.org 0x80BACFC :: bl bac18_redraw_status_store .org 0x80BADE6 :: bl bac18_redraw_status .org 0x80BACEA :: bl bacea_status_psi_window +.org 0x80BACBA :: bl print_window_with_buffer +.org 0x80BACC4 :: bl initWindow_buffer +.org 0x80BAD1A :: bl clearWindowTiles_buffer +.org 0x80BADF6 :: bl initWindow_buffer .org 0x80BACEE :: bl bac18_clear_psi .org 0x80BADB0 :: bl badb0_status_inner_window .org 0x80BADCC :: b 0x80BADD8 +//--------------------------------------------------------- +// PSI window hacks +//--------------------------------------------------------- + +.org 0x80BAE1C :: bl print_window_with_buffer +.org 0x80BAEC6 :: bl baec6_psi_window_print_buffer +.org 0x80BAED4 :: bl baec6_psi_window_print_buffer +.org 0x80BAEE2 :: bl baec6_psi_window_print_buffer +.org 0x80BAEF0 :: bl baec6_psi_window_print_buffer + //--------------------------------------------------------- // BAEF8 hacks (equip window) //--------------------------------------------------------- @@ -1511,12 +1542,15 @@ m2_coord_table_file: .definelabel m2_clearwindowtiles ,0x80CA834 .definelabel m2_menuwindow ,0x80C1C98 .definelabel m2_resetwindow ,0x80BE490 +.definelabel m2_sub_d3c50 ,0x80D3C50 .definelabel m2_hpwindow_up ,0x80D3F0C .definelabel m2_curhpwindow_down ,0x80D41D8 +.definelabel m2_sub_d6844 ,0x80D6844 .definelabel m2_div ,0x80F49D8 .definelabel m2_remainder ,0x80F4A70 -.definelabel m2_default_names ,0x82B9330 .definelabel m2_items ,0x8B1D62C +.definelabel m2_default_names ,0x82B9330 +.definelabel m2_psi_print_table ,0x8B2A9C0 //============================================================================== // Code files diff --git a/src/m2-vwf-entries.asm b/src/m2-vwf-entries.asm index 8abcc53..eb7f6ae 100644 --- a/src/m2-vwf-entries.asm +++ b/src/m2-vwf-entries.asm @@ -330,20 +330,50 @@ bl 0x80BE260 mov r1,r0 mov r0,r4 mov r2,0 -bl 0x80BE458 +bl initWindow_buffer // Render text mov r0,r4 -bl 0x80C8FFC +bl statusWindowText // Render numbers mov r0,r4 +ldrh r1,[r0,#0] +ldr r2,=#0xFBFF +and r1,r2 +strh r1,[r0,#0] mov r1,0 -bl 0x80C0A5C +bl statusNumbersPrint pop {r4,pc} .pool +//============================================================================== +// Redraws the status window (when exiting the PSI menu) and stores it +bac18_redraw_status_store: +push {lr} +bl bac18_redraw_status +bl store_pixels_overworld +pop {pc} +.pool + +//============================================================================== +// Only if the character changed store the buffer - called when reading inputs +bac6e_statusWindowNumbersInputManagement: +push {lr} +ldr r2,=#m2_active_window_pc +ldrb r2,[r2,#0] +push {r2} +bl statusWindowNumbers +pop {r2} +ldr r1,=#m2_active_window_pc +ldrb r1,[r1,#0] +cmp r1,r2 +beq @@end +bl store_pixels_overworld + +@@end: +pop {pc} //============================================================================== // Clears the PSI window when switching classes @@ -359,7 +389,8 @@ beq @@next // If flag 0x10 is set, clear the PSI window ldr r0,[r5,0x1C] // PSI window -bl clear_window +ldr r1,=#0x2012000 +bl clear_window_buffer @@next: // Clobbered code @@ -1761,7 +1792,6 @@ strb r2,[r0,#3] b @@end //Goes to the end of the routine @@goToInner: -bl load_pixels_overworld lsl r0,r0,0x10 //Properly stores the output into r4 and, since we're going into the inner window, sets vwf_skip to false asr r4,r0,0x10 ldr r0,[r5,#0x20] @@ -1884,7 +1914,7 @@ cmp r1,#0 //Checks if vwf_skip is false bne @@end mov r1,r2 //If it is, prints the PSI description mov r2,0 -bl m2_initwindow //Initializes the PSI description window +bl initWindow_buffer //Initializes the PSI description window ldr r0,[r5,0x28] bl print_window_with_buffer //Prints the PSI description window bl store_pixels_overworld @@ -2088,6 +2118,28 @@ pop {pc} .pool +//============================================================================== +//Prints and stores the PSI window in the PSI menu +baec6_psi_window_print_buffer: +push {lr} +bl psiWindow_buffer +bl store_pixels_overworld +pop {pc} + +//============================================================================== +//Loads the buffer in if entering another window from the main window +b7d9a_main_window_manage_input: +push {lr} +bl 0x80BE53C +cmp r0,#0 +beq @@end +cmp r0,#0 +blt @@end +bl load_pixels_overworld + +@@end: +pop {pc} + //============================================================================== //Prints the target window if and only if the cursor's position changed in this input management function c495a_status_target: @@ -2724,6 +2776,34 @@ pop {pc} .pool +//============================================================================== +//Prints the cash window and then stores the buffer to vram +b8894_printCashWindowAndStore: +push {lr} +bl printCashWindow +bl store_pixels_overworld +pop {pc} + +//============================================================================== +//UNUSED +bac46_statusWindowNumbersStore: +push {lr} +bl statusWindowNumbers +bl store_pixels_overworld +pop {pc} + +//============================================================================== +//Prints the status text and numbers in the buffer, then loads it in vram +b8320_statusWindowTextStore: +push {lr} +push {r0} +bl statusWindowText +pop {r0} +mov r1,#0 +bl statusNumbersPrint +bl store_pixels_overworld +pop {pc} + //============================================================================== //Loads the vram into the buffer, it's called each time there is only the main file_select window active (a good way to set the whole thing up) load_pixels_overworld: @@ -2733,7 +2813,7 @@ ldr r0,=#0x6002000 //Source str r0,[r1] ldr r0,=#0x2014000 //Target str r0,[r1,#4] -ldr r0,=#0xA4001000 //Store 0x4000 bytes - When VBlank and in words of 32 bits +ldr r0,=#0xA4001000 //Store 0x4000 bytes - When HBlank and in words of 32 bits str r0,[r1,#8] ldr r0,[r1,#8] pop {r0-r1,pc}