#include "common.h" #include #include uint16_t monochromeGBColorPalette[4] = { 0x7FFF, 0x56B6, 0x2D6B, 0x421 }; uint32_t mediumFastExpTable[] = { 0, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 4096, 4913, 5832, 6859, 8000, 9261, 10648, 12167, 13824, 15625, 17576, 19683, 21952, 24389, 27000, 29791, 32768, 35937, 39304, 42875, 46656, 50653, 54872, 59319, 64000, 68921, 74088, 79507, 85184, 91125, 97336, 103823, 110592, 117649, 125000, 132651, 140608, 148877, 157464, 166375, 175616, 185193, 195112, 205379, 216000, 226981, 238328, 250047, 262144, 274625, 287496, 300763, 314432, 328509, 343000, 357911, 373248, 389017, 405224, 421875, 438976, 456533, 474552, 493039, 512000, 531441, 551368, 571787, 592704, 614125, 636056, 658503, 681472, 704969, 729000, 753571, 778688, 804357, 830584, 857375, 884736, 912673, 941192, 970299, 1000000, }; uint32_t mediumSlowExpTable[] = { 0, 9, 57, 96, 135, 179, 236, 314, 419, 560, 742, 973, 1261, 1612, 2035, 2535, 3120, 3798, 4575, 5460, 6458, 7577, 8825, 10208, 11735, 13411, 15244, 17242, 19411, 21760, 24294, 27021, 29949, 33084, 36435, 40007, 43808, 47846, 52127, 56660, 61450, 66505, 71833, 77440, 83335, 89523, 96012, 102810, 109923, 117360, 125126, 133229, 141677, 150476, 159635, 169159, 179056, 189334, 199999, 211060, 222522, 234393, 246681, 259392, 272535, 286115, 300140, 314618, 329555, 344960, 360838, 377197, 394045, 411388, 429235, 447591, 466464, 485862, 505791, 526260, 547274, 568841, 590969, 613664, 636935, 660787, 685228, 710266, 735907, 762160, 789030, 816525, 844653, 873420, 902835, 932903, 963632, 995030, 1027103, 1059860, }; uint32_t fastExpTable[] = { 0, 6, 21, 51, 100, 172, 274, 409, 583, 800, 1064, 1382, 1757, 2195, 2700, 3276, 3930, 4665, 5487, 6400, 7408, 8518, 9733, 11059, 12500, 14060, 15746, 17561, 19511, 21600, 23832, 26214, 28749, 31443, 34300, 37324, 40522, 43897, 47455, 51200, 55136, 59270, 63605, 68147, 72900, 77868, 83058, 88473, 94119, 100000, 106120, 112486, 119101, 125971, 133100, 140492, 148154, 156089, 164303, 172800, 181584, 190662, 200037, 209715, 219700, 229996, 240610, 251545, 262807, 274400, 286328, 298598, 311213, 324179, 337500, 351180, 365226, 379641, 394431, 409600, 425152, 441094, 457429, 474163, 491300, 508844, 526802, 545177, 563975, 583200, 602856, 622950, 643485, 664467, 685900, 707788, 730138, 752953, 776239, 800000, }; uint32_t slowExpTable[] = { 0, 10, 33, 80, 156, 270, 428, 640, 911, 1250, 1663, 2160, 2746, 3430, 4218, 5120, 6141, 7290, 8573, 10000, 11576, 13310, 15208, 17280, 19531, 21970, 24603, 27440, 30486, 33750, 37238, 40960, 44921, 49130, 53593, 58320, 63316, 68590, 74148, 80000, 86151, 92610, 99383, 106480, 113906, 121670, 129778, 138240, 147061, 156250, 165813, 175760, 186096, 196830, 207968, 219520, 231491, 243890, 256723, 270000, 283726, 297910, 312558, 327680, 343281, 359370, 375953, 393040, 410636, 428750, 447388, 466560, 486271, 506530, 527343, 548720, 570666, 593190, 616298, 640000, 664301, 689210, 714733, 740880, 767656, 795070, 823128, 851840, 881211, 911250, 941963, 973360, 1005446, 1038230, 1071718, 1105920, 1140841, 1176490, 1212873, 1250000, }; uint8_t* convertGBColorPaletteToRGB24(uint16_t palette[4]) { static uint8_t result[12]; uint16_t work; uint8_t *cur = result; for(uint8_t i=0; i < 4; ++i) { // format is 15 bit BGR (https://www.huderlem.com/demos/gameboypalette.html) const uint8_t b5 = (palette[i] >> 10) & 0x1F; const uint8_t g5 = (palette[i] >> 5) & 0x1F; const uint8_t r5 = palette[i] & 0x1F; work = (static_cast(r5) * 255) / 31; (*cur) = (uint8_t)work; ++cur; work = (static_cast(g5) * 255) / 31; (*cur) = (uint8_t)work; ++cur; work = (static_cast(b5) * 255) / 31; (*cur) = (uint8_t)work; ++cur; } return result; } uint8_t getStatIV(PokeStat type, const uint8_t iv_data[2]) { // https://bulbapedia.bulbagarden.net/wiki/Individual_values switch(type) { case PokeStat::ATK: return (iv_data[0] >> 4); case PokeStat::DEF: return (iv_data[0] & 0xF); case PokeStat::SPEED: return (iv_data[1] >> 4); case PokeStat::SPECIAL: case PokeStat::SPECIAL_ATK: case PokeStat::SPECIAL_DEF: return (iv_data[1] & 0xF); case PokeStat::HP: // HP is based on the least significant bit of the other 4 stats return (((getStatIV(PokeStat::ATK, iv_data) & 0x1) << 3) | ((getStatIV(PokeStat::DEF, iv_data) & 0x1) << 2) | ((getStatIV(PokeStat::SPEED, iv_data) & 0x1) << 1) | ((getStatIV(PokeStat::SPECIAL, iv_data) & 0x1))); default: return 0; } } // https://bulbapedia.bulbagarden.net/wiki/Stat // Note that there may be a difference between the stats in the Gen1TrainerPokemon stats field and the ones calculated here // This is because stats are being recalculated when withdrawing the pokemon from the pc. // look into "The box trick" // If you store your pokemon in an ingame pc and take it out again, you'll see that now the stats match with the ones calculated here. uint16_t calculatePokeStat(PokeStat type, uint16_t baseVal, uint8_t stat_iv, uint16_t stat_exp, uint8_t level) { uint16_t result; // Terminology: For Gen 1 & 2, IVs are also referred to as Determinant Values (DVs) // first part: The fraction only // this part is common for all PokeStats including HP const uint16_t ivPart = (baseVal + stat_iv) * 2; const uint16_t statExpPart = static_cast(ceil(sqrt(stat_exp)) / 4); result = ((ivPart + statExpPart) * level) / 100; if(type == PokeStat::HP) { // now add the second part of the formula, which is specific for HP result += level + 10; } else { // now add the second part of the formula specific to all stats that aren't HP. result += 5; } return static_cast(result); } uint32_t *getExpTableForGrowthRate(uint8_t growthRate) { uint32_t *expTable; switch (growthRate) { case GRW_FAST: expTable = fastExpTable; break; case GRW_MEDIUM_FAST: expTable = mediumFastExpTable; break; case GRW_MEDIUM_SLOW: expTable = mediumSlowExpTable; break; case GRW_SLOW: expTable = slowExpTable; break; default: expTable = 0; break; } return expTable; } uint32_t getExpNeededForLevel(uint8_t level, uint8_t growthRate) { uint32_t *expTable; if(level < 1 || level > 100) { return 0; } expTable = getExpTableForGrowthRate(growthRate); return (expTable) ? expTable[level - 1] : 0; } uint8_t getLevelForExp(uint32_t exp, uint8_t growthRate) { const uint32_t *expTable = getExpTableForGrowthRate(growthRate); if (!expTable) { return 1; } for (uint8_t i = 1; i < 100; ++i) { // to check which level we have, we need to find the first entry that is more than the exp we have // when we find that, i would refer to the next level, not the current one. // However, since we're doing an array index, i is zero-based, whereas the pkmn level is 1 -based. // so it turns out that we can just return i here instead of subtracting by 1 if (exp < expTable[i]) { return i; } } return 100; } void printGameboyCartridgeHeader(const GameboyCartridgeHeader& h) { printf("Entry:\t%hhx %hhx %hhx %hhx\n", h.entry[0], h.entry[1], h.entry[2], h.entry[3]); printf("Title:\t%s\n", h.title); printf("Manufacturer code:\t%s\n", h.manufacturer_code); printf("CGB flag:\t%hhx\n", h.CGB_flag); printf("New Licensee code:\t%hhx %hhx\n", h.new_licensee_code[0], h.new_licensee_code[1]); printf("SGB flag:\t%hhx\n", h.SGB_flag); printf("Cartridge type:\t%hhx\n", h.cartridge_type); printf("Rom size:\t%hhx\n", h.rom_size); printf("Ram size:\t%hhx\n", h.ram_size); printf("Destination code:\t%hhx\n", h.destination_code); printf("Old Licensee code:\t%hhx\n", h.old_licensee_code); printf("Mask Rom version:\t%hhx\n", h.mask_rom_version_number); printf("Header checksum:\t%hhx\n", h.header_checksum); printf("Global checksum: \t%hhx %hhx\n", h.global_checksum[0], h.global_checksum[1]); }