DataDump Pokedex entries, (0x0805C8B4) with preproc support, and english dex glyphs (0x08092FA0) (#132)

* text graphics

* add dex preproc, data dump

* remove temp test data from rom.s

* cleanup temp files

* remove dump of 086AE5EC for focus

* correct file reference

* utf handling.

* add second colon

* Align dex entry structs to 4 bytes

* Fix dex text glyphs gfx:

---------

Co-authored-by: Marcus Huderle <huderlem@gmail.com>
This commit is contained in:
Retnuhytnuob 2025-07-13 08:18:51 -05:00 committed by GitHub
parent 32cd26024c
commit 4c8d5a9871
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 2655 additions and 21 deletions

2460
data/pokedex_entries/dex.inc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -740,8 +740,9 @@ gPokedexStateFuncs:: @ 0x0805C880
.4byte Pokedex_ReturnToTitle @ POKEDEX_STATE_RETURN_TO_TITLE
gPokedexEntries:: @ 0x0805C8B4
.incbin "baserom.gba", 0x5C8B4, 0x1CA0C
.include "data/pokedex_entries/dex.inc"
.align 2, 0
gFieldSelectStateFuncs:: @ 0x080792C0
.4byte LoadFieldSelectGraphics
.4byte sub_8C7C
@ -976,11 +977,8 @@ gPokedexSprites_Gfx:: @ 0x08089B60
.incbin "baserom.gba", 0x90760, 0x20
gUnknown_08090780:: @ 0x08090780
.incbin "baserom.gba", 0x90780, 0x2820
gUnknown_08092FA0:: @ 0x08092FA0
.incbin "baserom.gba", 0x92FA0, 0x1800
gPokedexTextGlyphs_Gfx:: @ 0x08090780
.incbin "graphics/pokedex/text_glyphs.4bpp"
gUnknown_080947A0:: @ 0x080947A0
.incbin "baserom.gba", 0x947A0, 0x1000

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -12,3 +12,6 @@ $(MON_PORTRAITS_DIR)/%.4bpp: $(MON_PORTRAITS_DIR)/%.png
$(MON_HATCH_SPRITES_DIR)/%.4bpp: $(MON_HATCH_SPRITES_DIR)/%.png
$(GFX) $< $@ -pinball-hatch-sprite
graphics/pokedex/text_glyphs.4bpp: graphics/pokedex/text_glyphs.png
$(GFX) $< $@ -num_tiles 513

View File

@ -17,5 +17,6 @@
#define POKEMON_NAME_LENGTH 10
#define POKEMON_HEIGHT_WEIGHT_TEXT_LENGTH 9
#define POKEMON_CATEGORY_NAME_LENGTH 11
#define POKEMON_DEX_LINE_LENGTH 42
#endif // GUARD_CONSTANTS_GLOBAL_H

View File

@ -76,12 +76,15 @@ extern const s16 gUnknown_086A6356[];
extern const u16 gUnknown_086A5EE2[][51];
extern const s16 gUnknown_086A6014[][51];
extern const u16 gUnknown_086A5E12[][4];
extern const u8 gUnknown_08090780[];
extern u8 gUnknown_08092FA0[]; // needs const
extern s16 gUnknown_086A64F0[];
extern u8 *gMonPortraitGroupGfx[];
extern u8 *gMonPortraitGroupPals[];
// The japanese and english text glyphs are sourced from the same blob of tile graphics, and
// each glyph is two tiles high.
#define ENGLISH_GLYPHS_START 0x2820
extern const u8 gPokedexTextGlyphs_Gfx[];
struct PokedexEntry
{
/*0x00*/ u16 dexNum[DEX_NUM_DIGITS];
@ -90,7 +93,7 @@ struct PokedexEntry
/*0x2C*/ s16 category[POKEMON_CATEGORY_NAME_LENGTH];
// The dex description has 2 pages with 3 lines each. Each line
// is 42 characters long.
/*0x42*/ s16 description[2 * 3 * 42];
/*0x42*/ s16 description[2 * 3 * POKEMON_DEX_LINE_LENGTH];
}; /* size=0x23C */
extern const struct PokedexEntry gPokedexEntries[];
@ -1736,8 +1739,8 @@ static void PrintSelectedMonDexNum(s16 species)
if (var2 == 0)
var2 = 4;
DmaCopy16(3, &gUnknown_08090780[var1], gUnknown_0202BE30, 0x20);
DmaCopy16(3, &gUnknown_08090780[var1 + 0x400], gUnknown_0201B130, 0x20);
DmaCopy16(3, &gPokedexTextGlyphs_Gfx[var1], gUnknown_0202BE30, 0x20);
DmaCopy16(3, &gPokedexTextGlyphs_Gfx[var1 + 0x400], gUnknown_0201B130, 0x20);
sub_71DC(var2, var0, 0);
var0 += var2;
}
@ -1749,7 +1752,7 @@ static void PrintSelectedMonDexNum(s16 species)
else
{
for (i = 0; i < 10; i++)
sub_10708(gUnknown_08092FA0, (void *)0x06004C00 + i * 0x20, 1, 2);
sub_10708((void *)&gPokedexTextGlyphs_Gfx[ENGLISH_GLYPHS_START], (void *)0x06004C00 + i * 0x20, 1, 2);
}
if (gPokedexFlags[species] == SPECIES_SEEN || gPokedexFlags[species] > SPECIES_SHARED)
@ -1761,8 +1764,8 @@ static void PrintSelectedMonDexNum(s16 species)
if (var2 == 0)
var2 = 6;
DmaCopy16(3, &gUnknown_08090780[var1], gUnknown_0202BE30, 0x20);
DmaCopy16(3, &gUnknown_08090780[0x400 + var1], gUnknown_0201B130, 0x20);
DmaCopy16(3, &gPokedexTextGlyphs_Gfx[var1], gUnknown_0202BE30, 0x20);
DmaCopy16(3, &gPokedexTextGlyphs_Gfx[0x400 + var1], gUnknown_0201B130, 0x20);
sub_71DC(var2, var0, 0);
var0 += var2;
}
@ -1773,7 +1776,7 @@ static void PrintSelectedMonDexNum(s16 species)
else
{
for (i = 0; i < 9; i++)
sub_10708(gUnknown_08092FA0, (void *)0x06004D00 + i * 0x20, 1, 2);
sub_10708((void *)&gPokedexTextGlyphs_Gfx[ENGLISH_GLYPHS_START], (void *)0x06004D00 + i * 0x20, 1, 2);
}
if (gPokedexFlags[species] == SPECIES_CAUGHT)
@ -1860,6 +1863,10 @@ void PrintDexNumbersFromListPosition(s16 listPosition)
{
if (gPokedexFlags[listPosition + i] > SPECIES_UNSEEN)
{
//This manually builds the tiles needed, for kerning reasons.
//First 3 bytes point to a tile glyph pair (with an upper and lower half) and
//the 4th byte is the width needed for that glyph, with the 'space between' included.
//The 'space' character is 4 px wide.
for (j = 0; j < POKEMON_NAME_LENGTH; j++)
{
// These don't use listPosition for some reason, despite being the only value passed
@ -1868,8 +1875,8 @@ void PrintDexNumbersFromListPosition(s16 listPosition)
if (var2 == 0)
var2 = 4;
DmaCopy16(3, &gUnknown_08090780[var1], gUnknown_0202BE30, 0x20);
DmaCopy16(3, &gUnknown_08090780[0x400 + var1], gUnknown_0201B130, 0x20);
DmaCopy16(3, &gPokedexTextGlyphs_Gfx[var1], gUnknown_0202BE30, 0x20);
DmaCopy16(3, &gPokedexTextGlyphs_Gfx[0x400 + var1], gUnknown_0201B130, 0x20);
sub_71DC(var2, var0, 0);
var0 += var2;
}
@ -1881,9 +1888,9 @@ void PrintDexNumbersFromListPosition(s16 listPosition)
else
{
for (j = 0; j < 7; j++)
sub_10708(gUnknown_08092FA0, (void *)0x06000000 + gUnknown_086A64F0[i] + j * 0x20, 1, 2);
sub_10708((void *)&gPokedexTextGlyphs_Gfx[ENGLISH_GLYPHS_START], (void *)0x06000000 + gUnknown_086A64F0[i] + j * 0x20, 1, 2);
sub_10708((void *)gUnknown_08090780, (void *)0x06000000 + gUnknown_086A64F0[i] + j * 0x20, 1, 2);
sub_10708((void *)gPokedexTextGlyphs_Gfx, (void *)0x06000000 + gUnknown_086A64F0[i] + j * 0x20, 1, 2);
}
}
}
@ -1945,8 +1952,8 @@ void sub_70E0(s16 species, u32 page)
if (var2 == 0)
var2 = 4;
DmaCopy16(3, &gUnknown_08090780[var1], gUnknown_0202BE30, 0x20);
DmaCopy16(3, &gUnknown_08090780[0x400 + var1], gUnknown_0201B130, 0x20);
DmaCopy16(3, &gPokedexTextGlyphs_Gfx[var1], gUnknown_0202BE30, 0x20);
DmaCopy16(3, &gPokedexTextGlyphs_Gfx[0x400 + var1], gUnknown_0201B130, 0x20);
sub_71DC(var2, var0, i);
var0 += var2;
}

