diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2017-09-10 17:16:52 -0400 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2017-09-10 17:16:52 -0400 |
commit | 1d82e3affd42c2336702af4a644baa8eec249ead (patch) | |
tree | aeea397863a7d2014bd960a9bd3ba090f841bcce | |
parent | 0882d1020d75bbddc8e8fbe30aed435e8814988a (diff) | |
download | gen3uploader-1d82e3affd42c2336702af4a644baa8eec249ead.tar.gz gen3uploader-1d82e3affd42c2336702af4a644baa8eec249ead.tar.bz2 gen3uploader-1d82e3affd42c2336702af4a644baa8eec249ead.zip |
Increased stability and added support for non-English names
The GameCube side of the program now can convert from the propietary character set to UTF-8. This is useful for representing names of Pokémon and players in a neutral way. The propietary character set is mostly compatible between the six languages supported by the games (as in, the hiragana and katakana characters unique to Japanese occupy spaces not used by the other languages for names, as do the letters with umlauts unique to German). However, six codepoints differ between the Japanese and non-Japanese character sets, and an additional two differ even amongst the non-Japanese sets. Because of this, the function that converts to UTF-8 takes a language as a parameter, and uses the correct characters for that language. From there, the behavior of this function differs slightly to that of the games. In the non-Japanese games, the Japanese encoding is used if the Pokémon in question originated in a Japanese game, and the non-Japanese encoding (disregarding the regional differences in the two codepoints mentioned earlier) otherwise. In the Japanese games, the Japanese encoding is used regardless of the Pokémon's origin. The decoding function I wrote always uses the character set corresponding to the language of the Pokémon's origin, because that most accurately represents the name given to it, and will not change just because the Pokémon was traded to a different game. The character set used for the name of the player is the one corresponding to the language of the cartridge. Additionally, a number of changes were made to the communication protocol between the GameCube and the GBA that appear to have dramatically increased stability. The most significant of these is likely that the transfer delay was increased tenfold. This causes the multiboot image to take slightly longer to download to the GBA, but the difference is not large enough to outweigh the benefits of the increased stability.
-rw-r--r-- | gba/source/link.c | 15 | ||||
-rw-r--r-- | gba/source/main.c | 17 | ||||
-rw-r--r-- | gba/source/serialize.c | 12 | ||||
-rw-r--r-- | gba/source/serialize.h | 3 | ||||
-rw-r--r-- | include/pokemon.h | 13 | ||||
-rw-r--r-- | source/encoding.c | 398 | ||||
-rw-r--r-- | source/encoding.h | 7 | ||||
-rw-r--r-- | source/link.c | 17 | ||||
-rw-r--r-- | source/main.c | 51 |
9 files changed, 448 insertions, 85 deletions
diff --git a/gba/source/link.c b/gba/source/link.c index 26443c8..05e4732 100644 --- a/gba/source/link.c +++ b/gba/source/link.c | |||
@@ -12,9 +12,9 @@ | |||
12 | 12 | ||
13 | void initializeLink() | 13 | void initializeLink() |
14 | { | 14 | { |
15 | REG_HS_CTRL |= JOY_RW; | ||
16 | REG_JOYTR = 0; | 15 | REG_JOYTR = 0; |
17 | while ((REG_HS_CTRL & JOY_WRITE) == 0); | 16 | REG_HS_CTRL |= JOY_RW; |
17 | while ((REG_HS_CTRL & JOY_READ) == 0); | ||
18 | REG_HS_CTRL |= JOY_RW; | 18 | REG_HS_CTRL |= JOY_RW; |
19 | } | 19 | } |
20 | 20 | ||
@@ -22,29 +22,22 @@ void waitForAck() | |||
22 | { | 22 | { |
23 | while ((REG_HS_CTRL & JOY_WRITE) == 0); | 23 | while ((REG_HS_CTRL & JOY_WRITE) == 0); |
24 | REG_HS_CTRL |= JOY_RW; | 24 | REG_HS_CTRL |= JOY_RW; |
25 | REG_JOYTR = 0; | ||
26 | while ((REG_HS_CTRL & JOY_WRITE) == 0); | ||
27 | REG_HS_CTRL |= JOY_RW; | ||
28 | } | 25 | } |
29 | 26 | ||
30 | u32 waitForResponse() | 27 | u32 waitForResponse() |
31 | { | 28 | { |
32 | u32 val; | 29 | u32 val; |
33 | 30 | ||
34 | REG_JOYTR = 1; | ||
35 | while ((REG_HS_CTRL & JOY_WRITE) == 0); | ||
36 | val = REG_JOYRE; | ||
37 | REG_HS_CTRL |= JOY_RW; | ||
38 | REG_JOYTR = 0; | ||
39 | while ((REG_HS_CTRL & JOY_WRITE) == 0); | 31 | while ((REG_HS_CTRL & JOY_WRITE) == 0); |
40 | REG_HS_CTRL |= JOY_RW; | 32 | REG_HS_CTRL |= JOY_RW; |
33 | val = REG_JOYRE; | ||
41 | 34 | ||
42 | return val; | 35 | return val; |
43 | } | 36 | } |
44 | 37 | ||
45 | void sendS32(s32 val) | 38 | void sendS32(s32 val) |
46 | { | 39 | { |
47 | REG_JOYTR = val; | 40 | sendU32(val); |
48 | } | 41 | } |
49 | 42 | ||
50 | void sendU32(u32 val) | 43 | void sendU32(u32 val) |
diff --git a/gba/source/main.c b/gba/source/main.c index aeb05af..0934e91 100644 --- a/gba/source/main.c +++ b/gba/source/main.c | |||
@@ -113,6 +113,21 @@ int main(void) | |||
113 | sendU32(trainerIdNum); | 113 | sendU32(trainerIdNum); |
114 | waitForAck(); | 114 | waitForAck(); |
115 | 115 | ||
116 | // Send cart language. | ||
117 | u8 cartLang = 0; | ||
118 | switch (*(u8*)(0x80000AF)) | ||
119 | { | ||
120 | case 'J': cartLang = Japanese; break; | ||
121 | case 'E': cartLang = English; break; | ||
122 | case 'F': cartLang = French; break; | ||
123 | case 'I': cartLang = Italian; break; | ||
124 | case 'D': cartLang = German; break; | ||
125 | case 'S': cartLang = Spanish; break; | ||
126 | } | ||
127 | |||
128 | sendU32(cartLang); | ||
129 | waitForAck(); | ||
130 | |||
116 | // Does the player want to import this game? | 131 | // Does the player want to import this game? |
117 | if (waitForResponse() == 0) | 132 | if (waitForResponse() == 0) |
118 | { | 133 | { |
@@ -193,7 +208,7 @@ int main(void) | |||
193 | 208 | ||
194 | struct PokemonIntermediate pki; | 209 | struct PokemonIntermediate pki; |
195 | 210 | ||
196 | PokemonIntermediateInit(&pki, bpkm, trainerIdNum, secretIdNum, &gameData); | 211 | PokemonIntermediateInit(&pki, bpkm, trainerIdNum, secretIdNum); |
197 | PokemonIntermediateStream(&pki); | 212 | PokemonIntermediateStream(&pki); |
198 | } | 213 | } |
199 | } | 214 | } |
diff --git a/gba/source/serialize.c b/gba/source/serialize.c index 4a80bdf..c5e8570 100644 --- a/gba/source/serialize.c +++ b/gba/source/serialize.c | |||
@@ -11,14 +11,6 @@ | |||
11 | #include "exptables.h" | 11 | #include "exptables.h" |
12 | #include "dexorder.h" | 12 | #include "dexorder.h" |
13 | 13 | ||
14 | enum Stat { | ||
15 | StatAttack, | ||
16 | StatDefense, | ||
17 | StatSpeed, | ||
18 | StatSpAttack, | ||
19 | StatSpDefense | ||
20 | }; | ||
21 | |||
22 | u32 CalculateStat( | 14 | u32 CalculateStat( |
23 | u8 base, | 15 | u8 base, |
24 | u32 iv, | 16 | u32 iv, |
@@ -50,8 +42,7 @@ void PokemonIntermediateInit( | |||
50 | struct PokemonIntermediate* pki, | 42 | struct PokemonIntermediate* pki, |
51 | struct BoxPokemon* bpkm, | 43 | struct BoxPokemon* bpkm, |
52 | u16 trainerId, | 44 | u16 trainerId, |
53 | u16 secretId, | 45 | u16 secretId) |
54 | const struct GameData* gameData) | ||
55 | { | 46 | { |
56 | DecryptBoxPokemon(bpkm); | 47 | DecryptBoxPokemon(bpkm); |
57 | 48 | ||
@@ -88,6 +79,7 @@ void PokemonIntermediateInit( | |||
88 | pki->metLocation = sub3->metLocation; | 79 | pki->metLocation = sub3->metLocation; |
89 | pki->pokeball = sub3->pokeball; | 80 | pki->pokeball = sub3->pokeball; |
90 | pki->altAbility = sub3->altAbility; | 81 | pki->altAbility = sub3->altAbility; |
82 | pki->language = bpkm->language & 3; | ||
91 | 83 | ||
92 | // Derive nature from the personality value. | 84 | // Derive nature from the personality value. |
93 | pki->nature = (bpkm->personality % 25); | 85 | pki->nature = (bpkm->personality % 25); |
diff --git a/gba/source/serialize.h b/gba/source/serialize.h index 38a4d6b..7fcae0f 100644 --- a/gba/source/serialize.h +++ b/gba/source/serialize.h | |||
@@ -17,8 +17,7 @@ void PokemonIntermediateInit( | |||
17 | struct PokemonIntermediate* pki, | 17 | struct PokemonIntermediate* pki, |
18 | struct BoxPokemon* bpkm, | 18 | struct BoxPokemon* bpkm, |
19 | u16 trainerId, | 19 | u16 trainerId, |
20 | u16 secretId, | 20 | u16 secretId); |
21 | const struct GameData* gameData); | ||
22 | 21 | ||
23 | void PokemonIntermediateStream(struct PokemonIntermediate* pki); | 22 | void PokemonIntermediateStream(struct PokemonIntermediate* pki); |
24 | 23 | ||
diff --git a/include/pokemon.h b/include/pokemon.h index 80e7ee7..d8a7265 100644 --- a/include/pokemon.h +++ b/include/pokemon.h | |||
@@ -11,6 +11,15 @@ | |||
11 | #define OT_NAME_LENGTH 7 | 11 | #define OT_NAME_LENGTH 7 |
12 | #define TILE_SIZE_4BPP 32 | 12 | #define TILE_SIZE_4BPP 32 |
13 | 13 | ||
14 | enum PokemonLanguage { | ||
15 | Japanese = 1, | ||
16 | English = 2, | ||
17 | French = 3, | ||
18 | Italian = 4, | ||
19 | German = 5, | ||
20 | Spanish = 7 | ||
21 | }; | ||
22 | |||
14 | struct PokemonIntermediate { | 23 | struct PokemonIntermediate { |
15 | u32 otId; | 24 | u32 otId; |
16 | u32 experience; | 25 | u32 experience; |
@@ -35,7 +44,9 @@ struct PokemonIntermediate { | |||
35 | u8 nickname[POKEMON_NAME_LENGTH]; | 44 | u8 nickname[POKEMON_NAME_LENGTH]; |
36 | u8 otName[OT_NAME_LENGTH]; | 45 | u8 otName[OT_NAME_LENGTH]; |
37 | u8 pokeball; | 46 | u8 pokeball; |
38 | u8 altAbility; // waste of space but nothing to pack it with | 47 | u8 language:3; |
48 | u8 altAbility:1; | ||
49 | u8 filler:4; // waste of space but nothing to pack it with | ||
39 | 50 | ||
40 | // the following values are generated from the personality value. | 51 | // the following values are generated from the personality value. |
41 | u8 nature:6; | 52 | u8 nature:6; |
diff --git a/source/encoding.c b/source/encoding.c index 0be1e0b..0a44800 100644 --- a/source/encoding.c +++ b/source/encoding.c | |||
@@ -9,15 +9,397 @@ | |||
9 | */ | 9 | */ |
10 | #include "encoding.h" | 10 | #include "encoding.h" |
11 | 11 | ||
12 | const char charmap[] = { | 12 | const char* charmap[] = { |
13 | ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '?', '.', '-', ' ', | 13 | " ", // space |
14 | ' ', '\"', '\"', '\'', '\'', '*', '*', ' ', ',', ' ', '/', 'A', 'B', 'C', 'D', 'E', | 14 | "\xe3\x81\x82", // hiragana letter a |
15 | 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', | 15 | "\xe3\x81\x84", // hiragana letter i |
16 | 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', | 16 | "\xe3\x81\x86", // hiragana letter u |
17 | 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ' ' | 17 | "\xe3\x81\x88", // hiragana letter e |
18 | "\xe3\x81\x8a", // hiragana letter o | ||
19 | "\xe3\x81\x8b", // hiragana letter ka | ||
20 | "\xe3\x81\x8d", // hiragana letter ki | ||
21 | "\xe3\x81\x8f", // hiragana letter ku | ||
22 | "\xe3\x81\x91", // hiragana letter ke | ||
23 | "\xe3\x81\x93", // hiragana letter ko | ||
24 | "\xe3\x81\x95", // hiragana letter sa | ||
25 | "\xe3\x81\x97", // hiragana letter si | ||
26 | "\xe3\x81\x99", // hiragana letter su | ||
27 | "\xe3\x81\x9b", // hiragana letter se | ||
28 | "\xe3\x81\x9d", // hiragana letter so | ||
29 | "\xe3\x81\x9f", // hiragana letter ta | ||
30 | "\xe3\x81\xa1", // hiragana letter ti | ||
31 | "\xe3\x81\xa4", // hiragana letter tu | ||
32 | "\xe3\x81\xa6", // hiragana letter te | ||
33 | "\xe3\x81\xa8", // hiragana letter to | ||
34 | "\xe3\x81\xaa", // hiragana letter na | ||
35 | "\xe3\x81\xab", // hiragana letter ni | ||
36 | "\xe3\x81\xac", // hiragana letter nu | ||
37 | "\xe3\x81\xad", // hiragana letter ne | ||
38 | "\xe3\x81\xae", // hiragana letter no | ||
39 | "\xe3\x81\xaf", // hiragana letter ha | ||
40 | "\xe3\x81\xb2", // hiragana letter hi | ||
41 | "\xe3\x81\xb5", // hiragana letter hu | ||
42 | "\xe3\x81\xb8", // hiragana letter he | ||
43 | "\xe3\x81\xbb", // hiragana letter ho | ||
44 | "\xe3\x81\xbe", // hiragana letter ma | ||
45 | "\xe3\x81\xbf", // hiragana letter mi | ||
46 | "\xe3\x82\x80", // hiragana letter mu | ||
47 | "\xe3\x82\x81", // hiragana letter me | ||
48 | "\xe3\x82\x82", // hiragana letter mo | ||
49 | "\xe3\x82\x84", // hiragana letter ya | ||
50 | "\xe3\x82\x86", // hiragana letter yu | ||
51 | "\xe3\x82\x88", // hiragana letter yo | ||
52 | "\xe3\x82\x89", // hiragana letter ra | ||
53 | "\xe3\x82\x8a", // hiragana letter ri | ||
54 | "\xe3\x82\x8b", // hiragana letter ru | ||
55 | "\xe3\x82\x8c", // hiragana letter re | ||
56 | "\xe3\x82\x8d", // hiragana letter ro | ||
57 | "\xe3\x82\x8f", // hiragana letter wa | ||
58 | "\xe3\x82\x92", // hiragana letter wo | ||
59 | "\xe3\x82\x93", // hiragana letter n | ||
60 | "\xe3\x81\x81", // hiragana letter small a | ||
61 | "\xe3\x81\x83", // hiragana letter small i | ||
62 | "\xe3\x81\x85", // hiragana letter small u | ||
63 | "\xe3\x81\x87", // hiragana letter small e | ||
64 | "\xe3\x81\x89", // hiragana letter small o | ||
65 | "\xe3\x82\x83", // hiragana letter small ya | ||
66 | "\xe3\x82\x85", // hiragana letter small yu | ||
67 | "\xe3\x82\x87", // hiragana letter small yo | ||
68 | "\xe3\x81\x8c", // hiragana letter ga | ||
69 | "\xe3\x81\x8e", // hiragana letter gi | ||
70 | "\xe3\x81\x90", // hiragana letter gu | ||
71 | "\xe3\x81\x92", // hiragana letter ge | ||
72 | "\xe3\x81\x94", // hiragana letter go | ||
73 | "\xe3\x81\x96", // hiragana letter za | ||
74 | "\xe3\x81\x98", // hiragana letter zi | ||
75 | "\xe3\x81\x9a", // hiragana letter zu | ||
76 | "\xe3\x81\x9c", // hiragana letter ze | ||
77 | "\xe3\x81\x9e", // hiragana letter zo | ||
78 | "\xe3\x81\xa0", // hiragana letter da | ||
79 | "\xe3\x81\xa2", // hiragana letter di | ||
80 | "\xe3\x81\xa5", // hiragana letter du | ||
81 | "\xe3\x81\xa7", // hiragana letter de | ||
82 | "\xe3\x81\xa9", // hiragana letter do | ||
83 | "\xe3\x81\xb0", // hiragana letter ba | ||
84 | "\xe3\x81\xb3", // hiragana letter bi | ||
85 | "\xe3\x81\xb6", // hiragana letter bu | ||
86 | "\xe3\x81\xb9", // hiragana letter be | ||
87 | "\xe3\x81\xbc", // hiragana letter bo | ||
88 | "\xe3\x81\xb1", // hiragana letter pa | ||
89 | "\xe3\x81\xb4", // hiragana letter pi | ||
90 | "\xe3\x81\xb7", // hiragana letter pu | ||
91 | "\xe3\x81\xba", // hiragana letter pe | ||
92 | "\xe3\x81\xbd", // hiragana letter po | ||
93 | "\xe3\x81\xa3", // hiragana letter small tu | ||
94 | "\xe3\x82\xa2", // katakana letter a | ||
95 | "\xe3\x82\xa4", // katakana letter i | ||
96 | "\xe3\x82\xa6", // katakana letter u | ||
97 | "\xe3\x82\xa8", // katakana letter e | ||
98 | "\xe3\x82\xaa", // katakana letter o | ||
99 | "\xe3\x82\xab", // katakana letter ka | ||
100 | "\xe3\x82\xad", // katakana letter ki | ||
101 | "\xe3\x82\xaf", // katakana letter ku | ||
102 | "\xe3\x82\xb1", // katakana letter ke | ||
103 | "\xe3\x82\xb3", // katakana letter ko | ||
104 | "\xe3\x82\xb5", // katakana letter sa | ||
105 | "\xe3\x82\xb7", // katakana letter si | ||
106 | "\xe3\x82\xb9", // katakana letter su | ||
107 | "\xe3\x82\xbb", // katakana letter se | ||
108 | "\xe3\x82\xbd", // katakana letter so | ||
109 | "\xe3\x82\xbf", // katakana letter ta | ||
110 | "\xe3\x83\x81", // katakana letter ti | ||
111 | "\xe3\x83\x84", // katakana letter tu | ||
112 | "\xe3\x83\x86", // katakana letter te | ||
113 | "\xe3\x83\x88", // katakana letter to | ||
114 | "\xe3\x83\x8a", // katakana letter na | ||
115 | "\xe3\x83\x8b", // katakana letter ni | ||
116 | "\xe3\x83\x8c", // katakana letter nu | ||
117 | "\xe3\x83\x8d", // katakana letter ne | ||
118 | "\xe3\x83\x8e", // katakana letter no | ||
119 | "\xe3\x83\x8f", // katakana letter ha | ||
120 | "\xe3\x83\x92", // katakana letter hi | ||
121 | "\xe3\x83\x95", // katakana letter hu | ||
122 | "\xe3\x83\x98", // katakana letter he | ||
123 | "\xe3\x83\x9b", // katakana letter ho | ||
124 | "\xe3\x83\x9e", // katakana letter ma | ||
125 | "\xe3\x83\x9f", // katakana letter mi | ||
126 | "\xe3\x83\xa0", // katakana letter mu | ||
127 | "\xe3\x83\xa1", // katakana letter me | ||
128 | "\xe3\x83\xa2", // katakana letter mo | ||
129 | "\xe3\x83\xa4", // katakana letter ya | ||
130 | "\xe3\x83\xa6", // katakana letter yu | ||
131 | "\xe3\x83\xa8", // katakana letter yo | ||
132 | "\xe3\x83\xa9", // katakana letter ra | ||
133 | "\xe3\x83\xaa", // katakana letter ri | ||
134 | "\xe3\x83\xab", // katakana letter ru | ||
135 | "\xe3\x83\xac", // katakana letter re | ||
136 | "\xe3\x83\xad", // katakana letter ro | ||
137 | "\xe3\x83\xaf", // katakana letter wa | ||
138 | "\xe3\x83\xb2", // katakana letter wo | ||
139 | "\xe3\x83\xb3", // katakana letter n | ||
140 | "\xe3\x82\xa1", // katakana letter small a | ||
141 | "\xe3\x82\xa3", // katakana letter small i | ||
142 | "\xe3\x82\xa5", // katakana letter small u | ||
143 | "\xe3\x82\xa7", // katakana letter small e | ||
144 | "\xe3\x82\xa9", // katakana letter small o | ||
145 | "\xe3\x83\xa3", // katakana letter small ya | ||
146 | "\xe3\x83\xa5", // katakana letter small yu | ||
147 | "\xe3\x83\xa7", // katakana letter small yo | ||
148 | "\xe3\x82\xac", // katakana letter ga | ||
149 | "\xe3\x82\xae", // katakana letter gi | ||
150 | "\xe3\x82\xb0", // katakana letter gu | ||
151 | "\xe3\x82\xb2", // katakana letter ge | ||
152 | "\xe3\x82\xb4", // katakana letter go | ||
153 | "\xe3\x82\xb6", // katakana letter za | ||
154 | "\xe3\x82\xb8", // katakana letter zi | ||
155 | "\xe3\x82\xba", // katakana letter zu | ||
156 | "\xe3\x82\xbc", // katakana letter ze | ||
157 | "\xe3\x82\xbe", // katakana letter zo | ||
158 | "\xe3\x83\x80", // katakana letter da | ||
159 | "\xe3\x83\x82", // katakana letter di | ||
160 | "\xe3\x83\x85", // katakana letter du | ||
161 | "\xe3\x83\x87", // katakana letter de | ||
162 | "\xe3\x83\x89", // katakana letter do | ||
163 | "\xe3\x83\x90", // katakana letter ba | ||
164 | "\xe3\x83\x93", // katakana letter bi | ||
165 | "\xe3\x83\x96", // katakana letter bu | ||
166 | "\xe3\x83\x99", // katakana letter be | ||
167 | "\xe3\x83\x9c", // katakana letter bo | ||
168 | "\xe3\x83\x91", // katakana letter pa | ||
169 | "\xe3\x83\x94", // katakana letter pi | ||
170 | "\xe3\x83\x97", // katakana letter pu | ||
171 | "\xe3\x83\x9a", // katakana letter pe | ||
172 | "\xe3\x83\x9d", // katakana letter po | ||
173 | "\xe3\x83\x83", // katakana letter small tu | ||
174 | "0", // arabic numeral zero | ||
175 | "1", // arabic numeral one | ||
176 | "2", // arabic numeral two | ||
177 | "3", // arabic numeral three | ||
178 | "4", // arabic numeral four | ||
179 | "5", // arabic numeral five | ||
180 | "6", // arabic numeral six | ||
181 | "7", // arabic numeral seven | ||
182 | "8", // arabic numeral eight | ||
183 | "9", // arabic numeral nine | ||
184 | 0, // exclamation mark [varies] | ||
185 | 0, // question mark [varies] | ||
186 | 0, // period [varies] | ||
187 | 0, // hyphen [varies] | ||
188 | "\xe3\x83\xbb", // interpunct | ||
189 | "\xe2\x80\xa6", // ellipsis | ||
190 | 0, // left double quotation mark [varies] | ||
191 | 0, // right double quotation mark [varies] | ||
192 | 0, // left single quotation mark [varies] | ||
193 | 0, // right single quotation mark [varies] | ||
194 | "\xe2\x99\x82", // mars astrological sign | ||
195 | "\xe2\x99\x80", // venus astrological sign | ||
196 | 0, // unused | ||
197 | ",", // comma | ||
198 | 0, // unused | ||
199 | "/", // forward slash | ||
200 | "A", // uppercase latin letter a | ||
201 | "B", // uppercase latin letter b | ||
202 | "C", // uppercase latin letter c | ||
203 | "D", // uppercase latin letter d | ||
204 | "E", // uppercase latin letter e | ||
205 | "F", // uppercase latin letter f | ||
206 | "G", // uppercase latin letter g | ||
207 | "H", // uppercase latin letter h | ||
208 | "I", // uppercase latin letter i | ||
209 | "J", // uppercase latin letter j | ||
210 | "K", // uppercase latin letter k | ||
211 | "L", // uppercase latin letter l | ||
212 | "M", // uppercase latin letter m | ||
213 | "N", // uppercase latin letter n | ||
214 | "O", // uppercase latin letter o | ||
215 | "P", // uppercase latin letter p | ||
216 | "Q", // uppercase latin letter q | ||
217 | "R", // uppercase latin letter r | ||
218 | "S", // uppercase latin letter s | ||
219 | "T", // uppercase latin letter t | ||
220 | "U", // uppercase latin letter u | ||
221 | "V", // uppercase latin letter v | ||
222 | "W", // uppercase latin letter w | ||
223 | "X", // uppercase latin letter x | ||
224 | "Y", // uppercase latin letter y | ||
225 | "Z", // uppercase latin letter z | ||
226 | "a", // lowercase latin letter a | ||
227 | "b", // lowercase latin letter b | ||
228 | "c", // lowercase latin letter c | ||
229 | "d", // lowercase latin letter d | ||
230 | "e", // lowercase latin letter e | ||
231 | "f", // lowercase latin letter f | ||
232 | "g", // lowercase latin letter g | ||
233 | "h", // lowercase latin letter h | ||
234 | "i", // lowercase latin letter i | ||
235 | "j", // lowercase latin letter j | ||
236 | "k", // lowercase latin letter k | ||
237 | "l", // lowercase latin letter l | ||
238 | "m", // lowercase latin letter m | ||
239 | "n", // lowercase latin letter n | ||
240 | "o", // lowercase latin letter o | ||
241 | "p", // lowercase latin letter p | ||
242 | "q", // lowercase latin letter q | ||
243 | "r", // lowercase latin letter r | ||
244 | "s", // lowercase latin letter s | ||
245 | "t", // lowercase latin letter t | ||
246 | "u", // lowercase latin letter u | ||
247 | "v", // lowercase latin letter v | ||
248 | "w", // lowercase latin letter w | ||
249 | "x", // lowercase latin letter x | ||
250 | "y", // lowercase latin letter y | ||
251 | "z", // lowercase latin letter z | ||
252 | 0, // unused | ||
253 | 0, // unused | ||
254 | "\xc3\x84", // uppercase latin letter a with diaeresis | ||
255 | "\xc3\x96", // uppercase latin letter o with diaeresis | ||
256 | "\xc3\x9c", // uppercase latin letter u with diaeresis | ||
257 | "\xc3\xa4", // lowercase latin letter a with diaeresis | ||
258 | "\xc3\xb6", // lowercase latin letter o with diaeresis | ||
259 | "\xc3\xbc" // lowercase latin letter u with diaeresis | ||
18 | }; | 260 | }; |
19 | 261 | ||
20 | char debugGen3Decode(u8 val) | 262 | /** |
263 | * Converts a string encoded with the propietary gen 3 character encoding into | ||
264 | * a UTF-8 encoded string. The function will read the input buffer until either | ||
265 | * the max length has been reached, or an 0xFF has been found. The output buffer | ||
266 | * must be at least one plus three times the max length in size. | ||
267 | */ | ||
268 | void decodePokemonCharset( | ||
269 | const u8* input, | ||
270 | int maxLength, | ||
271 | char* output, | ||
272 | enum PokemonLanguage language) | ||
21 | { | 273 | { |
22 | return charmap[val - 0xA0]; | 274 | for (int i=0; i<maxLength; i++) |
275 | { | ||
276 | char cur = *input; | ||
277 | input++; | ||
278 | |||
279 | if (cur == 0xff) | ||
280 | { | ||
281 | break; | ||
282 | } | ||
283 | |||
284 | const char* next = 0; | ||
285 | |||
286 | if (cur == 0xab) | ||
287 | { | ||
288 | // fullwidth exclamation mark | ||
289 | if (language == Japanese) | ||
290 | { | ||
291 | next = "\xef\xbc\x81"; | ||
292 | } | ||
293 | // exclamation mark | ||
294 | else { | ||
295 | next = "!"; | ||
296 | } | ||
297 | } else if (cur == 0xac) | ||
298 | { | ||
299 | // fullwidth question mark | ||
300 | if (language == Japanese) | ||
301 | { | ||
302 | next = "\xef\xbc\x9f"; | ||
303 | } | ||
304 | // question mark | ||
305 | else { | ||
306 | next = "?"; | ||
307 | } | ||
308 | } else if (cur == 0xad) | ||
309 | { | ||
310 | // ideographic full stop | ||
311 | if (language == Japanese) | ||
312 | { | ||
313 | next = "\xe3\x80\x82"; | ||
314 | } | ||
315 | // period | ||
316 | else { | ||
317 | next = "."; | ||
318 | } | ||
319 | } else if (cur == 0xae) | ||
320 | { | ||
321 | // katakana-hiragana prolonged sound mark | ||
322 | if (language == Japanese) | ||
323 | { | ||
324 | next = "\xe3\x83\xbc"; | ||
325 | } | ||
326 | // hyphen | ||
327 | else { | ||
328 | next = "-"; | ||
329 | } | ||
330 | } else if (cur == 0xb1) | ||
331 | { | ||
332 | // left white corner bracket | ||
333 | if (language == Japanese) | ||
334 | { | ||
335 | next = "\xe3\x80\x83"; | ||
336 | } | ||
337 | // double low-9 quotation mark | ||
338 | else if (language == German) | ||
339 | { | ||
340 | next = "\xe2\x80\x9e"; | ||
341 | } | ||
342 | // left double angle quotation mark | ||
343 | else if (language == French) | ||
344 | { | ||
345 | next = "\xc2\xab"; | ||
346 | } | ||
347 | // left double quotation mark | ||
348 | else { | ||
349 | next = "\xe2\x80\x9c"; | ||
350 | } | ||
351 | } else if (cur == 0xb2) | ||
352 | { | ||
353 | // right white corner bracket | ||
354 | if (language == Japanese) | ||
355 | { | ||
356 | next = "\xe3\x80\x8f"; | ||
357 | } | ||
358 | // left double quotation mark | ||
359 | else if (language == German) | ||
360 | { | ||
361 | next = "\xe2\x80\x9c"; | ||
362 | } | ||
363 | // right double angle quotation mark | ||
364 | else if (language == French) | ||
365 | { | ||
366 | next = "\xc2\xbb"; | ||
367 | } | ||
368 | // right double quotation mark | ||
369 | else { | ||
370 | next = "\xe2\x80\x9d"; | ||
371 | } | ||
372 | } else if (cur == 0xb3) | ||
373 | { | ||
374 | // left corner bracket | ||
375 | if (language == Japanese) | ||
376 | { | ||
377 | next = "\xe3\x80\x8c"; | ||
378 | } | ||
379 | // left single quotation mark | ||
380 | else { | ||
381 | next = "\xe2\x80\x98"; | ||
382 | } | ||
383 | } else if (cur == 0xb4) | ||
384 | { | ||
385 | // right corner bracket | ||
386 | if (language == Japanese) | ||
387 | { | ||
388 | next = "\xe3\x80\x8d"; | ||
389 | } | ||
390 | // right single quotation mark | ||
391 | else { | ||
392 | next = "\xe2\x80\x99"; | ||
393 | } | ||
394 | } else { | ||
395 | next = charmap[(int)cur]; | ||
396 | } | ||
397 | |||
398 | for (; *next != 0; next++) | ||
399 | { | ||
400 | *output++ = *next; | ||
401 | } | ||
402 | } | ||
403 | |||
404 | *output = 0; | ||
23 | } | 405 | } |
diff --git a/source/encoding.h b/source/encoding.h index 4dc3b1f..0cf6165 100644 --- a/source/encoding.h +++ b/source/encoding.h | |||
@@ -8,7 +8,12 @@ | |||
8 | #define ENCODING_H_95547384 | 8 | #define ENCODING_H_95547384 |
9 | 9 | ||
10 | #include <gccore.h> | 10 | #include <gccore.h> |
11 | #include "pokemon.h" | ||
11 | 12 | ||
12 | char debugGen3Decode(u8 val); | 13 | void decodePokemonCharset( |
14 | const u8* input, | ||
15 | int maxLength, | ||
16 | char* output, | ||
17 | enum PokemonLanguage language); | ||
13 | 18 | ||
14 | #endif /* end of include guard: ENCODING_H_95547384 */ | 19 | #endif /* end of include guard: ENCODING_H_95547384 */ |
diff --git a/source/link.c b/source/link.c index 27837f8..c627039 100644 --- a/source/link.c +++ b/source/link.c | |||
@@ -12,7 +12,7 @@ | |||
12 | 12 | ||
13 | //from my tests 50us seems to be the lowest | 13 | //from my tests 50us seems to be the lowest |
14 | //safe si transfer delay in between calls | 14 | //safe si transfer delay in between calls |
15 | #define SI_TRANS_DELAY 50 | 15 | #define SI_TRANS_DELAY 500 |
16 | 16 | ||
17 | static u8* resbuf; | 17 | static u8* resbuf; |
18 | static u8* cmdbuf; | 18 | static u8* cmdbuf; |
@@ -61,7 +61,7 @@ u32 recv() | |||
61 | SI_Transfer(1, cmdbuf, 1, resbuf, 5, transcb, SI_TRANS_DELAY); | 61 | SI_Transfer(1, cmdbuf, 1, resbuf, 5, transcb, SI_TRANS_DELAY); |
62 | 62 | ||
63 | while (transval == 0); | 63 | while (transval == 0); |
64 | printf("%08lx\n", *(vu32*)resbuf); | 64 | //printf("%08lx\n", *(vu32*)resbuf); |
65 | return *(vu32*)resbuf; | 65 | return *(vu32*)resbuf; |
66 | } | 66 | } |
67 | 67 | ||
@@ -82,14 +82,7 @@ void send(u32 msg) | |||
82 | 82 | ||
83 | u32 getMsg() | 83 | u32 getMsg() |
84 | { | 84 | { |
85 | u32 val = 0; | 85 | u32 val = __builtin_bswap32(recv()); |
86 | while (val == 0) | ||
87 | { | ||
88 | val = __builtin_bswap32(recv()); | ||
89 | } | ||
90 | |||
91 | send(0); | ||
92 | while (recv()!=0); | ||
93 | send(0); | 86 | send(0); |
94 | 87 | ||
95 | return val; | 88 | return val; |
@@ -105,10 +98,7 @@ void getMsgArr(u32* arr, int len) | |||
105 | 98 | ||
106 | void sendMsg(u32 msg) | 99 | void sendMsg(u32 msg) |
107 | { | 100 | { |
108 | while (recv()==0); | ||
109 | send(msg); | 101 | send(msg); |
110 | while (recv()!=0); | ||
111 | send(0); | ||
112 | } | 102 | } |
113 | 103 | ||
114 | void waitForGBA() | 104 | void waitForGBA() |
@@ -157,5 +147,4 @@ void waitForGame() | |||
157 | void waitForAck() | 147 | void waitForAck() |
158 | { | 148 | { |
159 | while (recv() != 0) {sleep(1);} | 149 | while (recv() != 0) {sleep(1);} |
160 | send(0); | ||
161 | } | 150 | } |
diff --git a/source/main.c b/source/main.c index ceb24d5..1355533 100644 --- a/source/main.c +++ b/source/main.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <stdio.h> | 10 | #include <stdio.h> |
11 | #include <stdlib.h> | 11 | #include <stdlib.h> |
12 | #include <unistd.h> | 12 | #include <unistd.h> |
13 | #include <string.h> | ||
13 | #include "link.h" | 14 | #include "link.h" |
14 | #include "encoding.h" | 15 | #include "encoding.h" |
15 | #include "multiboot.h" | 16 | #include "multiboot.h" |
@@ -117,6 +118,7 @@ void* extractor(void* userdata) | |||
117 | 118 | ||
118 | printf("\n"); | 119 | printf("\n"); |
119 | VIDEO_WaitVSync(); | 120 | VIDEO_WaitVSync(); |
121 | sleep(1); | ||
120 | 122 | ||
121 | u32 isValid = getMsg(); | 123 | u32 isValid = getMsg(); |
122 | if (isValid == -1) | 124 | if (isValid == -1) |
@@ -144,19 +146,13 @@ void* extractor(void* userdata) | |||
144 | // Get trainer ID | 146 | // Get trainer ID |
145 | u32 trainerId = getMsg(); | 147 | u32 trainerId = getMsg(); |
146 | 148 | ||
147 | printf("Trainer: "); | 149 | // Get game language. |
150 | enum PokemonLanguage gameLanguage = getMsg(); | ||
148 | 151 | ||
149 | for (int i = 0; i < 8; i++) | 152 | char d_trainerName[25]; |
150 | { | 153 | decodePokemonCharset(trainerName, 8, d_trainerName, gameLanguage); |
151 | if (trainerName[i] == 0xFF) | ||
152 | { | ||
153 | break; | ||
154 | } else { | ||
155 | printf("%c", debugGen3Decode(trainerName[i])); | ||
156 | } | ||
157 | } | ||
158 | 154 | ||
159 | printf(" (%ld)\n", trainerId); | 155 | printf("Trainer: %s (%ld)\n", d_trainerName, trainerId); |
160 | 156 | ||
161 | // Wait for confirmation. | 157 | // Wait for confirmation. |
162 | printf("Press A to import the data from this game.\n"); | 158 | printf("Press A to import the data from this game.\n"); |
@@ -219,34 +215,15 @@ void* extractor(void* userdata) | |||
219 | 215 | ||
220 | struct PokemonIntermediate* pki = (struct PokemonIntermediate*)(&rawdata); | 216 | struct PokemonIntermediate* pki = (struct PokemonIntermediate*)(&rawdata); |
221 | 217 | ||
222 | printf("Species: %d\n", __builtin_bswap16(pki->species)); | 218 | char d_pokename[31]; |
223 | 219 | decodePokemonCharset(pki->nickname, 10, d_pokename, pki->language); | |
224 | u8* pokename = pki->nickname; | ||
225 | printf("Nickname: "); | ||
226 | |||
227 | for (int i = 0; i < 10; i++) | ||
228 | { | ||
229 | if (pokename[i] == 0xFF) | ||
230 | { | ||
231 | break; | ||
232 | } else { | ||
233 | printf("%c", debugGen3Decode(pokename[i])); | ||
234 | } | ||
235 | } | ||
236 | 220 | ||
237 | printf("\nOT: "); | 221 | char d_otName[22]; |
222 | decodePokemonCharset(pki->otName, 7, d_otName, pki->language); | ||
238 | 223 | ||
239 | for (int i=0; i<7; i++) | 224 | printf("Species: %d\n", __builtin_bswap16(pki->species)); |
240 | { | 225 | printf("Nickname: %s\n", d_pokename); |
241 | if (pki->otName[i] == 0xFF) | 226 | printf("OT: %s\n", d_otName); |
242 | { | ||
243 | break; | ||
244 | } else { | ||
245 | printf("%c", debugGen3Decode(pki->otName[i])); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | printf("\n"); | ||
250 | printf("Level: %d\n", pki->level); | 227 | printf("Level: %d\n", pki->level); |
251 | printf("HP: %ld\n", __builtin_bswap32(pki->hp)); | 228 | printf("HP: %ld\n", __builtin_bswap32(pki->hp)); |
252 | printf("Attack: %ld\n", __builtin_bswap32(pki->attack)); | 229 | printf("Attack: %ld\n", __builtin_bswap32(pki->attack)); |