This is a split board - You can return to the Split List for other boards.

Notable Breakpoints

#11tsanth(Topic Creator)Posted 1/4/2008 1:00:28 PM
Well, I verified my theory about IV being dependent upon PV. Here's the PV generation routine:

PVIVGenSTART: push r3-r7,r14
02066D92 (T) add sp,-18h
02066D94 (T) str r2,[sp,10h]
02066D96 (T) str r3,[sp,14h]
02066D98 (T) ldr r4,[sp,30h]
02066D9A (T) mov r6,r0
02066D9C (T) mov r7,r1
02066D9E (T) bl rand ; -> (LOOP)
02066DA2 (T) mov r5,r0
02066DA4 (T) bl rand ; ->
02066DA8 (T) lsl r0,r0,10h
02066DAA (T) orr r5,r0
02066DAC (T) mov r0,r5
02066DAE (T) bl PVShuf ; ->
PVShufREJOIN: cmp r4,r0
02066DB4 (T) bne 2066D9Eh ; --^ (to LOOP)
02066DB6 (T) mov r0,1h
02066DB8 (T) str r0,[sp]
02066DBA (T) str r5,[sp,4h]
02066DBC (T) mov r0,0h
02066DBE (T) str r0,[sp,8h]
02066DC0 (T) str r0,[sp,0Ch]
02066DC2 (T) ldr r2,[sp,10h]
02066DC4 (T) ldr r3,[sp,14h]
02066DC6 (T) mov r0,r6
02066DC8 (T) mov r1,r7
02066DCA (T) bl IVGenSTART ; ->
IVGenREJOIN: add sp,18h
PVIVGenRET: pop r3-r7,r15


PVShuf is a routine which does a lot of random-number generating to make a "valid" PV. I haven't decoded that completely yet, but it's relatively simple, so it shouldn't take too long to figure out.

IVGen is extremely convoluted, at least to me, since I don't have the breadth of experience in ARM assembly to decode it by sight.

