about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2017-07-11 18:14:18 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2017-07-11 18:14:18 -0400
commitec66a022a8879a5300f2ae64cd86a5d8cfbd1a36 (patch)
tree06e096126cf673be5cfd9dd1ff164c8d46520de9
parent57afb4058710a978bd7b07a368125d04378c62f1 (diff)
downloadgen3uploader-ec66a022a8879a5300f2ae64cd86a5d8cfbd1a36.tar.gz
gen3uploader-ec66a022a8879a5300f2ae64cd86a5d8cfbd1a36.tar.bz2
gen3uploader-ec66a022a8879a5300f2ae64cd86a5d8cfbd1a36.zip
Things are semi-reliably working now!
A good portion of the time, the Wii will display:

Pokemon LeafGreen
Trainer: Starla (34182)

which is the correct data on the cartridge I am testing with.

Most of the GBA changes are within comments and are unimportant. I did
uncomment the portion where it sends over the trainer's name, and I
fixed how it reads the trainer ID from memory.

The Wii changes involve properly cooperating in the message sending
protocol I'm having the GBA and Wii use.

More description regarding protocol: I'm not super familiar with the
JOY BUS protocol because it's undocumented, but there seems to be this
issue where the Wii reads the same value multiple times from the cable,
and since the cable is used to negotiate the multiboot image, I need to
make sure that the Wii and GBA are on the same page. Since the last
message that the GBA sends is nonzero, I have the GBA image start by
sending a zero and waiting for a response, and I have the Wii wait for a
zero. The Wii then sends a zero in response to the GBA. From then on,
the message sending protocol works like so:

Wii: waits for non-zero value
GBA: sends non-zero value, waits for any response
Wii: reads message, sends 0 response, waits for 0 response
GBA: receives response, sends 0 response, waits for any response
Wii: reads 0, continues on with program

The reason for this is to prevent incorrect communication caused by the
Wii reading the same value from the GBA multiple times by essentially
delimiting the message. This is currently pretty slow because I have
debugging messages and sleeps everywhere. I will clean this code up, but
this project is slightly dark magic right now and I wanted to commit
something that worked in the slightest.

