From abe7bde678b2535ad9744d608b5c38dd86146491 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Fri, 4 Aug 2023 03:28:17 +0000 Subject: [PATCH] graphic: display nearly-complete stats page #1 Type is not displayed because the type names have no parsers/generators yet. --- Makefile | 2 + derived/font.png | Bin 5212 -> 17992 bytes graphic.cpp | 101 ++++++++++++++++++++++++++++++++++++++----- graphic.hpp | 7 ++- main.cpp | 31 +++++++++++-- number.cpp | 68 +++++++++++++++++++++++++++++ number.hpp | 16 +++++++ pokemon.hpp | 2 + pokemon_instance.cpp | 76 +++++++++++++++----------------- pokemon_instance.hpp | 6 ++- 10 files changed, 252 insertions(+), 57 deletions(-) create mode 100644 number.cpp create mode 100644 number.hpp diff --git a/Makefile b/Makefile index e867e42..66a736e 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,8 @@ SRC += vram.cpp SRC += font.cpp SRC += graphic.cpp SRC += menu.cpp +SRC += number.cpp +SRC += pokemon_instance.cpp DEP = $(patsubst %.cpp,%.cpp.d,$(SRC)) diff --git a/derived/font.png b/derived/font.png index 3e60100ee1093bd93365cc6c557d570559531009..56efba3e5b97fac53474d339e2e5b5d316c47e39 100644 GIT binary patch delta 14563 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 LqIjLCaq#~E1m*yG delta 1810 zcmV+t2krRCi~-yzkRyKp!+KO$bW&k=AaHVTW@&6?Aar?fWgumEX=VTbc-n1H!4U%? z2>e?`N%kB7+nuT#YCV)E*;A zj~!F8{ZbDy1-23_!!IO1KkM;hFj6(PU5xbZ!oCW{Uts+*;*nC&I%@oIqvA&3Aw)N* z<6D%9=Ia;slUC?hp#{;k?Vo+N=^dNB1LhMEWD$_j0NO%8HIgj??I58T7o=WSH?x8K zo6|&i1LgZ!98#PVN&o->Ba1ZYgt3nVIVys|w zN|O|eNeoF!@eOHmh-Vac=smZCs8y#lvRAlnDtHJ!z)S5e~aj zmx6$MNE5gn8?c{+>y%D+)h4Oz>--_|hW)HDBl;}=pxP?<#=7b*Y%4S2InGl~Kv zFf(CgV`XMCEjBV{HZ3$|Wn?X3GB#l?G&VCcWMXAvF*RjkllwKN4KOz`Ff%qdIX5&m zG&z&6Hf{|!Ix{d-FgZFjHaajklPWhM4L3S7FjO!(Iy5#qFgUYVHxU7|OgUf(1b;*y zN0YEYAAbiP2`&iFe#f@}00enSL_t(&-sM?aa^x@wWL&=D^dWl=x%+{H0DUP#?+&Wo+H^#Z?KPMhSM9}lxXHnMik zi;ZiCk`8t2A#u|71rJF-+s)s*o3DT2d?9pT?0@B-MMO>km2c>_^DNFXYF`KxFtl;s zb4ht8KCs?1eaO)t1}CDl3lk+_^Z-dZmgplYW_D892=3MpW6te+ZmcG}vM+TF6fm$7 zLfzbRJ-_EEaH9{(-~FB0E(OW{lO0>Di(KDsjAgPyTw9DEQUeoID~P zV8FwPAY4O|D-sM(@RNR^jTJX9o|yc10EvqS=WTc`Z(nbPpAFirfkOlU)W!ga_J7sw z0nQLG@!#BZOw!5IOYi*^e6;FlFXS&m*~Sw^g&yB zzPgyO1!-l(X=p^``}C11f8uH$93o)hI{usp`rrRzhW7|SV!vVBX8dF0hikUB;Q&6R z1QW=|Ej0ArEz`Z9V)^i`$A4j{^sFa_eqGf#aVN_|`e2g4@8T@jwV4K19AHht%%7tV z-3mcP6(p71OAhdc{nB}m3~OSEURkaMkl5#a9eBgjWJcMcR;XZCu;7;oD44}@b4ZmN z-sC`rWCf683nF7c-D*m70QK2&U;%g{YFmI)@L?v`j7L;KS@zezUw`I^AXXlTYR%-D zh^8J1`_6@nVz$))KyQ?1DCJqHFjmPhOVlpeaJ4Ij?0I~Y!g?bh`<(-Ag>)t}fE|al zl-{*l$=&2qsek6cQ5gIBbUe!Y8>sO*$CZRbd}+r%M~33{+5w8ca|XwTE%@j zP-saZd$Y|Pc+|z#_#+V>KJDEDMT7ntke77eH>Ee;aDd3#p#T5?07*qoM6N<$f?n%N AivR!s diff --git a/graphic.cpp b/graphic.cpp index 0ac2d09..db737e9 100644 --- a/graphic.cpp +++ b/graphic.cpp @@ -5,6 +5,9 @@ #include "font.hpp" #include "start_size.hpp" #include "control.hpp" +#include "number.hpp" + +#include "pokemon_instance.hpp" struct dialog_border { static constexpr uint8_t corner_top_left = 105; @@ -44,6 +47,12 @@ struct hp_bar { static constexpr uint8_t end_cap_bar = 0x66; }; +struct stats { + static constexpr uint8_t id = 0x70; // ID + static constexpr uint8_t no = 0x71; // No + static constexpr uint8_t no_dot = 0x4e; // . +}; + #define S reinterpret_cast void draw_text(const uint32_t base_pattern, @@ -184,23 +193,95 @@ void draw_hp_bar(const uint32_t base_pattern, put_char(base_pattern, top_left.x + 8, top_left.y, end_cap); } -static uint32_t hp = 0; - -void draw_stats1(const uint32_t base_pattern) +void draw_stats1(const uint32_t base_pattern, + const pokemon_instance_t& pokemon_instance) { // white out the entire screen draw_box_background(base_pattern, {-1, -1}, {20, 18}); // top status battle box - draw_battle_border(base_pattern, {19, 1}, {8, 7}); - draw_hp_bar(base_pattern, {11, 4}, hp_bar::end_cap_bar, (hp >> 3) % 48); - hp++; + { + draw_battle_border(base_pattern, {19, 1}, {8, 7}); - // bottom border - draw_battle_border(base_pattern, {19, 9}, {12, 17}); + // hp + { + const int32_t hp_48 = (pokemon_instance.current_hit_points * 48) / pokemon_instance.stat_values.hit_points; + draw_hp_bar(base_pattern, {11, 3}, hp_bar::end_cap_bar, hp_48); - // bottom left dialog box - draw_box_border(base_pattern, {0, 8}, {9, 17}); + draw_number_right_align(base_pattern, {12, 4}, + pokemon_instance.current_hit_points, + 3, ascii_to_font(' ')); // width, fill + + put_char(base_pattern, 15, 4, ascii_to_font('/')); + + draw_number_right_align(base_pattern, {16, 4}, + pokemon_instance.stat_values.hit_points, + 3, ascii_to_font(' ')); // width, fill + } + + // name + draw_text(base_pattern, pokemon[pokemon_instance.species].name, 9, 1); + + // level + put_char(base_pattern, 14, 2, battle_border::level); + draw_number_left_align(base_pattern, {15, 2}, + pokemon_instance.level, + 3); // width + +#define S reinterpret_cast + draw_text(base_pattern, S("STATUS/___"), 9, 6); + } + + // bottom right border + { + draw_battle_border(base_pattern, {19, 9}, {12, 17}); + + for (int32_t ix = 0; ix < 2; ix++) { + draw_text(base_pattern, S("TYPE"), 10, 9 + (2 * ix)); + put_char(base_pattern, 15, 9 + (2 * ix), ascii_to_font('1' + ix)); + put_char(base_pattern, 15, 9 + (2 * ix), ascii_to_font('/')); + } + } + + { // bottom left dialog box + draw_box_border(base_pattern, {0, 8}, {9, 17}); + + draw_text(base_pattern, S("ATTACK"), 1, 9 + 0); + draw_text(base_pattern, S("DEFENSE"), 1, 9 + 2); + draw_text(base_pattern, S("SPEED"), 1, 9 + 4); + draw_text(base_pattern, S("SPECIAL"), 1, 9 + 6); +#undef S + + draw_number_right_align(base_pattern, {6, 10 + 0}, + pokemon_instance.stat_values.attack, + 3, ascii_to_font(' ')); // width, fill + + draw_number_right_align(base_pattern, {6, 10 + 2}, + pokemon_instance.stat_values.defense, + 3, ascii_to_font(' ')); // width, fill + + draw_number_right_align(base_pattern, {6, 10 + 4}, + pokemon_instance.stat_values.speed, + 3, ascii_to_font(' ')); // width, fill + + draw_number_right_align(base_pattern, {6, 10 + 6}, + pokemon_instance.stat_values.special, + 3, ascii_to_font(' ')); // width, fill + } // end bottom left dialog box + + // pokedex number + { + put_char(base_pattern, 1, 7, stats::no); + put_char(base_pattern, 2, 7, stats::no_dot); + + const int32_t pokedex_number = static_cast(pokemon_instance.species) + 1; + draw_number_right_align(base_pattern, + {3, 7}, + pokedex_number, + 3, // width + ascii_to_font('0') // fill + ); + } } void dialog_t::draw(const uint32_t base_pattern, diff --git a/graphic.hpp b/graphic.hpp index e9c65bf..f9f5a7e 100644 --- a/graphic.hpp +++ b/graphic.hpp @@ -5,6 +5,8 @@ #include "render_map.hpp" // for cell_offset #include "vdp2.h" +#include "pokemon_instance.hpp" + static inline void put_char(const uint32_t base_pattern, const int32_t x, const int32_t y, // in cells const uint8_t c) @@ -27,11 +29,12 @@ void draw_box_background(const uint32_t base_pattern, void draw_battle_border(const uint32_t base_pattern, const screen_cell_t& top_corner, const screen_cell_t& bottom_corner); -void draw_stats1(const uint32_t base_pattern); +void draw_stats1(const uint32_t base_pattern, + const pokemon_instance_t& pokemon_instance); struct dialog_t { - static constexpr screen_cell_t top_left = { 0, 12}; + static constexpr screen_cell_t top_left = { 0, 12}; static constexpr screen_cell_t bottom_right = {19, 17}; static void draw(const uint32_t base_pattern, diff --git a/main.cpp b/main.cpp index 90c1479..aad9bbb 100644 --- a/main.cpp +++ b/main.cpp @@ -27,6 +27,7 @@ #include "menu.hpp" #include "pokemon.hpp" +#include "pokemon_instance.hpp" static int32_t pokemon_raw_index = 0; @@ -171,6 +172,15 @@ void render_pokemon(const uint32_t ix, const enum pokemon_t::pokemon pokemon_id, const uint32_t character_address = (base_pattern * 16) / 8; const uint32_t dimension = pokemon_sprite_dimension(pokemon[pokemon_id].pic.front.size); + int32_t x_offset; + int32_t y_offset; + switch (dimension) { + default: + case 40: x_offset = 2; y_offset = 2; break; + case 48: x_offset = 1; y_offset = 1; break; + case 56: x_offset = 1; y_offset = 0; break; + } + vdp1.vram.cmd[ix].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__NORMAL_SPRITE; vdp1.vram.cmd[ix].LINK = 0; // The "end code" is 0xf, which is being used in the mai sprite palette. If @@ -181,8 +191,8 @@ void render_pokemon(const uint32_t ix, const enum pokemon_t::pokemon pokemon_id, | COLR__COLOR_BANK__TYPE0__PR(0); vdp1.vram.cmd[ix].SRCA = character_address; vdp1.vram.cmd[ix].SIZE = SIZE__X(dimension) | SIZE__Y(dimension); - vdp1.vram.cmd[ix].XA = (cell_offset::x * 8) + screen_cell.x * 8; - vdp1.vram.cmd[ix].YA = (cell_offset::y * 8) + screen_cell.y * 8; + vdp1.vram.cmd[ix].XA = (cell_offset::x * 8) + (screen_cell.x + x_offset) * 8; + vdp1.vram.cmd[ix].YA = (cell_offset::y * 8) + (screen_cell.y + y_offset) * 8; } void render_sprites(const offset_t& offset) @@ -486,8 +496,12 @@ void update() //else if (event::button_a() ) check_sign(); } +static uint32_t frame = 0; + void render() { + frame++; + const offset_t offset = state.player.offset(); render_sprites(offset); @@ -505,7 +519,18 @@ void render() cursor_t cursor = { 1, 1 }; draw_menu_cursor(state.draw.base_pattern.font, fight_menu, cursor); - draw_stats1(state.draw.base_pattern.font); + static pokemon_instance_t pokemon_instance; + pokemon_instance.species = static_cast(pokemon_raw_index); + pokemon_instance.stat_experience = {0, 0, 0, 0, 0}; + pokemon_instance.determinant_values.dvs = 0b1110'0101'1000'0110; + pokemon_instance.level = 70; + pokemon_instance.determine_stats(); + if (frame % 4 == 0) + pokemon_instance.current_hit_points++; + if (pokemon_instance.current_hit_points > pokemon_instance.stat_values.hit_points) + pokemon_instance.current_hit_points = 0; + + draw_stats1(state.draw.base_pattern.font, pokemon_instance); } extern "C" diff --git a/number.cpp b/number.cpp new file mode 100644 index 0000000..04ecf7e --- /dev/null +++ b/number.cpp @@ -0,0 +1,68 @@ +#include + +#include "graphic.hpp" +#include "font.hpp" + +// left-align (with fill) +// right-align + +struct bcd_t { + uint32_t digits; + int32_t length; + + auto operator<=>(const bcd_t&) const = default; +}; + +static inline constexpr bcd_t int_to_bcd(int32_t n) +{ + if (n < 0) n = 0; // are there negative numbers in pokemon? + if (n == 0) return { 0, 1 }; + uint32_t bcd = 0; + + int32_t index = 0; + while (n != 0) { + bcd |= (n % 10) << (4 * index); + n /= 10; + index += 1; + } + return { bcd, index }; +} + +static_assert(int_to_bcd(0) == (bcd_t){0x0, 1}); +static_assert(int_to_bcd(9) == (bcd_t){0x9, 1}); +static_assert(int_to_bcd(20) == (bcd_t){0x20, 2}); +static_assert(int_to_bcd(512) == (bcd_t){0x512, 3}); + +void draw_number_right_align(const uint32_t base_pattern, + const screen_cell_t& pos, + const int32_t n, + const int32_t width, + const uint8_t fill) +{ + const bcd_t bcd = int_to_bcd(n); + + int32_t index = 0; + while (index < width) { + const uint8_t digit = (index < bcd.length) + ? ascii_to_font('0' + ((bcd.digits >> (4 * index)) & 0b1111)) + : fill; + index++; + put_char(base_pattern, (pos.x + width) - index, pos.y, digit); + } +} + +void draw_number_left_align(const uint32_t base_pattern, + const screen_cell_t& pos, + const int32_t n, + const int32_t width) +{ + const bcd_t bcd = int_to_bcd(n); + + int32_t index = 0; + int32_t length = width < bcd.length ? width : bcd.length; + while (index < length) { + const uint8_t digit = ascii_to_font('0' + ((bcd.digits >> (4 * index)) & 0b1111)); + index++; + put_char(base_pattern, pos.x + (length - index), pos.y, digit); + } +} diff --git a/number.hpp b/number.hpp new file mode 100644 index 0000000..184d92c --- /dev/null +++ b/number.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include "coordinates.hpp" + +void draw_number_right_align(const uint32_t base_pattern, + const screen_cell_t& pos, + const int32_t n, + const int32_t width, + const uint8_t fill); + +void draw_number_left_align(const uint32_t base_pattern, + const screen_cell_t& pos, + const int32_t n, + const int32_t width); diff --git a/pokemon.hpp b/pokemon.hpp index 0cdbbd9..a81ce56 100644 --- a/pokemon.hpp +++ b/pokemon.hpp @@ -1,3 +1,5 @@ +#pragma once + #include #include "gen/pokemon/moves.hpp" diff --git a/pokemon_instance.cpp b/pokemon_instance.cpp index cadc9da..94b169b 100644 --- a/pokemon_instance.cpp +++ b/pokemon_instance.cpp @@ -1,9 +1,9 @@ #include "pokemon_instance.hpp" -static uint16_t _determine_stat(const uint32_t base_stat_value, - const uint32_t determinant_value, - const uint32_t stat_experience, - const uint32_t level) +static constexpr uint16_t _determine_stat(const uint32_t base_stat_value, + const uint32_t determinant_value, + const uint32_t stat_experience, + const uint32_t level) { const uint32_t x = base_stat_value + determinant_value; const uint32_t y = sqrt_ceil(stat_experience) / 4; @@ -17,45 +17,41 @@ static_assert(_determine_stat( 90, 0b0101, 0, 70) == (138 - 5)); static_assert(_determine_stat(130, 0b1000, 0, 70) == (198 - 5)); static_assert(_determine_stat(154, 0b0110, 0, 70) == (229 - 5)); -constexpr inline uint16_t -pokemon_instance_t::determine_stat(enum stat_t stat) +void +pokemon_instance_t::determine_stats() { - switch (stat) { - default: - case stat_t::hit_points: - return _determine_stat(pokemon[species].base_stat_values.hit_points, - determinant_values.hit_points(), - stat_experience.hit_points, - level) - + 10 + level; - case stat_t::attack: - return _determine_stat(pokemon[species].base_stat_values.attack, - determinant_values.attack(), - stat_experience.attack, - level) - + 5; - case stat_t::defense: - return _determine_stat(pokemon[species].base_stat_values.defense, - determinant_values.defense(), - stat_experience.defense, - level) - + 5; - case stat_t::speed: - return _determine_stat(pokemon[species].base_stat_values.speed, - determinant_values.speed(), - stat_experience.speed, - level) - + 5; - case stat_t::special: - return _determine_stat(pokemon[species].base_stat_values.special, - determinant_values.special(), - stat_experience.special, - level) - + 5; - } + stat_values.hit_points = _determine_stat(pokemon[species].base_stat_values.hit_points, + determinant_values.hit_points(), + stat_experience.hit_points, + level + ) + 10 + level; + + stat_values.attack = _determine_stat(pokemon[species].base_stat_values.attack, + determinant_values.attack(), + stat_experience.attack, + level + ) + 5; + + stat_values.defense = _determine_stat(pokemon[species].base_stat_values.defense, + determinant_values.defense(), + stat_experience.defense, + level + ) + 5; + + stat_values.speed = _determine_stat(pokemon[species].base_stat_values.speed, + determinant_values.speed(), + stat_experience.speed, + level + ) + 5; + + stat_values.special = _determine_stat(pokemon[species].base_stat_values.special, + determinant_values.special(), + stat_experience.special, + level + ) + 5; } -constexpr inline uint16_t +void pokemon_instance_t::learn_move(enum move_t::move move, int32_t index) { switch (index) { diff --git a/pokemon_instance.hpp b/pokemon_instance.hpp index 00772c7..45a79a3 100644 --- a/pokemon_instance.hpp +++ b/pokemon_instance.hpp @@ -1,3 +1,5 @@ +#pragma once + #include #include "sqrt.hpp" @@ -77,7 +79,7 @@ struct pokemon_instance_t { // - id number // - original trainer - constexpr inline uint16_t determine_stat(enum stat_t stat); + void determine_stats(); - constexpr inline void learn_move(enum move_t::move move, uint32_t index); + void learn_move(enum move_t::move move, int32_t index); };