View File

@ -171,6 +171,12 @@ Directive AsmFile::GetDirective()
return Directive::String;
else if (CheckForDirective(".braille"))
return Directive::Braille;
else if (CheckForDirective(".dexName"))
return Directive::DexName;
else if (CheckForDirective(".dexCategory"))
return Directive::DexCategory;
else if (CheckForDirective(".dexText"))
return Directive::DexText;
else
return Directive::Unknown;
}
@ -369,6 +375,126 @@ int AsmFile::ReadBraille(unsigned char* s)
return length;
}
int AsmFile::ReadDexString(unsigned short* s, uint8_t targetLength, bool padLeft = false)
{
// Sample dexEncoding map
static std::map<std::string, unsigned short> dexEncoding =
{
{ " ", 0x0000 },
{ "-", 0x2826 }, { "", 0x2846 }, { "", 0x2866 },
{ "0", 0x2886 }, { "1", 0x28A3 }, { "2", 0x28C6 }, { "3", 0x28E6 },
{ "4", 0x2906 }, { "5", 0x2926 }, { "6", 0x2946 }, { "7", 0x2966 },
{ "8", 0x2986 }, { "9", 0x29A6 }, { "", 0x29C6 },
{ "A", 0x29E6 }, { "B", 0x2A06 }, { "C", 0x2A26 }, { "D", 0x2A46 },
{ "E", 0x2A66 }, { "F", 0x2A86 }, { "G", 0x2AA6 }, { "H", 0x2AC6 },
{ "I", 0x2AE2 }, { "J", 0x2B06 }, { "K", 0x2B26 }, { "L", 0x2B46 },
{ "M", 0x2B66 }, { "N", 0x2B86 }, { "O", 0x2BA6 }, { "P", 0x2BC6 },
{ "Q", 0x2BE6 }, { "R", 0x3006 }, { "S", 0x3026 }, { "T", 0x3046 },
{ "U", 0x3066 }, { "V", 0x3086 }, { "W", 0x30A6 }, { "X", 0x30C6 },
{ "Y", 0x30E6 }, { "Z", 0x3106 },
{ "a", 0x3126 }, { "b", 0x3146 }, { "c", 0x3166 }, { "d", 0x3186 },
{ "e", 0x31A6 }, { "f", 0x31C6 }, { "g", 0x31E6 }, { "h", 0x3206 },
{ "i", 0x3222 }, { "j", 0x3246 }, { "k", 0x3266 }, { "l", 0x3283 },
{ "m", 0x32A6 }, { "n", 0x32C5 }, { "o", 0x32E6 }, { "p", 0x3306 },
{ "q", 0x3326 }, { "r", 0x3345 }, { "s", 0x3366 }, { "t", 0x3386 },
{ "u", 0x33A6 }, { "v", 0x33C6 }, { "w", 0x33E6 }, { "x", 0x3806 },
{ "y", 0x3826 }, { "z", 0x3846 },
{ "ˎ", 0x3866 }, { "˳", 0x3886 }, { "", 0x38A6 }, { "", 0x38C6 },
{ "×", 0x38E6 }, { "", 0x3926 }, { "", 0x3906 }, { "!", 0x3942 },
{ "?", 0x3968 }, { ":", 0x3984 }, { ";", 0x39A4 }, { ",", 0x39C4 },
{ ".", 0x39E4 }, { "", 0x3A04 }, { "(", 0x3A26 }, { ")", 0x3A46 },
{ "~", 0x3A68 }, { "", 0x3A88 }, { "é", 0x3AA6 }, { "`", 0x3AC3 },
{ "´", 0x3AE4 }, { "#", 0x3B06 },
};
SkipWhitespace();
if (m_buffer[m_pos] != '"')
RaiseError("expected dex string literal");
m_pos++;
std::vector<unsigned short> temp;
while (m_buffer[m_pos] != '"')
{
if (temp.size() == targetLength)
RaiseError("mapped string longer than %d entries", targetLength);
std::string c;
unsigned char first = static_cast<unsigned char>(m_buffer[m_pos]);
if (first < 0x80) {
// ASCII
c += m_buffer[m_pos++];
}
else if ((first & 0xE0) == 0xC0) {
c += m_buffer[m_pos++];
c += m_buffer[m_pos++];
}
else if ((first & 0xF0) == 0xE0) {
c += m_buffer[m_pos++];
c += m_buffer[m_pos++];
c += m_buffer[m_pos++];
}
else if ((first & 0xF8) == 0xF0) {
c += m_buffer[m_pos++];
c += m_buffer[m_pos++];
c += m_buffer[m_pos++];
c += m_buffer[m_pos++];
}
else {
RaiseError("invalid UTF-8 sequence at position %d", m_pos);
}
if (dexEncoding.count(c) == 0)
{
if (c.size() == 1 && IsAsciiPrintable(c[0]))
RaiseError("character '%c' not valid in dex string", c);
else
{
std::string hex;
char hexStr[5];
for (unsigned short i = 0; i < c.size(); i++) {
std::snprintf(hexStr, sizeof(hexStr), "\\x%02X", static_cast<unsigned char>(c[i]));
hex += hexStr;
}
RaiseError("character '%s' not valid in dex string", hex.c_str());
}
}
temp.push_back(dexEncoding[c]);
}
m_pos++; // Past closing quote
ExpectEmptyRestOfLine();
// Padding logic
int actualLength = static_cast<int>(temp.size());
int padCount = targetLength - actualLength;
// Fill output with padding + data
int pos = 0;
if (padLeft)
{
for (int i = 0; i < padCount; ++i) s[pos++] = 0x0000;
for (unsigned short val : temp) s[pos++] = val;
}
else
{
for (unsigned short val : temp) s[pos++] = val;
for (int i = 0; i < padCount; ++i) s[pos++] = 0x0000;
}
return targetLength;
}
// If we're at a comma, consumes it.
// Returns whether a comma was found.
bool AsmFile::ConsumeComma()