By knowing the state of the PRNG (e.g. forcing it to return 0 for testing, as what I've done), it's possible to determine exactly what values we need to look for to find the relevant routines which generate the PV and IV. What I've found is that the IV is indeed generated after the PV: the IV generator calls the PRNG, which has been mangled (at that point) by the PV generator. pAC is making a little more sense to me now.

I'm making charts. More to come later!
---
Where the fear has gone there will be nothing.
Only I will remain.
#12tsanth(Topic Creator)Posted 1/8/2008 4:40:42 PM
Poffin making and berry farming has been taking up my time as of late, but I'll be getting back to this stuff soon enough.

Something I found interesting about the busy-loop that the game uses: berry changes proc right before the minute changes and bring about a sparkly animation, while tint changes due to time proc on the minute. Those two bits of information might be useful for someone trying to find where those events happen in the code.
---
Where the fear has gone there will be nothing.
Only I will remain.
#13tsanth(Topic Creator)Posted 1/8/2008 4:49:46 PM
Another thing before I forget: the game evidently has another way to check a pokemon's EV levels other than by simply referencing the given values changed via Pokesav. For example, setting a pokemon to run HP 4 / Spe 252 / Atk 252 will result in strange overflow errors. Putting a pokemon into and out of a box fixes the overflow errors, but doesn't reset the counter.

I still have to investigate whether saving and reloading or transferring a pokemon via trade "fixes" the glitches. As-is, I'm very impressed with Game Freak's dedication to keeping check-values for important stuff.

They don't appear to check trainer ID and secret ID, since those don't appear to be useful for anything except for shiny determination. This begs the question: how feasible would it be to simply give an arbitrary pokemon trainer IDs such that it fulfills the shiny formula?

Something to try later, I guess.
---
Where the fear has gone there will be nothing.
Only I will remain.
#14tsanth(Topic Creator)Posted 1/9/2008 10:35:34 AM
Did a bit more testing into the wee hours of the morning:

IVs, as used in-battle, seem to be stored in six separate values, while the PV is stored as a block-value. The memory locations for the six IVs:

027E38D8 IV_HP
027E38D0 IV_Atk
027E38CC IV_Def
027E38C8 IV_Spe
027E38C4 IV_SpA
027E38C0 IV_SpD


This is interesting because it is possible to force the game to re-calculate all of the PVs and IVs for a given pokemon by halting execution at the point where the routine rejoins its parent (at 0x0223CA4A) and forcing execution to return to the start of the initialization for the generation routine (at 0x0223CA40). What I would find even more interesting is if there were a way to force generation to loop until a set of desired IVs were reached. My attempts to do so, however, have been waylaid by the fact that the generation routine is apparently dependent upon all of the surrounding code.

More tests to come later.
---
Where the fear has gone there will be nothing.
Only I will remain.
#15Jeffmaz2001Posted 1/9/2008 10:52:55 AM
tsanth, I am curious about the resources you are using. Where did you get the assembly codes for the processor of the NDS? As I recall, the GBA was a derivitive of the Z80, and therefore used a superset of the Z80 instruction set. But I seem to also recall that the NDS is a 16-bit processor and assume that it has an all-new instruction set, with the ability to revert to executing code intended for the GBA processor (GBA mode).

Where did you get that? And what kind of programming do you do? Many "programmers" work in C++ or Java or other high-level languages, but you seem comfortable in the assembly/disassembly world. Do you also have hardware experience, or are you software only?
---
Any idiot can hack, many do.
I am playing 2 copies each of Diamond and Pearl.
#16tsanth(Topic Creator)Posted 1/9/2008 12:59:33 PM
I'm using the hobbyist version of no$gba for my disassembly. The more hardcore people use IDA for their stuff, but I'm stepping through the code and marking out points of interest the old-fashioned way: by hand. It's a little slow, but it works for me personally because it gives me more incentive to really understand what's going on with all those function calls.

no$gba provides an overview and summary of the NDS , its processors, and relevant opcodes/flags for the CPU (http://nocash.emubase.de/gbatek.htm). As I understand it, it uses an ARM7 and ARM9 for different sorts of processing. The great majority of the code I've been stepping through is THUMB-mode ARM (GBA-compatible stuff), so it's not too far removed from other assembly that I've seen before. I like the ARM much better than 80x86 assembly: so far, it's treated me much better.

My work's a lot different: I currently write logistics software and servlets, primarily in Java and Perl with bits of (MySQL-flavored) SQL. My hobby coding is mostly in whatever tickles my fancy at the time; most of the time it happens to be in work-related languages, so my past projects have been Java (AWT and Swing included), Perl, C++, C, and bash, but I've dabbled in a few other languages (like Lisp and PHP) and I'm looking to pick up Python (maybe in Stackless form also) in the near future. I used to do electronics work with a buddy of mine back in junior high and high school, so that's a skill that comes in handy sometimes, too. A small part of my past involved me doing hardware support, so I like to consider myself somewhat well-rounded.

A long time ago, when my dad first brought home the V20 with DOS 3.21 (not even 3.22!), I spent a lot of time learning how to use DOS, write batch files, and use DOS debug. Eventually I learned that "CD 21" actually meant something, but it wasn't until college that I really picked up the theory to put my experience to work for me: I found that I really liked my microprocessor internals course, so the love of it has stuck with me since.

Overall, I just find the stuff fascinating.
---
Where the fear has gone there will be nothing.
Only I will remain.
#17Jeffmaz2001Posted 1/9/2008 1:16:49 PM
So you don't like the 8086 code much either, huh? I used to do hand assembly for processors, my favorite was the 68000. The 8086 drove me nuts, whoever invented the concept of segmentation should be shot. Gimmee contiguous address space ANY DAY! But aside from that, the 8086 also had a horrible instruction set, with stuff that was neither op-code or operand, but some nebulous thing in between, as I recall. I was VERY happy when I discovered I didn't NEED to mess with any 8086 assembly when I learned that I could code interrupt routines in C. Whew! Then Microsoft threw me a curve: They game me a 32-bit processor with a 32-bit write instruction that operated by doing two 16-bit writes back-to-back. The 80486 was CAPABLE of writing 32 bits at a time, the instruction was there, but the Microsoct C compiler had no way of coding that instruction. They couldn't understand why this would be a problem, but the hardware I was using wanted to latch all 32-bits in hardware and two sequencial writes of 16 bits, (repeated on upper and lower words) just fouled things up. I had to get someone to write an assembly routine I could link in that would actually call the correct instruction, JUST to get that hardware to work for reads and writes of 32 bits. If I had been working with the 68000, I could have written it in my sleep, but the 8086 family just never sunk in on my.

Enough reminising, back to work. :)
---
Any idiot can hack, many do.
I am playing 2 copies each of Diamond and Pearl.
#18erdrick9024Posted 1/9/2008 4:41:25 PM
This is a quality topic and I wish I had something to contribute.
---
Kirbies in Hats: http://www.whackyantics.com/kih
MS (Bera): Satinka/Numorfeo/Aventail/Etamu/Lunamise (32/26/21/19/55)
#19tsanth(Topic Creator)Posted 1/9/2008 5:10:32 PM
There's always stuff to contribute. Just little, seemingly trivial things in the game might be useful when trying to find information about how the game works. I'd be totally interested in hearing about odd or otherwise interesting behavior that the game has, e.g. the turn-and-encounter thing, or how pokemon get healed only after finishing a dual-trainer battle. It'd probably be a long while before I get around to all that cool stuff, but it'd be nice to have it around at least as a reference in case someone else gets bored with a debugger.

Aside on that: knowing that the game procs an encounter every time you turn on an encounter-capable square is good information, because it explains how one can "cheat" the safari zone by waiting in a patch of grass and turning around in circles in the same square.

It also helps for those who are interested in minimizing encounters through Victory Road: if you can avoid an extra turn on the way out, you might save yourself an extra two chances to proc an encounter. That might be useful if you're running low on potions and really need to get out of an encounter-prone zone.

Just some thoughts.
---
Where the fear has gone there will be nothing.
Only I will remain.
#20tsanth(Topic Creator)Posted 1/9/2008 7:45:45 PM
Just discovered something: the check condition in PVIVGen (address 0x02066DB4) doesn't matter to pAC. When r4 comes into the function, it's set to some arbitrary value in the range 0x00..0x18 (possibly generated from the encounter seed). Forcing the check to succeed results in a PV-IV pair which validates as legitimate. What this means is that pAC is only concerned about whether or not the PV generates the IV-set. This now makes some sense to me, since by design, one can't tell what the value of r4 should have been unless you knew how to run the PRNG backwards (and by design, that's typically not possible). That's probably possible with rainbow tables, but the storage and time requirements are prohibitive, especially when our realm of concern is "just a game."

