1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
TAS - Pokemon Yellow run in 0:00 by gia (01:09.63)
pokemon yellow in 0:00 tas gbc game boy color done quick glitch tool assisted speedrun ash pikachu full complete pokedex fast
Dec 27 2010
This is a Tool Assisted Speedrun - TAS, it uses an emulator, savestates, bots and whatnot. They are used in order to overcome human limitations such as skill, reflex and luck ;o
You can find more tases here or at: http://tasvideos.org/
These are my previously published movies:
http://www.youtube.com/watch?v=gr3L597dZFM
http://www.youtube.com/watch?v=cYHYL8JJsFo
There are also movies published by p4wn3r at tasvideos.
I suggest you read the movie's full comments, this is the first one's:
http://tasvideos.org/1958S.html
Drama comments:
I published the first tas a long time ago. A long time after that (about a year) I suddenly decided I wanted to check the game and found an improvement that became the second movie.
A couple months later p4wn3r published a movie that used the same main strategy, with some improvements I totally missed for being stupid. So far so good, but he claimed he figured the main strategy on his own. Of course I was wary of that, but it could have been just a coincidence, I knew p4wn3r had been researched ZZAZZ and had been able to explain how it works, so he had the ability to come up with this stuff, my problem was the timing, really? I wait a year and he does this just now?. Anyway, I had found an improvement to the strategy which again got me the faster time shortly after this, but I decided not to publish anything for a while just in case. Using just Pokémon switches I could move the 76 to the stairs byte without having to access the item menu.
So months flew by, and one day, very recently, p4wn3r messaged me to my surprise. My first guess was that he had a new movie so I jumped to tasvideos and there it was, it was a nice improvement that also used a new stategy I hadn't think of, that certainly settled it, as he had proved he doesn't need to copy anything from anyone.
His new time matched mine with a different strategy, give or take frames. But using Pokémon switches his movie could be improved. I don't recall the reason of his original message but the convo was basically me proposing coauthorship, each of us researching on our own in the meantime and then p4wn3r figuring the improvement on his own and declining the offer. On my research however I had found something new, I couldn't time it without starting a tas, and I wanted to go deeper before trying. So now I got a much faster game, I suppose it can be beat, but I have finally reached the "source", or actually the "destination". If you read the comments they are always about what if you can do this faster by turning this into that, or not having to do 'x' oe whatever else. Basically, I can go now to the credits from the starting point, skipping walking, skipping talking to oak, skipping the rating, skipping everything. Now doing all that takes longer in frames, this movie is the fastest I could do, instead of skipping things that dont actually take too long I just spend less time moving memory around.
I just hope I didn't miss one stupid frame somewhere and the future improvement is something clever :)
Technical comments:
[code]
The technical comments have stuff about bits and bytes that might be too hard to understand without some training so... the drama might be enough for you... Also this time there's a lot to say so this may end up like a thesis, I'll update this as I can.
* First, read other tases comments.
* Now read this in notepad or somethin with fixed-width fonts.
In order for this TAS or its variations to be possible, a hole must be punctured on the game's data. In this case using the save corruption glitch (another way is the zzazz trick, for example). The save corruption glitch is already explained, it "gives" you access to 255 Pokémon instead of six. This is one hole, and by manipulating the Pokémon party the game's RAM can be modified. Using this the item counter can be overwritten from 20 to 255, giving a second hole, the item menu, which can be used to edit RAM data in a finer way.
Besides these, there are few places to attack using the GUI given by the developers since the run is optimized enough that walking too far from the starting point is out of the question. So this time you have to see what can you attack from inside the game, using these two holes you have opened. The previous runs changed warp points and stuff. This run changes the map script pointer, the map script pointer is basically a function pointer, a function pointer is a reference to a function, functions can be short or very long, basically you just save the address where the function is located and that way you are assured of the space you will need, two bytes. The code loads these bytes, jumps to the address pointed to and starts executing from there.
Now to explain a map script, it is code that is run every frame when inside a map area, the script is different for each map since each map should have specific events related to them. The cool thing about the Hall of Fame is that as soon as you enter it, its script's job is to make you walk the five steps to Dr. Oak, talk to him, and load the final rating and the credits sequence. So basically, what starts the ending is this function, not the map you are in, if you could make your current map's script that of the Hall of Fame then you'd be set. So that's what we do here? moslty, but, what happens when you change your current map to 76h (Hall of Fame)?, why isn't its script loaded automatically and you execute the ending sequence? Why did previous runs need a warping point?
Well, when you change the current map address with the map you want to claim to be in, the game detects this change and loads only certain data, it doesn't reload the map script pointer. So you end up at 76h but with the script pointer of your room. This doesn't work out.
To understand why you have to understand how the game and Game Boy work. The Game Boy's processor works with code and data present on its RAM. The RAM is smaller than the ROM, so let's say Pokémon Yellow is 1MB, but the RAM is only 64KB big, to be able to load all the possible data the ROM is divided into chunks of the same size, 16KB each, these are called banks, starting with bank 0. RAM area 4000-7FFF can be switched with the different ROM banks so that the developer is able to access the data of any part of the ROM. Bank 0 is always loaded in RAM 0000-3FFF so it usually has global functions and data. So:
Game Boy
0000-3FFF -> ROM Bank 0
4000-7FFF -> ROM Bank ? (01,02, ...,3F,40) (64 banks, each bank with different data)
8000-9FFF -> Video RAM
A000-FFFF -> Rest of RAM
Pokémon Yellow ROM
00000-03FFF -> ROM Bank 0
04000-07FFF -> ROM Bank 1
08000-0BFFF -> ROM Bank 2
0C000-0FFFF -> ROM Bank 3
10000-13FFF -> ROM Bank 4
18000-1BFFF -> ROM Bank 6
1C000-1FFFF -> ROM Bank 7
2C000-2FFFF -> ROM Bank 0B
44000-47FFF -> ROM Bank 11
48000-4BFFF -> ROM Bank 12
4C000-4FFFF -> ROM Bank 13
50000-53FFF -> ROM Bank 14
54000-57FFF -> ROM Bank 15
58000-5BFFF -> ROM Bank 16
5C000-5FFFF -> ROM Bank 17
60000-63FFF -> ROM Bank 18
74000-77FFF -> ROM Bank 1D
80000-83FFF -> ROM Bank 20
BC000-BFFFF -> ROM Bank 2F
E8000-EBFFF -> ROM Bank 3A
F0000-F3FFF -> ROM Bank 3C
HoF's map script pointer is 3964 -> RAM 6439 (pointers are stored reversed), 6439 is the area of switchable ROM banks. There are hundreds of maps on the game, and they have their scripts, object lists, etc. All of that doesn't fit into a single ROM bank, so the Hall of Fame's script may not be loaded at 4000-7FFF at all times, just at specific moments, like, ahem, when you are at HoF.
HoF map data is stored on bank 16, so its easier to say that HoF's script is at 16:6439. Rom Bank, two points, Ram Address. It is to be expected that at least another map may share this bank however, and if we were to warp to that other map and at the same time switch the script pointer to that of HoF, it would still be executed without issues, and the credits reached. And so it does. When D35D (current map) is changed the game does switch to the correct bank, the bank number to load is on the map data's header, by using iimarckus Pokémon Red disassembly project I could quickly get the bank values stored there (load it up and search 'MapHeaderBanks'). However this is Pokémon Yellow, so some differences could happen, as well as having to figure out the final result of invalid bank values (ie Bank FF when the max is 40). These are the banks loaded for each map value:
MAP VALUE ON ROM VALUE ON POKERED DISASSEMBLY FINAL BANK LOADED
0 6 6
1 6 6
2 6 6
3 6 6
4 11 11
5 6 6
6 6 6
7 6 6
8 7 7
9 14 14
A 14 14
B 1 1
C 7 7
D 15 15
E 15 15
F 15 15
10 15 15
11 16 16
12 12 12
13 16 16
14 15 15
15 16 16
16 16 16
17 16 16
18 15 15
19 15 15
1A 16 16
1B 16 16
1C 15 15
1D 16 16
1E 15 15
1F 14 14
20 15 15
21 14 14
22 14 14
23 14 14
24 14 14
25 12 12
26 17 17
27 6 6
28 7 7
29 11 11
2A 7 7
2B 7 7
2C 7 7
2D 1d 1D
2E 7 7
2F 17 17
30 7 7
31 17 17
32 17 17
33 18 18
34 17 17
35 17 17
36 17 17
37 7 7
38 1d 1D
39 7 7
3A 17 17
3B 12 12
3C 14 14
3D 12 12
3E 7 7
3F 7 7
40 17 17
41 17 17
42 7 7
43 17 17
44 12 12
45 7 7
46 7 7
47 17 17
48 15 15
49 7 7
4A 17 17
4B 17 17
4C 7 7
4D 17 17
4E 17 17
4F 7 7
50 7 7
51 12 12
52 11 11
53 7 7
54 12 12
55 7 7
56 12 12
57 12 12
58 7 7
59 17 17
5A 16 16
5B 17 17
5C 17 17
5D 7 7
5E 7 7
5F 18 18
60 18 18
61 11 11
62 18 18
63 18 18
64 18 18
65 18 18
66 18 18
67 18 18
68 18 18
69 1d 1D
6A 1d 1D
6B 1d 1D
6C 17 17
6D 1d 1D
6E 1d 1D
6F 1d 1D
70 1d 1D
71 16 16
72 1d 1D
73 1d 1D
74 1d 1D
75 1d 1D
76 16 16
77 18 18
78 1d 1D
79 18 18
7A 11 18
7B 15 15
7C 12 12
7D 12 12
7E 12 12
7F 12 12
80 12 12
81 12 12
82 12 12
83 12 12
84 7 7
85 12 12
86 12 12
87 12 12
88 12 12
89 12 12
8A 12 12
8B 12 12
8C 12 12
8D 17 17
8E 18 18
8F 18 18
90 18 18
91 18 18
92 18 18
93 18 18
94 18 18
95 7 7
96 17 17
97 7 7
98 7 7
99 1d 1D
9A 1d 1D
9B 1d 1D
9C 1d 1D
9D 1d 1D
9E 1d 1D
9F 11 11
A0 11 11
A1 11 11
A2 11 11
A3 15 15
A4 15 15
A5 11 11
A6 1d 1D
A7 1d 1D
A8 1d 1D
A9 1d 1D
AA 1d 1D
AB 1d 1D
AC 1d 1D
AD 1d 1D
AE 6 6
AF 1d 1D
B0 17 17
B1 17 17
B2 17 17
B3 7 7
B4 17 17
B5 17 17
B6 17 17
B7 7 7
B8 12 12
B9 12 12
BA 12 12
BB 12 12
BC 7 7
BD 15 15
BE 12 12
BF 12 12
C0 11 11
C1 7 7
C2 14 14
C3 12 12
C4 6 6
C5 18 18
C6 11 11
C7 11 11
C8 11 11
C9 11 11
CA 11 11
CB 11 11
CC 1 1
CD 1 1
CE 1 1
CF 16 16
D0 16 16
D1 6 6
D2 6 6
D3 6 6
D4 14 14
D5 15 15
D6 14 14
D7 14 14
D8 14 14
D9 11 11
DA 11 11
DB 12 12
DC 11 11
DD 11 11
DE 12 12
DF 11 11
E0 11 11
E1 11 11
E2 11 11
E3 11 11
E4 1d 1D
E5 7 7
E6 1d 1D
E7 1 1
E8 11 11
E9 17 17
EA 16 16
EB 18 18
EC 11 11
ED 11 11
EE 11 11
EF 13 13
F0 13 13
F1 11 11
F2 11 11
F3 11 11
F4 11 11
F5 1d 1D
F6 1d 1D
F7 1d 1D
F8 3c 3c
F9 fa 3a
FA 2f 2f
FB d4 14
FC cb b
FD 6f 2f
FE 20 20
FF 14 14
The important map values are F8, which loads bank 3C (useful later). These values load bank 16, the same as HoF: 11,13,15,16,17,1A,1B,1D,5A,71,76,CF,D0,EA.
While those maps load the same bank that doesn't mean their map scipt pointer points to the HoF script, so now we'd need to manipulate one of these values and place it at D35D, and then also manipulate a 3964 and place it at the map script's location D36D/D36E. Those are three values, manipulating the Trainer ID you only get two, which means you'd have to pull a trick to get that third value. Unless luckily it just happened to be naturally on the route while scrolling through items, or switching Pokémon.
However, 6439 is just the start of the function, it does several things before rolling the credits, the function that rolls the credits could be very well at some other address, perhaps even bank 0, which would mean any map would be able to access it. To figure out the truth reverse engineering of the assembly was required. An emulator with good debugging abilities is BGB, and it was used. First I had to find which specific instruction, or set of instructions were in charge of rolling the credits, as an additional objective, which addresses could pull off the same or similar effect as 6439, I seem to have deleted the list, but not the results: One of the many addresses that could still pull off the ending was 6401 (yes, a lot of instructions BEFORE the start of the function), and the instructions that call the credits start at 6461, the instructions themselves are:
A = 55h;
call 3EB4();
The function 3EB4 is used in several places of the ROM, this function has an array of function pointers, A is set with the index of the function that is to be executed and then 3EB4 is called, and the function is executed. So another way to trigger the ending would be to call 3EB4 while having 55h set on A. Sadly, putting B43Eh at D36D doesnt set A to 55h, so the credits dont roll that way, When doing that, A is set to the value of D36D (in this case B4h). A good idea would be to check in what areas of the ROM these two instructions are called even if just by coincidence (ie. Pokémon data that matches these instructions when read that way), if there was another place then that would be another possible address to call. Not only that, if the instruction call 3EB4 were to be found on an address that ends in 55 when loaded into RAM then that could do it too!
So now I had to get the list of all the banks I have access to when changing maps, then check the entirety of these banks' data looking for 3E 55 CD B4 3E (translates to A=55h;call 3EB4()) or at least CD B4 3E. Then translating it ROM address to the RAM address it would have when loaded. Then seeing if the address ends in 55 (which would allow A not to be set to anything beforehand, as it would be set to 55h before calling the function from the map script). Sadly, no luck... would have loved it, some close calls though. These are the translated addresses of each call to 3EB4 from each bank.
Bank 0:
0702
0104
6909
7209
7b0a
890a
e60c
610e
5611
5f13
981d
b01d
f223
aa2a
d62c
ed2c
d531
5232
32DE
3424
387E
3f21
01:
0d86
1041
1591
159a
187E
1883
1A81
1A88
1ABD
1B23
1BB8
1E9B
2047
28BC
2E27
3757
375C
3761
3AC6
3AD8
3AE7
06:
0E88
0EAF
0EB8
0F91
0FF7
1206
13A4
13BC
1423
143B
15F4
16BD
18C5
1998
1C87
1E4E
207A
208D
25A7
2612
2801
07:
03ED
041C
0426
0537
05FD
0607
0684
06E1
0768
07ED
07F7
082F
0839
0876
0889
09B7
09E6
0CFF
0D09
0EDE
0FAB (A=56)
165F
180B (A=54)
211F
218A
21BB
22C8 (A=56)
247D
0B:
3E08
11:
03B3
08CE
0A8C
156F
1579
174C
175B
17A2
1834
19D1
1A92
25C3
26FF
283B
2846
(HOME'S 1ST FLOOR)
12:
02F6
0572
0C9E
0D12
0D28
0D9B
0E2A
0E8C
0F27
13FD
1425
160C
191D
1E08
1F89
1F98
1FF9
209E
20DB
13:
-
14:
0F46
1042
1060
1156 <- so close!
11BF
11FE
1311
1338
1633
1645
164F
1659
1822
1BDC
1BEF
1D5B
2631
2899
15:
1281
142F
143D
146D
2364
23AE
23EA
16:
14DC
181C
1A6E
1CC5
1F2F
2463
24FC
(YOUR ROOM)
17:
40db
42f6
4300
4E32
4E81
5509
55c5
56ff
5712
5725
57d3
5C6e
18:
05C7
0966
0EB4
0EC3
0ED3
0F1C
0F56
0F60
0F6A
1426
14FD
2148
2463
2472
24B2
1D:
0075
00B9
00C3
00CD
021C
02CF
07C7
14BA
15C9
165D
188B
1910
1F88
206B
2092
20AD
20F3
2101
20:
-
2F:
-
3A:
2466
3C:
02B5
1B95
1CAA
1D57
1FD4
208E
21DC
2471
247B
24F6
25AE
25C1
Ok no use there, I could store the call 3EB4();return; instructions starting at D355 (ends in 55) and then place 55D3h at D36D so that this gets executed. But as you can imagine that ends being a lot of manipulation, and much slower than just doing something else. Dead end here.
So now we have to go deeper, what does function 55h at 3EB4 do? Again this is an array of pointers, but not just pointers, this time also a bank value is added to the mix, Bank:Address to load and call. The function that is called is 3C:4F26. Getting to this function we skip walking and also talking to Oak. Of course the end result is exactly the same as 3EB4 or 6461, but at least we got more possibilities. Bank 3C can be loaded with map F8, if you recall from before, and of course 4F26 doesn't have to be the only address that can pull it off, we can skip some bytes and still get the job done. By the way, this is basically it, the credits are drawn here, meaning that trying to go deeper you will end up seeing garbage on screen. These addresses when assigned to the map script (and having F8 as map) have different effects:
The empty addresses mark a crash or similar. The '->' mean "same as the previous effect".
3C:
4F26 RATING+CREDITS
4F29
4F2B
4F2E ->CREDITS ONLY
4F31
4F33 ->
4F36 ->
4F39 ->
4F3B -> CREDITS WITH TEXT OFFCENTER
4F3D ->
4F3E ->
4F40 ->
4F42 ->
4F44 ->
4F46 ->
4F48 ->
4F4A ->
4F4D -> "CREDITS" WITH UNRECOGNIZABLE TEXT
4F50 ->
4F53 ->
4F56 ->
4F59 ->
4F5B ->
4F5D ->
4F60 ->
4F63 ->
4F66 ->
4F69 ->
4F6C ->
4F6F ->
4F72 ->
4F74 -> AND W/ GARBLED MUSIC
4F76 ->
4F79 -> MUSIC DOESNT CHANGE FROM PREVIOUS AREA
4F7B ->
4F7E ->
4F7F ->
4F82 ->
4F85 ->
4F88 -> NO CREDITS, DISCO DANCE!! (flicker screen)
4F8A
4F8C
4F8F
4F91
4F92
4F94
4F97
4F99
4F9C
4F9D
4F9F
4F85 CALLS 50B6
50B6 -> MUSIC DOESNT CHANGE FROM PREVIOUS AREA
50B9
50BA
50BB
50BE
50BF
50C2
50C3
50C4
50C5
50C6
50C8 ->
50CA
50CC ->
50CE
50D0
50D2
50D4
50D6
50D8
50DA
50DC
50DE
50E1
50E2
50E4
50E6
50E9
50EC
50ED
50EF ->
50F2 ->
50F4 ->
50F6 ->
50F8 ->
50FB ->
50FE
5100
5103
5105
5107
5109
510C
510E
5111
5112
50FB CALLS 4FA4
4FA4 ->
4FA7 ->
4FAA ->
4FAB ->
4FAD
4FB0
4FB2
4FB5
4FB8
4FBB
4FBE
4FC1
4FC2
4FC4
4FC7
4FCA
4FCD
4FCF
4FD1
4FD4
4FD7
4FD9
4FDB
4FDD
4FDF
4FE1
4FE4
4FE7
4FE9
4FEC
4FEF
4FF1
4FF4
4FF6
4FF8
4FFB
4FFC
4FFE
The only problem is that since your map script is set to this then the credits (or rating+credits) loop infinitely. And the game never resets... So while I feel I found the "destination" I wanted to find, first it is sort of questionable if the game was beaten "properly" (game doesn't reset after credits). And second it is again the case of needing to manipulate three values to pull this off.
Talking about having to manipulate three values, if you rewind to the part where I said 6401 will still call the credits (plus walking and Oak speech though) then this value is perfect, because 01 is a natural value that is present right before the Trainer ID. As such we can get the following bytes 01 64 76. 0164h will make the map script point to the credits (eventually) and 76 can change the map (and the ROM bank) to complete the summoning of the credits. Only two values to manipulate, yay!
To manipulate values you can move Pokémon, move items, sure, use the naturally existing values in RAM, to create new values you can manipulate the Trainer ID, the Rival's name, toss items, move similar items on top of each other (the quantity values are recalculated), etc. But the problem is that most of these take too long (over 120 frames), or not very flexible. The Trainer ID is the only one that is extremely fast and can get two different values. These are the possible Rival name values:
Default rival names:
BLUE 81 8B 94 84 50 86 80 91 98 50 89
GARY 86 80 91 98 50 89 8E 87 8D 50 50
JOHN 89 8E 87 8D 50 50 11 46 D3 21 9F
Character values:
A 80
B 81
C 82
D 83
E 84
F 85
G 86
H 87
I 88
J 89
K 8A
L 8B
M 8C
N 8D
O 8E
P 8F
Q 90
R 91
S 92
T 93
U 94
V 95
W 96
X 97
Y 98
Z 99
BLANK 7F
CROSSMARK F1
( 9A
) 9B
: 9C
; 9D
[ 9E
] 9F
PK E1
MN E2
- E3
? E6
! E7
MALE EF
FEMALE F5
/ F3
. F2
, F4
a A0
b A1
c A2
d A3
e A4
f A5
g A6
h A7
i A8
j A9
k AA
l AB
m AC
n AD
o AE
p AF
q B0
r B1
s B2
t B3
u B4
v B5
w B6
x B7
y B8
z B9
EOF 50
null 00
Why 120 frames? 120 frames is what it takes to walk to glitched Oak and talk to him. If this wasn't necessary then the run would end as soon as you exit the start menu. Trying to optimize only this part means we no longer want to reach the credits sequence itself or at least the final rating sequence (3C:4F26) because for once it loops infinitely, or 3EB4 with A=55h because they will take longer than the 120 frames it takes to do what we skip that way.
120 frames is also a very low ceiling, switching Pokémon take about 69 frames, so you can only do one more switch to try to get rid of this animation. Each item scroll takes about 7-10 frames and that doesn't count switching the items, so you can't move around too much. A good possibility would be to find gui addresses, maybe there's a magical value that can make you scroll faster, show more items on the screen (scrolls that do scroll the current viewport are slower than scrolls on items currently visible) or more items per scroll (although that could be bad). Another possibility would be to find another function pointer that can be modified and that is close to the starting working area (so that it can be reached and modified faster than the current run). Or a 3EB4 on a ram address that ends in 55 on a bank that I didn't research because it is not a bank loaded on the overworld (hence why I didn't research it, the map script only executes on the overworld, another function pointer would have different code and may not set A with the end of the function adress).
Also of note, the walking and talking doesn't always take 120 frames, for example on the actual correctly-loaded HoF it takes a whole lot to talk to Oak. Of all the map values that load bank 16 the following take 137 frames: 11,13,15,16,17,1A,1B,1D. These take 120 frames: 5A,71,76,CF,D0,EA. Not only that, on the item menu these values are rendered as items, the following render slowly: 11,13,15,16,17,1A,1B,1D,5A,71,76. The following faster: CF,D0,EA.
So in the ideal world, you'd use CF, D0 or EA as map value to load bank 16 and then the HoF script. Then remember we also need a 64 on the other byte of the Trainer ID. So 64CFh, 64D0h or 64EAh. To get these values I had to run my good old bot for a while, 6476 was found at 20 frames cost, and later 641A at 12 frames cost, These weren't the holy grail so I had to pull off some tricks to get a value I wanted. First, in order to further manipulate the RNG I researched the effects of resetting the game, resetting on the first frame of the movie renders no effect, it counts as an idle frame (I assume the emulator resets as the first thing and leaves the frame time idle, hence this happening), however if you reset at any point further then the game restarts with a modified set of values. Resetting at any frame past the first: 2,3,4,5,etc give the same result so its obvious you just want to reset at the second frame. In order to prove this I had to manually check the combination possibilities up to 5 frames of idle/reset manipulation... This however did not result in any faster manipulation. The second trick is to use more inputs between the game load and the new game selection, by moving up and down during the new game/options menu you can further move the rng, altthough just by one bit. Lets say that by waiting 20 idle frames you get 1010h, then if you waste those same 20 frames by instead-of-idling-you-move-on-this-menu then the result would be 1110h. And 63D0h was a value at 11 frames cost, that only appeared when resetting on the second frame, and that had enough idle time on the New Game menu to introduce a single cursor movement (they take 3 frames, one of input, two of cool down). Moving down would then be out of the way since you'd need anoher three frames to move back up, but luckily the menu allows you to input Up, and that won't move the cursor, as New Game is the top option. And there, 64D0h, and even faster manipulation than the previous alternative.
RED is still chosen because it costs 3 frames to select, but you name is displayed twice, which means YELLOW costs 6 frames compared to RED, for a net gain of 3 frames. BLUE is chosen because it doesn't matter, I hope. You don't have to scroll his buggy name as you'll see later, but those values end up somewhere, I just dismissed their possible effect.
The save is corrupted on the starting position, because that's all that is needed. But then comes the Pokémon and item manipulation. How do we bring 0164h to D36D? and D0h to D35D in the fastest way? Of course this was the first question ever (with 76 instead of D0 and 3964 instead of 0164), but I'm showing it last because it's faster and easier to explain the final result instead of every iteration. In order to come up with the optimal solution you have to learn what happens when you switch Pokémon, because it isn't as simple as it sounds.
Data on debuggers are formatted as 16 bytes per row, but a Pokémon takes 44 bytes, so first lets format the RAM so that it shows a Pokémon on each row:
A B C D E F 0 1 2 3 4 - 5 6 7 8 9 A B C D E F - 0 1 2 3 4 5 6 7 8 9 A - B C D E F 0 1 2 3 4 5
6 7 8 9 A B C D E F 0 - 1 2 3 4 5 6 7 8 9 A B - C D E F 0 1 2 3 4 5 6 - 7 8 9 A B C D E F 0 1
2 3 4 5 6 7 8 9 A B C - D E F 0 1 2 3 4 5 6 7 - 8 9 A B C D E F 0 1 2 - 3 4 5 6 7 8 9 A B C D
E F 0 1 2 3 4 5 6 7 8 - 9 A B C D E F 0 1 2 3 - 4 5 6 7 8 9 A B C D E - F 0 1 2 3 4 5 6 7 8 9
QQ II QQ II QQ II QQ II QQ II QQ - II QQ II QQ II QQ II QQ II QQ II - QQ II QQ II QQ II QQ II QQ II QQ - II QQ II QQ II QQ II QQ II QQ II
1 D16A FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF
2 D196 FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF
3 D1C2 FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF
4 D1EE FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF
5 D21A FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF
6 D246 FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF
7 D272 [FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF
8 D29E FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF]-[FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF
9 D2CA FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF FF FF FF]
10 D2F6 [00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00]00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00*00*00 00 00 00 00
11 D322 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 30 00 81 8B 94 84 50
12 D34E 86 80 91 98 50*89*03 00 00[01 59]-*76*BA 02 00 26 12 C7 06 03 01[01 - 00]00 04 04 04 10 40 C7 40[B0 40]- 00 FF 00 00 00 00 00 00 00 00 00
13 D37A 00 FF 00 00 00 00 00 00 00 00 00 - 00 FF 00 00 00 00 00 00 00 00 00 - 00 FF 00 00 00 00 00 00 00 00 00 - 00[3D 00 00 00 00 00 00 00 00 00
14 D3A6 00 00]C8 40 00 00 0A 01 01 07 02 -*25*00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00
15 D3D2 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00
16 D3FE 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00
17 D42A 00 00 00 00 FF 00 00 00 00 00 00 - 00 FF 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00
18 D456 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 5A 80 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00
19 D482 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 40 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00
20 D4AE 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00
21 D4DA 00 00 00 00 00 00 00 FD 02 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00
22 D506 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 08 08 00 98 - 01 00 04 19 90 52 00 4E D6 4A FF
23 D532 FF FF FF 00 00 00 00 01 14 01 FF - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00
24 D55E 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00
25 D58A 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 4D 01 FC 02 18 22 - 01 00 16 10 00 00 0C 60 08 00 C0
26 D5B6 18 00 00 00 00 00 00 00 00 00 40 - 9E 27 00 00 00 00 00 00 00 00 00 - FF FF 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00
27 D5E2 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00
28 D60E 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00
29 D63A 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00
30 D665+1 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00
How to read? The first column is the Pokémon index, first Pokémon in party, second, etc. The second is the starting address in RAM, however when you want to find a specific address it gets hairy since you have to count from here. Let's find D17B, get the last digit of the address of the row D16A -> A, find it on the top four rows, the first row starts with A. You want to find 7B, the first B would be 6B, so find the second, thats 7B. The fifth row has a string of II and QQ, II means Item value (byte that when read as an item on th eitem menu would be the item name) and QQ is the item quantity. The rest is the data, I marked some important bytes, so I could find them easier, and put some data section in brackets, showing the cluster defines some value as a group or the cluster is treated as an item on the item menu (so I dont have to check the IIQQ header all the time). Byte values can change depending on your state, but most are the natural value you'll find if you are tasing.
So if you switch Pokémon 12 with Pokémon 14, the value 76 (Trainer ID) would replace the value 25 (staircase's map target), that's an old improvement I didn't release. Using the Pokémon menu I could modify the staircase target and do my same 2nd run faster, without having to access the item menu, as far as I recall at least.
That's not all however, as you can see there are dividers every 11 bytes, making 4 groups per row. A Pokémon data is not just those 44 bytes, a Pokémon also has a nickname and an OT Name, and these are stored separately.So check row 1,2,3,4,5,6, that's the normal party, row 7 shouldn't be Pokémon data, it should be nickname data (or OT data, I on't recall which is first, does it matter right now? they are FF anyway). They are 6 Pokémon, so 6 nicknames, count 6 blocks, aha they end halfway on row 8. After that the OT data, another 6 blocks, they take over row 9.
What's in row 10? Well it starts with the 152 Pokémon caught flags, each bit represents a Pokémon, if 1 then it was caught, if 0 then it wasnt. So you only have to place FFs on these first two blocks and you'll get the error rating in the end. Not getting this rating means a lot lot of lost frames, because your movie will end when you close the final message dialog which would be at the rating now. So this is a requirement.
Then the seen Pokémon data follows, and it ends with the byte between *s, This is the item counter, and the item list begins, ends and some random RAM data appear, rivals name, Trainer ID etc, won't explain each...
When you switch Pokémon 12 and 14, it is to be expected that their nickname and also their OT switch as well. So lets redraw the table based on nicknames, and on OTs
6 --- --- --- --- --- --- --- ---
7 001 002 003 004 --- --- --- ---
8 005 006 007 008 --- --- 001 002
9 009 010 011 012 003 004 005 006
10 013 014 015 016 007 008 009 010
11 017 018 019 020 011 012 013 014
12 021 022 023 024 015 016 017 018
13 025 026 027 028 019 020 021 022
14 029 030 031 032 023 024 025 026
15 033 034 035 036 027 028 029 030
16 037 038 039 040 031 032 033 034
Again, 44 bytes per row, but this time we only show one number per 11 byte block. The first group (column 2,3,4,5) of values are the nicknames, the other group the OTs. The first column is the Pokémon index on your party. As expected Pokémon 6 does not hold nickname, nor OT information. Row 7 has the nickname for Pokémon 1, 2,3 and 4, as the table shows, and it goes on until Pokémon number 40. OTs start at the half of row 8 and by row 16 you'll have the OT of Pokémon number 34 on your party. The blank row is just to separate the rows full of FF from the other rows. Of note the item list starts on row 10 too. The current map is on row 12, and row 11 has mostly 00s but it is very close to the start of the item list.
So when you switch Pokémon 12 with 14 (to simplify: 12-14) you also switch the block 4 of row 9 with row 10 block 2 (9.4-10.2) and you also do 11.2-11.4, at the same time? well no, first switch the Pokémon, then switch the nickname, then the OT, they are sequential basically. This proves a slight problem when switching to row 11 for example. As you can see, when switchng to row 11, 11.1 is also switched. So if you try to bring data there, it won't arrive in the same order it came. So, in the example, we 2-10 and then 12-14. The idea is to fill row 10 with FF so that we get 152 caught Pokémon, and then move 76 to the staircase target map so that we finish the game without accessing the item menu. Sounds cool, but if you see when you 12-14 you also do 9.4-10.2, if 9.4 had an array of 00s then you would lose your 152 caught Pokémon, and be in trouble. Now, row 9 is full of FF so that's not the problem, though there are other problems with coordinates and stuff, that brings the idea that when you play with this you are moving a lot of bytes around as a block, so its harder to keep the game happy about the new values it receives on its main ram addresses.
As you can see optimizing stuff having this in mind gives quite a lot of possibilities, most of them don't work or become longer due to the extra block moving. Anyway, back at optimizing, out of all the possible solutions I had to try about three, compare timings and take note of them and stuff. The solution I finally use is 2-10, 12-13, 13-11, enter the item menu, then back at the Pokémon menu do 11-12 and call it a day.
Let's analyze this, before doing anything we have all the blocks from 1 to 9 full of FF. Let's say that a block full of FFh is "FF". Conversely a block full of 00h is "00". Block 11.4 has some data, basically the start of your rival's name, let's call it "30". Block 12.1 ends with two bytes, 01 and the beginning of your trainer ID (which now is 64, not 59), now mentally switch it with block 12.3, the bracketed values match in position. B040 is the map script pointer for your current room, so basically if we do 12.1-12.3 then our script points to HoF script address, we just need to load bank 16. The values at 12.1 are mostly the end of you rival's name, text speed (03h) and stuff, they dont mind much if they are changed with different values. The values at 12.3 are more important (map size, and map data pointers), but luckily won't crash with this switch, the biggest issue is when you set the map size to 00h or something then you can't move :D, but luckily the rival's name has some big values. Also, on 12.3 the value 40h matches the position of the value 03h on 12.1, 40h is a multiple of 16 (decimal) which means the text speed is set to fastest as a bonus. Let's call 12.1 as "64" a short version of 0164, 64 being the most important value it contains to us. Since we chose the last byte of the block block 12.3 would be "40" then.
Let's call 12.2 as "76" to reminds us that it contains the part of the trainer ID we will use to replace the current map value (although now it is D0, but 76 must be ingrained in your memory already). Now the current map value is 26h on this same block, we don't have a D0h in any block that matches its position, so we can't just switch Pokémon to replace its value, we have to actually go to the item menu to do this. The cool thing is that D0h will be on the way so we won't lose time backtracking. Since we will have to scroll all the way to this 26h it would be nicer if we could optimize this scrolling. We can switch a bunch of FF to row 11 so that the scrolling is fastest (7 frames per item), but what about moving the whole data block closer to the start do the switch, then move it back in place? would that be faster? The answer is yes, if you do it in few moves. Scrolling (44bytes / 2=)22 FF items costs about (22*7=)154 frames compared with not doing so. So if you can do it in less then fine.
Finally 12.4 can be "0F" since it is mostly 00 but has one FF. I'll stop there because I dont need the others but whatever, you can keep going down. Now let's draw the initial state:
10 00 00 00 00
11 00 00 00 30
12 64 76 40 0F
13 0F 0F 0F 3D
We want to switch 64 with 40, then move D0h which is at 76 to another spot shich is in 76 while as close to 10.4 as possible, but then move it back in place, Fill 10.1 and 10.2 with FF. And place a big enough number in 10.4's item counter (5th byte) so that we can scroll to do 76's switching. The ideal way would be to end with this:
10 FF FF ?? FF
11 FF 76 64 ??
12 ?? ?? ?? ??
13 ?? ?? ?? ??
That way we have 152 Pokémon, enough items on the counter, but also the first and following items are FF (which are faster to scroll through), then we move the D0h in place while having the 0164 already in place, and then we do 11-12 to move the data back and go to the credits. We could possibly have this:
10 FF FF ?? FF
11 76 ?? 64 ??
12 ?? ?? ?? ??
13 ?? ?? ?? ??
That way D0h is as close as possible to the start of the item list, but then moving it back to 12.2 becomes a problem because it would need an extra Pokémon switch at the very least. ok so let's do 11-12 to move the data up, this is what we expect to get:
10 00 00 00 00
11 64 76 40 0F
12 00 00 00 30
13 0F 0F 0F 3D
We get this however, 76 and 64 are switched, because 11.1-11.2 happens when 11-12 is done:
10 00 00 00 00
11 76 64 40 0F
12 00 00 00 30
13 0F 0F 0F 3D
Ok so in the end I came up with a final solution, 2-10, 12-13, 13-11, item switch, 11-12, let's see in action:
2-10 (+ 7.2-9.2 and 8.4-10.4, but they dont change how the ram looks like in the end)
10 FF FF FF FF
11 00 00 00 30
12 64 76 40 0F
13 0F 0F 0F 3D
12-13
9 FF FF FF FF
10 FF FF FF FF
11 00 00 00 30
12 0F 0F 0F 3D
13 64 76 40 0F
+9.4-10.1 (no visible effect)
+10.3-10.4 (no visible effect again)
9 FF FF FF FF
10 FF FF FF FF
11 00 00 00 30
12 0F 0F 0F 3D
13 64 76 40 0F
13-11
9 FF FF FF FF
10 FF FF FF FF
11 64 76 40 0F
12 0F 0F 0F 3D
13 00 00 00 30
The data is in place, but any switch to 11 scrambles its order!:
+9.3-10.1 (no visible effect)
+11.1-11.3
9 FF FF FF FF
10 FF FF FF FF
11 40 76 64 0F
12 0F 0F 0F 3D
13 00 00 00 30
Aha! just the block switch we wanted, 64 is now in position. and also the text speed is 40h now.
item switching:
Move D0h at 11.2 down a couple items to replace 26h at 11.2. On the way we will have to scroll through a couple cancel buttons (from 10.4), then a bunch of items (from 11.1), the good thing is that these items are not very glitchy, and as such dont introduce much lag, at least so that it warrants to do a switch to replace them, not even replacing them with FF. Also your rival's very glitchy name is out of the way, its first part is down at 13.4, and the second part is at 64 which is now after 76.
11-12
+9.2-9.3 (no visible effect, dont care anyway)
+11.1-11.2 (no visible effect, dont care anyway)
10 FF FF FF FF
11 0F 0F 0F 3D
12 40 76 64 0F
13 00 00 00 30
And the ending runs. The switches done are not only minimal (4 switches), the cursor moving is also as well. Moving from Pokémon to Pokémon costs 5 frames. But here we do 2-10 which is practically obligatory, no loss. Then 12-13, fine we have to move from 10 to 12 to do this, we lost 10 frames. Then 13-11, we are already at 13... and doing these moves are so that stuff dont get scrambled against us when moving closer to the start of the item list. And finally 11-12, while we already are at 11. Other solutions lose a lot of time scrolling up and down because the numbers don't match and then get added the 69 frames of actually doing the switch.
Oak's error message is due to not having the data correctly loaded. It takes 120 frames compared to 137 because this error message is faster to close.
[/code]
Thanks to:
* was0x's improvement. Scrolling instead of switching as the first action after entering the pokemon menu saves one frame. ie. do 2-10 instead of 1-10.
* p4wn3r's latest runs which made me research some more and also an improvement. Don't name the rival if you aren't going to benefit from it.
* iimarckus for his Pokemon Red Disassambly Project.
* bobmario51 for his Glitchfest run (http://www.youtube.com/watch?v=1EYHT25_FCc) which sparked improvement (better late than never).
* hanzou and Chamale for making me attempt a TAS of this game.
* Visual Boy Advance v19.3 authors
* BGB project.
* TAS Movie Editor authors.
* cafiremage2 and everyone that gave me data on how their actual game cart behaved when trying these glitch things.
* All the rom hackers that put their discoveries online, from memory i recall gamefaqs, datacrystal, glitchcity, upokecenter, matt's pokemon resource pack and more with sites that have ceased to exist by now.
Enjoy the site? All donations are appreciated

Free Text Host is brought to you by Dagon Design
This site contains no adware, spyware, or popups
Questions? Comments?     Privacy Policy     Report abuse here