View File

@ -31,6 +31,9 @@ enum class Directive
Include,
String,
Braille,
DexName,
DexCategory,
DexText,
Unknown
};
@ -46,6 +49,7 @@ public:
std::string ReadPath();
int ReadString(unsigned char* s);
int ReadBraille(unsigned char* s);
int ReadDexString(unsigned short* s, uint8_t targetLength, bool padLeft);
bool IsAtEnd();
void OutputLine();
void OutputLocation();

View File

@ -24,6 +24,7 @@
#include "asm_file.h"
#include "c_file.h"
#include "charmap.h"
#include "../../include/constants/global.h"
Charmap* g_charmap;
@ -43,6 +44,22 @@ void PrintAsmBytes(unsigned char *s, int length)
}
}
void PrintAsmHalfwords(unsigned short* s, int length)
{
if (length > 0)
{
std::printf("\t.2byte ");
for (int i = 0; i < length; i++)
{
std::printf("0x%04X", s[i]);
if (i < length - 1)
std::printf(", ");
}
std::putchar('\n');
}
}
void PreprocAsmFile(std::string filename)
{
std::stack<AsmFile> stack;
@ -83,6 +100,24 @@ void PreprocAsmFile(std::string filename)
PrintAsmBytes(s, length);
break;
}
case Directive::DexName:{
unsigned short s[POKEMON_NAME_LENGTH];
int length = stack.top().ReadDexString(s, POKEMON_NAME_LENGTH, false);
PrintAsmHalfwords(s, length);
break;
}
case Directive::DexCategory:{
unsigned short s[POKEMON_CATEGORY_NAME_LENGTH];
int length = stack.top().ReadDexString(s, POKEMON_CATEGORY_NAME_LENGTH, true);
PrintAsmHalfwords(s, length);
break;
}
case Directive::DexText:{
unsigned short s[POKEMON_DEX_LINE_LENGTH];
int length = stack.top().ReadDexString(s, POKEMON_DEX_LINE_LENGTH, false);
PrintAsmHalfwords(s, length);
break;
}
case Directive::Unknown:
{
std::string globalLabel = stack.top().GetGlobalLabel();