Other thoughts:

1) The search space to find a valid DWORD pair for the PV generation (bottom word and top word, respectively) would be 2^16, which is doable with current hardware, but prohibitive for a web application. Given a DWORD pair generator, it would be possible to make reasonable-looking numbers which would validate in all cases, if we assume that the encounter seed isn't stored along with the pokemon data. To wit:

Seeding the PRNG with 0xCAFEBABE results in the next number being 0xB84FC759. Let's suppose that we were given 0xCAFE???? and wanted to find a result matching the pattern 0xB84F????. My maths indicate to me that's a 2^16 search space, even if we assume that such a match exists: I do not yet know if every value entered into the PRNG maps to a unique value.

2) By looking at the numbers, it makes sense why full-0 and full-31 IV sets are so rare in wild pokemon: an IV set is contingent upon the game generating a DWORD pair which, by luck, satisfies an effectively-random 1d24 dice roll, which can then generate a full-0 or full-31 IV set. What this means is that the game is, on average, knocking out 23/24 of every set of DWORD pairs, so you really only have a very small space out of which you can generate IVs. The lesson? Those who have found triple-31 Dittos are holding something very rare.

Seeing as how I haven't even figured out a sensible way to code the PV shuffling routine yet, I think it'll be a while before I figure out the IV generator.

...

In before tl;dr. Back to tracing assembly!
---
Where the fear has gone there will be nothing.
Only I will remain.