Also added a debug function that transcodes from the proprietary gen 3
encoding to ASCII in the domain of characters that can actually be used
in names (except for the 6 special German ones). Thanks to Bulbapedia
(https://bulbapedia.bulbagarden.net/wiki/Character_encoding_in_Generation_III)
for this. It's used for now to display the Trainer name on the console.
It assumes that the cartridge is non-Japanese; this will be addressed.
I'm not currently planning on transcoding names before transmitting them,
because of the fact that there are characters in the character set that
are not present in any other character set, and thus transcoding them
spuriously (like PK -> P,K) is a loss of data. However, it is true that
no such characters exist in the set of characters that can be used for
names (in either the Japanese or non-Japanese encoding), so I may later
decide to transcode to Unicode on the Wii before transmitting.
-rw-r--r--gba/source/gamedata.c2
-rw-r--r--gba/source/main.c64
-rw-r--r--source/encoding.c14
-rw-r--r--source/encoding.h8
-rw-r--r--source/main.c77
5 files changed, 117 insertions, 48 deletions
diff --git a/gba/source/gamedata.c b/gba/source/gamedata.c index 19d5100..8e63232 100644 --- a/gba/source/gamedata.c +++ b/gba/source/gamedata.c
@@ -493,7 +493,7 @@ bool initSaveData(
493 } 493 }
494 494
495 loadsave(0); 495 loadsave(0);
496 496// sendS32(-1);
497 // now the save is loaded, we can do what we want with the loaded blocks. 497 // now the save is loaded, we can do what we want with the loaded blocks.
498 // first, we're going to want to decrypt the parts that are crypted, if applicable. 498 // first, we're going to want to decrypt the parts that are crypted, if applicable.
499 decryptSaveStructures(gSaveBlock1,gSaveBlock2,gSaveBlock3); 499 decryptSaveStructures(gSaveBlock1,gSaveBlock2,gSaveBlock3);
diff --git a/gba/source/main.c b/gba/source/main.c index 104866a..94d4c2b 100644 --- a/gba/source/main.c +++ b/gba/source/main.c
@@ -96,31 +96,53 @@ int main(void)
96 m3_fill(RGB15(31,31,31)); 96 m3_fill(RGB15(31,31,31));
97 plot_sqr( 4, 4, RGB15(31, 0, 0) ); // or CLR_RED 97 plot_sqr( 4, 4, RGB15(31, 0, 0) ); // or CLR_RED
98 98
99 99 /*
100 100
101 //*(vu16 *)(REG_BASE + 0x84) = 0x8f; 101 //*(vu16 *)(REG_BASE + 0x84) = 0x8f;
102 //REG_IME = 1; 102 //REG_IME = 1;
103 // the vblank interrupt must be enabled for VBlankIntrWait() to work 103 // the vblank interrupt must be enabled for VBlankIntrWait() to work
104 // since the default dispatcher handles the bios flags no vblank handler 104 // since the default dispatcher handles the bios flags no vblank handler
105 // is required 105 // is required
106 //irqInit(); 106 irqInit();
107 //irqEnable(IRQ_VBLANK); 107 irqEnable(IRQ_VBLANK);
108 108
109 //consoleDemoInit(); 109 consoleDemoInit();
110 //REG_JOYTR = 0; 110 //REG_JOYTR = 0;
111 111
112 // ansi escape sequence to set print co-ordinates 112 // ansi escape sequence to set print co-ordinates
113 // /x1b[line;columnH 113 // /x1b[line;columnH
114 //u32 i; 114 //u32 i;
115 //iprintf("\x1b[9;2HPokemon Gen III Data Extractor\n"); 115 iprintf("\x1b[9;2HPokemon Gen III Data Extractor\n");
116 //iprintf("\x1b[10;4HPlease look at the TV\n"); 116 iprintf("\x1b[10;4HPlease look at the TV\n");
117 117
118 // disable this, needs power 118 // disable this, needs power
119 //SNDSTAT = 0; 119 SNDSTAT = 0;
120 //SNDBIAS = 0; 120 SNDBIAS = 0;
121 121
122 // Set up waitstates for EEPROM access etc. 122 // Set up waitstates for EEPROM access etc.
123 //REG_WAITCNT = 0x0317; 123 REG_WAITCNT = 0x0317;
124
125 s32 gamesize = getGameSize();
126 u32 savesize = SaveSize(save_data,gamesize);
127 switch (savesize){
128 case 0x200:
129 GetSave_EEPROM_512B(save_data);
130 break;
131 case 0x2000:
132 GetSave_EEPROM_8KB(save_data);
133 break;
134 case 0x8000:
135 GetSave_SRAM_32KB(save_data);
136 break;
137 case 0x10000:
138 GetSave_FLASH_64KB(save_data);
139 break;
140 case 0x20000:
141 GetSave_FLASH_128KB(save_data);
142 break;
143 default:
144 break;
145 }*/
124 146
125 //clear out previous messages 147 //clear out previous messages
126 REG_HS_CTRL |= JOY_RW; 148 REG_HS_CTRL |= JOY_RW;
@@ -172,10 +194,12 @@ int main(void)
172 plot_sqr( 5, 4, RGB15( 31, 0,31) ); 194 plot_sqr( 5, 4, RGB15( 31, 0,31) );
173 waitForAck(); 195 waitForAck();
174 plot_sqr( 5, 5, RGB15( 16, 16,16) ); 196 plot_sqr( 5, 5, RGB15( 16, 16,16) );
197
175 // Get access to save data. 198 // Get access to save data.
176 pSaveBlock1 SaveBlock1; 199 pSaveBlock1 SaveBlock1;
177 pSaveBlock2 SaveBlock2; 200 pSaveBlock2 SaveBlock2;
178 pSaveBlock3 SaveBlock3; 201 pSaveBlock3 SaveBlock3;
202 //iprintf("gonna check thing\n");
179 if (!initSaveData(&SaveBlock1, &SaveBlock2, &SaveBlock3)) 203 if (!initSaveData(&SaveBlock1, &SaveBlock2, &SaveBlock3))
180 { 204 {
181 // Unsupported game version. 205 // Unsupported game version.
@@ -187,12 +211,13 @@ int main(void)
187 211
188 continue; 212 continue;
189 } 213 }
214 //iprintf("success\n");
190 plot_sqr( 5, 6, RGB15( 0, 31,16) ); 215 plot_sqr( 5, 6, RGB15( 0, 31,16) );
191 sendS32(1); 216 sendS32(1);
192 waitForAck(); 217 waitForAck();
193 /* 218
194 // Send trainer name. 219 // Send trainer name.
195 u8* trainerName; 220 u8* trainerName = 0;
196 221
197 if (GAME_RS) 222 if (GAME_RS)
198 { 223 {
@@ -204,14 +229,6 @@ int main(void)
204 { 229 {
205 trainerName = SaveBlock2->e.playerName; 230 trainerName = SaveBlock2->e.playerName;
206 } 231 }
207 iprintf("%d\n", trainerName[0]);
208 iprintf("%d\n", trainerName[1]);
209 iprintf("%d\n", trainerName[2]);
210 iprintf("%d\n", trainerName[3]);
211 iprintf("%d\n", trainerName[4]);
212 iprintf("%d\n", trainerName[5]);
213 iprintf("%d\n", trainerName[6]);
214 iprintf("%d\n", trainerName[7]);
215 232
216 u32 tn1 = 233 u32 tn1 =
217 (trainerName[0] << 24) 234 (trainerName[0] << 24)
@@ -230,10 +247,10 @@ int main(void)
230 247
231 sendU32(tn2); 248 sendU32(tn2);
232 waitForAck(); 249 waitForAck();
233*/ 250
234 // Send trainer ID. 251 // Send trainer ID.
252
235 u8* trainerId = 0; 253 u8* trainerId = 0;
236
237 if (GAME_RS) 254 if (GAME_RS)
238 { 255 {
239 trainerId = SaveBlock2->rs.playerTrainerId; 256 trainerId = SaveBlock2->rs.playerTrainerId;
@@ -246,9 +263,10 @@ int main(void)
246 } 263 }
247 264
248 u32 tti = 265 u32 tti =
249 (trainerId[2] << 8) 266 (trainerId[1] << 8)
250 | (trainerId[3]); 267 | (trainerId[0]);
251 268
269 //iprintf("sending trainer id %ld\n", tti);
252 sendU32(tti); 270 sendU32(tti);
253 waitForAck(); 271 waitForAck();
254 272
diff --git a/source/encoding.c b/source/encoding.c new file mode 100644 index 0000000..a69fc7e --- /dev/null +++ b/source/encoding.c
@@ -0,0 +1,14 @@
1#include "encoding.h"
2
3const char charmap[] = {
4 ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '?', '.', '-', ' ',
5 ' ', '\"', '\"', '\'', '\'', '*', '*', ' ', ',', ' ', '/', 'A', 'B', 'C', 'D', 'E',
6 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
7 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
8 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ' '
9};
10
11char debugGen3Decode(u8 val)
12{
13 return charmap[val - 0xA0];
14}
diff --git a/source/encoding.h b/source/encoding.h new file mode 100644 index 0000000..be99895 --- /dev/null +++ b/source/encoding.h
@@ -0,0 +1,8 @@
1#ifndef ENCODING_H_95547384
2#define ENCODING_H_95547384
3
4#include <gccore.h>
5
6char debugGen3Decode(u8 val);
7
8#endif /* end of include guard: ENCODING_H_95547384 */
diff --git a/source/main.c b/source/main.c index 79fd2fc..dfcdc3b 100644 --- a/source/main.c +++ b/source/main.c
@@ -17,6 +17,7 @@
17#include <dirent.h> 17#include <dirent.h>
18#include <fat.h> 18#include <fat.h>
19#include "link.h" 19#include "link.h"
20#include "encoding.h"
20 21
21//from my tests 50us seems to be the lowest 22//from my tests 50us seems to be the lowest
22//safe si transfer delay in between calls 23//safe si transfer delay in between calls
@@ -308,6 +309,21 @@ u32 deriveKeyC(u32 keyCderive, u32 kcrc) {
308 return keyc; 309 return keyc;
309} 310}
310 311
312u32 getMsg()
313{
314 u32 val = 0;
315 while (val == 0)
316 {
317 val = __builtin_bswap32(recv());
318 fsleep(1);
319 }
320 send(0);
321 while (recv()!=0) {fsleep(1);};
322 send(0);
323
324 return val;
325}
326
311int main(int argc, char *argv[]) 327int main(int argc, char *argv[])
312{ 328{
313 void *xfb = NULL; 329 void *xfb = NULL;
@@ -482,7 +498,7 @@ int main(int argc, char *argv[])
482 u32 bootkey = docrc(0xBB,keyc) | 0xbb000000; 498 u32 bootkey = docrc(0xBB,keyc) | 0xbb000000;
483 printf("BootKey = 0x%08lx\n",bootkey); 499 printf("BootKey = 0x%08lx\n",bootkey);
484 send(bootkey); 500 send(bootkey);
485 /* 501 /*
486 printf("GBA Found! Waiting on BIOS...\n"); 502 printf("GBA Found! Waiting on BIOS...\n");
487 503
488 resbuf[2]=0; 504 resbuf[2]=0;
@@ -557,12 +573,12 @@ int main(int argc, char *argv[])
557 endproc(); 573 endproc();
558 } else if (btns & PAD_BUTTON_A) 574 } else if (btns & PAD_BUTTON_A)
559 {*/ 575 {*/
560 sleep(1); 576 sleep(2);
561 //recv(); 577 //recv();
562 578
563 //if (recv() == 0) //ready 579 //if (recv() == 0) //ready
564 { 580 //{
565 581 {{
566 printf("Waiting for GBA...\n"); 582 printf("Waiting for GBA...\n");
567 while (recv() != 0) {fsleep(1);}; 583 while (recv() != 0) {fsleep(1);};
568 send(0); 584 send(0);
@@ -604,6 +620,7 @@ int main(int argc, char *argv[])
604 620
605 send(0); 621 send(0);
606 while (recv()!=0) {fsleep(1);}; 622 while (recv()!=0) {fsleep(1);};
623 send(0);
607 //sleep(1); 624 //sleep(1);
608 625
609 if (gameId == -1) 626 if (gameId == -1)
@@ -644,27 +661,26 @@ int main(int argc, char *argv[])
644 661
645 send(0); 662 send(0);
646 while (recv()!=0) {fsleep(1);}; 663 while (recv()!=0) {fsleep(1);};
664 send(0);
647 //sleep(1); 665 //sleep(1);
648 /* 666
649 // Get trainer name 667 // Get trainer name
650 u8 trainerName[8]; 668 u8 trainerName[8];
651 669
652 u32 tnd = recv(); 670 u32 tnd = getMsg();
653 send(0); 671 //send(0);
654 trainerName[0] = (tnd & 0xFF000000); 672 trainerName[0] = (tnd & 0xFF000000) >> 24;
655 trainerName[1] = (tnd & 0x00FF0000) >> 8; 673 trainerName[1] = (tnd & 0x00FF0000) >> 16;
656 trainerName[2] = (tnd & 0x0000FF00) >> 16; 674 trainerName[2] = (tnd & 0x0000FF00) >> 8;
657 trainerName[3] = (tnd & 0x000000FF) >> 24; 675 trainerName[3] = (tnd & 0x000000FF);
658 676
659 tnd = recv(); 677 tnd = getMsg();
660 send(0); 678 //send(0);
661 trainerName[4] = (tnd & 0xFF000000); 679 trainerName[4] = (tnd & 0xFF000000) >> 24;
662 trainerName[5] = (tnd & 0x00FF0000) >> 8; 680 trainerName[5] = (tnd & 0x00FF0000) >> 16;
663 trainerName[6] = (tnd & 0x0000FF00) >> 16; 681 trainerName[6] = (tnd & 0x0000FF00) >> 8;
664 trainerName[7] = (tnd & 0x000000FF) >> 24; 682 trainerName[7] = (tnd & 0x000000FF);
665 683
666 printf("Trainer: %s", (char*) trainerName);
667*/
668 // Get trainer ID 684 // Get trainer ID
669 u32 trainerId = 0; 685 u32 trainerId = 0;
670 while (trainerId == 0) 686 while (trainerId == 0)
@@ -674,7 +690,20 @@ int main(int argc, char *argv[])
674 } 690 }
675 send(0); 691 send(0);
676 while (recv()!=0) {fsleep(1);}; 692 while (recv()!=0) {fsleep(1);};
693 send(0);
677 //sleep(1); 694 //sleep(1);
695
696 printf("Trainer: ");
697
698 for (int i = 0; i < 8; i++)
699 {
700 if (trainerName[i] == 0xFF)
701 {
702 break;
703 } else {
704 printf("%c", debugGen3Decode(trainerName[i]));
705 }
706 }
678 707
679 printf(" (%ld)\n", trainerId); 708 printf(" (%ld)\n", trainerId);
680 709
@@ -917,9 +946,9 @@ int main(int argc, char *argv[])
917 sleep(5); 946 sleep(5);
918 } 947 }
919 }*/ 948 }*/
920// } 949 }
921 // } 950// }
922// } 951// }
923 } 952 }
924 return 0; 953 return 0;
925} 954}