Jump to content

Bond697

Former Staff
  • Posts

    1358
  • Joined

  • Last visited

Posts posted by Bond697

  1. i would imagine they have different ai "scripts" for different types of pokemon. an attacker wouldn't be as worried about healing as something bulky meant to sit there for awhile, etc. so they're given different weight depending on the ai "program" meant for that type of poke.

  2. i know the game does lots of damage calcs to see what move it should use and i think it takes into consideration how much damage it can do vs what recovery would do for it. if they can use recover and you attack, then they're roughly right back where they started anyway. i don't think they know what you're going to do next, just (possibly) what you have done, so they're not evaluating it against your next move, just different odds. it makes complete sense that the higher the attack stat, the more likely they are to attack. it gives better return on investment.

  3. so i've been working on this and i thought it would be good to put up a basic example of the kind of thing you'll have access to with this kit:

    all the function definitions are straight from the arm9 and are normally used for allocating memory in-game. you'll have access to all the same stuff plus some inlined and macro functions.

    by my count, if you add the 2 free blocks together here:

    #define FREE1 0x23A8B04

    #define FREE1_SIZE 0x374FC

    #define FREE2 0x23FA800

    #define FREE2_SIZE 0x5000

    you end up with roughly 240kb free for your own data/code, which is quite a bit. this is especially so since you'll be able to move code and stuff in and out of ram via overlays.

    i think what will happen is that i'll write a function that just allocates all the free memory into 2 main heaps that you can do things with, one around 0x5000 bytes and one around 0x374FC bytes. you won't have to use that function and you can write your own to partition up the memory even more, but it will be there as a. an example and b. for ease of use.

  4. you might want to try these:

    non_dex_complete_unova                         DCW 0x287        ; DATA XREF: 
    RAM_ARM9:0208F838                                                     ; these pokes don't count toward dex completion(unova)
    RAM_ARM9:0208F83A 88 02                       DCW 0x288
    RAM_ARM9:0208F83C 89 02                       DCW 0x289
    RAM_ARM9:0208F83E EE 01                       DCW 0x1EE
    
    RAM_ARM9:0208F840 27 00       word_208F840    DCW 0x27                ; DATA XREF: sub_200DBDC+66o
    RAM_ARM9:0208F840                                                     ; sub_200DBDC+AAo ...
    RAM_ARM9:0208F842 1F 05                       DCW 0x51F
    RAM_ARM9:0208F844 63 00                       DCW 0x63
    RAM_ARM9:0208F846 20 05                       DCW 0x520
    RAM_ARM9:0208F848 9F 00                       DCW 0x9F
    RAM_ARM9:0208F84A 21 05                       DCW 0x521
    RAM_ARM9:0208F84C E5 00                       DCW 0xE5
    RAM_ARM9:0208F84E 22 05                       DCW 0x522
    RAM_ARM9:0208F850 28 01                       DCW 0x128
    RAM_ARM9:0208F852 23 05                       DCW 0x523
    RAM_ARM9:0208F854 00 00                       DCW 0
    RAM_ARM9:0208F856 24 05                       DCW 0x524
    
    RAM_ARM9:0208F858 9F 00       word_208F858    DCW 0x9F                ; DATA XREF: sub_200DBDC+EAo
    RAM_ARM9:0208F858                                                     ; RAM_ARM9:off_200DCE8o
    RAM_ARM9:0208F85A 1F 05                       DCW 0x51F
    RAM_ARM9:0208F85C 5D 01                       DCW 0x15D
    RAM_ARM9:0208F85E 20 05                       DCW 0x520
    RAM_ARM9:0208F860 C1 01                       DCW 0x1C1
    RAM_ARM9:0208F862 21 05                       DCW 0x521
    RAM_ARM9:0208F864 25 02                       DCW 0x225
    RAM_ARM9:0208F866 22 05                       DCW 0x522
    RAM_ARM9:0208F868 7B 02                       DCW 0x27B
    RAM_ARM9:0208F86A 23 05                       DCW 0x523
    RAM_ARM9:0208F86C 00 00                       DCW 0
    RAM_ARM9:0208F86E 24 05                       DCW 0x524
    
    RAM_ARM9:0208F870 97 00       non_dex_complete DCW 0x97       
    RAM_ARM9:0208F870                                                     ; these pokes don't count toward dex completion(all)
    RAM_ARM9:0208F872 FB 00                       DCW 0xFB
    RAM_ARM9:0208F874 81 01                       DCW 0x181
    RAM_ARM9:0208F876 82 01                       DCW 0x182
    RAM_ARM9:0208F878 E9 01                       DCW 0x1E9
    RAM_ARM9:0208F87A EA 01                       DCW 0x1EA
    RAM_ARM9:0208F87C EB 01                       DCW 0x1EB
    RAM_ARM9:0208F87E EC 01                       DCW 0x1EC
    RAM_ARM9:0208F880 ED 01                       DCW 0x1ED
    RAM_ARM9:0208F882 87 02                       DCW 0x287
    RAM_ARM9:0208F884 88 02                       DCW 0x288
    RAM_ARM9:0208F886 89 02                       DCW 0x289
    RAM_ARM9:0208F888 EE 01                       DCW 0x1EE        
    

    idk exactly what makes up the list, but if it matches the legendary list, you might have some luck.

    other than that, that stuff would need to be changed twice, once for the battle subway overlay set and once for the pwt overlay set.

  5. reserved for explanation.

    so this is just a basic runthrough of how this came about.

    **see here for the different types of trainer pokes: http://projectpokemon.org/forums/showthread.php?24589-B2W2-General-ROM-Info&p=161021&viewfull=1#post161021

    i had a few issues to tackle. for one, all the code needed to fit into some very small spaces. the function that makes trainerpokes leaves very small windows to actually do what i needed to do- no more than 6 or 8 bytes each time. second, there are 4 different kinds of trainerpokes and each type jumps to the trainerpoke stat creation function just a bit differently. so in the small amounts of room i had, i had to account for each of the 4 sets of code being different/using different registers. an early thought i had was to use a few of my own functions that do basically the same thing, but with different registers. that was my plan for quite awhile, but i managed to come up with a way that allowed me to route all 4 sets of code to the same nature creation function.

    one of the challenges here was finding space for me to use to put my code. first, the code HAD to go in the arm9. i didn't have enough room to really go crazy with overlays and i didn't want to anyway. an overlay loading system is something i have planned for later with user-made code and i didn't want that to conflict with this code. i used a good idea i had for nesting code instead:

    romhacks will never run in dsi mode, right? they can't. there's no dsi mode dump of white 2 U and even if there was, editing the rom would likely break necessary data that allowed for dsi mode booting. so what i could do is look for places where the game checked to see if it was in dsi mode. i found code that was set to ONLY run in dsi mode and removed it with the (correct) assumption that it will simply never run. after that i wrote my own code in THUMB which allows for fitting a greater amount of code in a smaller area. this is a picture of the code in action: (green is ARM, red is THUMB)

    nature_hack.png

    note the STMFD at the top(which is ARM) and if you follow it does, you'll see where isDSi runs to check for dsi mode. that call will never be true, so right after that my code begins in THUMB(test_hack) at the MOVS and runs through the POP near the bottom. note the bright blue sets of bytes next to the ARM and THUMB code. there's 4 next to the ARM and 2 next to the THUMB, which is mine. so there's smaller THUMB code nested inside the larger ARM code. when the main function there runs starting at the STMFD, it will jump past my code and continue on and when my code runs, it ends just before the ARM starts again.

    so figuring that part out wasn't too bad. finding enough space in unused code wasn't difficult since my function was small and was done in THUMB to keep it tiny. i ended up using 52 bytes total there, which is good because now i can fit more code in the rest of that space as needed.

    so that worked out well. the real problem though was in getting the code that makes trainerpokes to cooperate. this is my planning notes: http://pastebin.com/PYFdK3Mj

    the very, very first thing i did was fix the level loading code for all 4 types of trainerpoke. gamefreak treats level as a 16-bit number here, likely for the sake of keeping alignment to 2 or 4-bytes. what i did was edit some code so that it went from this:

    LDRH    R0, [R0,#2]     ; load level
    

    to this:

    LDRB    R0, [R0,#2]     ; load level
    

    the top version loads a halfword(16-bit) while the bottom loads a byte(8-bit) and leaves the other byte for me.

    i wanted to get the first of the 4 working and then i figured i would move on to the rest. that starts as:

    RAM_ARM9:02030A4C EB F7 20 FD                 BL      createPKM
    RAM_ARM9:02030A50 0D 9A                       LDR     R2, [sP,#0x98+current_tr_poke_ptr] this load a pointer to the trpoke poke's file to r2
    RAM_ARM9:02030A52 0D 9B                       LDR     R3, [sP,#0x98+current_tr_poke_ptr] same into r3
    RAM_ARM9:02030A54 D2 88                       LDRH    R2, [R2,#6]     ; form                    byte 7 is the form to use in the trpoke file
    RAM_ARM9:02030A56 5B 78                       LDRB    R3, [R3,#1]     ; gender_abil             byte 2 is the gender/abil byte
    RAM_ARM9:02030A58 04 98                       LDR     R0, [sP,#0x98+trainer_idx] ; trainer_idx  this is unused but would be a massive pain to do anything with
    RAM_ARM9:02030A5A 21 1C                       MOVS    R1, R4          ; pPkm
    RAM_ARM9:02030A5C 00 F0 E6 F9                 BL      setTrainerPkmStats
    

    so my first thought is that LDR R2 and LDR R3 do the same thing there so right away we can trim out 1 of those instructions for use in a new branch. THUMB instructions are 2 bytes, but THUMB branch with links are 4 bytes, so i would need to make room and get rid of a few instructions for that AND make sure the next function has the arguments it needs. so getting rid of that leaves 1 more + arguments i need for my function and the next. the second thing i can do is move the ldrh and ldrb there into my function at the very end so that they're available to the next function. that frees up 4 more bytes to use for preparation. the final thing i ended up doing is something that is extremely unconventional and not a legal/acceptable move for nintendo's compiler because it breaks programming standards. it helps me because it frees up more rooom though. see where it says "MOVS R1, R4 ; pPkm"? i need that value for my function. i went to look and for all 4 types that value is always in R4. so i don't pass it into my function, i simply assume it's in r4 and take it as i need it. one other nice thing i take advantage of is that "LDR R0, [sP,#0x98+trainer_idx] ; trainer_idx" is completely unused in "setTrainerPkmStats" for some reason, so i can ignore it completely. taking advantage of all these optimizations gets me this:

    RAM_ARM9:02030A50 0D 9A       LDR     R2, [sP,#0x98+current_tr_poke_ptr]
    RAM_ARM9:02030A52 10 1C       MOVS    R0, R2
    RAM_ARM9:02030A54 C0 46       NOP
    RAM_ARM9:02030A56 29 F0 A1 FF BL      test_hack
    

    where i managed to optimize so much that i actually had room left over and had to use a NOP for the extra space. this is true for one other type also. the first and third have extra space, but the other 2 use it all.

    the last one presented a problem because it looks like this:

    RAM_ARM9:02030D80 FA 88                       LDRH    R2, [R7,#6]     ; form
    RAM_ARM9:02030D82 7B 78                       LDRB    R3, [R7,#1]     ; gender_abil
    RAM_ARM9:02030D84 04 98                       LDR     R0, [sP,#0x98+trainer_idx] ; trainer_idx
    RAM_ARM9:02030D86 21 1C                       MOVS    R1, R4          ; pPkm
    RAM_ARM9:02030D88 00 F0 50 F8                 BL      setTrainerPkmStats
    

    note how the loading is done from R7, but i assume everywhere else that the loading is done via R2. that means that the first thing i have to do i move the value in r7 over to r2 and go from there so that i can keep using the 1 function to set natures and preserve space. BUT i only have 6 bytes to work with and that includes a couple of moves and a branch, so that's at least 8. i solved this by being a little bit clever here. the other 3 calls to test_hack have the same value in r0 and r2. it's always the same in both and i use both eventually. so my thought was to allow the move from r7 to r2 and then add a bit to test_hack that moves the value in r2 into r0. the other 3 are always equal already, so it won't affect them and it lets the last type fit and use the same function. this was the result:

    RAM_ARM9:02030D80 3A 1C       MOVS    R2, R7                          ; form
    RAM_ARM9:02030D82 29 F0 0B FE BL      test_hack
    

    and this is the final version of test_hack:

    RAM_ARM9:0205A99C 10 1C       MOVS    R0, R2
    RAM_ARM9:0205A99E F0 B5       PUSH    {R4-R7,LR}
    RAM_ARM9:0205A9A0 07 1C       MOVS    R7, R0
    RAM_ARM9:0205A9A2 26 1C       MOVS    R6, R4
    RAM_ARM9:0205A9A4 15 1C       MOVS    R5, R2
    RAM_ARM9:0205A9A6 FC 78       LDRB    R4, [R7,#3]
    RAM_ARM9:0205A9A8 00 2C       CMP     R4, #0
    RAM_ARM9:0205A9AA 06 D0       BEQ     loc_205A9BA
    RAM_ARM9:0205A9AC 19 2C       CMP     R4, #0x19
    RAM_ARM9:0205A9AE 04 DC       BGT     loc_205A9BA                     ; pPkm
    RAM_ARM9:0205A9B0 30 1C       MOVS    R0, R6                          ; pPkm
    RAM_ARM9:0205A9B2 61 1E       SUBS    R1, R4, #1                      ; nature
    RAM_ARM9:0205A9B4 C2 F7 2A FE BL      setNatureResetStats       
    RAM_ARM9:0205A9B8 06 E0       B       loc_205A9C8
    RAM_ARM9:0205A9BA             loc_205A9BA                             ; max
    RAM_ARM9:0205A9BA 19 20       MOVS    R0, #0x19
    RAM_ARM9:0205A9BC AA F7 C4 FE BL      randMain64
    RAM_ARM9:0205A9C0 01 1C       MOVS    R1, R0                          ; nature
    RAM_ARM9:0205A9C2 30 1C       MOVS    R0, R6                          ; pPkm
    RAM_ARM9:0205A9C4 C2 F7 22 FE BL      setNatureResetStats
    RAM_ARM9:0205A9C8             loc_205A9C8
    RAM_ARM9:0205A9C8 2A 1C       MOVS    R2, R5
    RAM_ARM9:0205A9CA 53 78       LDRB    R3, [R2,#1]
    RAM_ARM9:0205A9CC D2 88       LDRH    R2, [R2,#6]
    RAM_ARM9:0205A9CE 31 1C       MOVS    R1, R6
    RAM_ARM9:0205A9D0 F0 BD       POP     {R4-R7,PC}
    

    note that the very first instruction moves r2 into r0. usually THUMB functions begin with PUSH and end with POP(or don't use PUSH and POP at all), so this is unconventional, but it solves my problem.

  6. The first post will be the patch and instructions and the second will be a look into how I managed to do this.

    Using this will be a little bit complex for now until the new version of Kazo's trainer editor shows up. I don't know if he'll be doing it or if I'll be doing it, but it will be available at some point soon-ish. Until then, there are basic instructions in the text file and obviously you can ask questions in here.

    So what we've got here is the first implementable hack for 5th gen Rom hacks. For now it will just be for B2W2, but will eventually be for BW as well. As the title states, it lets you pick the nature for opposing trainers' pokes.

    http://hack.thundaga.com/trainer_nature.7z

    Also, here's a pic of what I was talking about in the text file:

    nature_byte.png

    The red square is byte 0x4B, the one you're supposed to edit.

  7. i just opened one of my hgss states with the rom running, saved state 5, added a poke to my party and first box, loaded state 5, and everything is fine.

    you might want to maybe try shutting desmume off when you're editing states. i can't see anything wrong at all, though.

  8. fyi: i am working on this, but i'm transitioning to windows 8(which i fucking love by the way) and thus am working slowly. what i thought was going to be a small project with 1 function made by me is turning out to be bigger than expected to say the least. there's going to be a very long post detailing everything i had to do once i finish this thing.

    right now i have the sort of scaffolding implemented. a limitation that gamefreak had placed on the trainer pkm files is now gone and i have access to the trainer pkm files and the resulting pkm files.

  9. http://projectpokemon.org/wiki/Notable_Breakpoints#Pok.C3.A9mon_HGSS_.28U.29

    02108514 Starter species in RAM(in the decompressed arm9 @ 108514) Bond697

    so to make it into an AR code:

    this changes the first starter:

    12108514 0000xxxx

    D2000000 00000000

    the second:

    12108518 0000xxxx

    D2000000 00000000

    the third:

    1210851C 0000xxxx

    D2000000 00000000

    to change all 3 at once:

    12108514 0000xxxx

    12108518 0000xxxx

    1210851C 0000xxxx

    D2000000 00000000

    enter the code with the starter number(s) you want before you start a new game.

  10. that was about the narcs. those can change in size because there's nothing hardcoded about their size or location since they're almost always loaded into free space on the heap. overlays have to be precise because they're all code and the arm9/other overlays jump around between each other.

    if another overlay/ an earlier point in the same overlay jumps to a new function in a changed overlay and everything isn't accounted for, it'll start reading invalid instructions and the game crashes.

  11. oh, i'm not sure actually. kazo may have thought that nature was editable. it's 100% definitely not, though:

    RAM_ARM9:02030EC8             loc_2030EC8                             ; CODE XREF: setTrainerPkmStats+62j
    RAM_ARM9:02030EC8                                                     ; setTrainerPkmStats+66j
    RAM_ARM9:02030EC8 28 1C                       MOVS    R0, R5          ; pPkm
    RAM_ARM9:02030ECA 00 21                       MOVS    R1, #0          ; field
    RAM_ARM9:02030ECC 00 22                       MOVS    R2, #0          ; data
    RAM_ARM9:02030ECE EB F7 29 FF                 BL      getPkmStat      ; pid
    RAM_ARM9:02030ED2 00 12                       ASRS    R0, R0, #8
    RAM_ARM9:02030ED4 19 21                       MOVS    R1, #0x19       ; denom
    RAM_ARM9:02030ED6 5C F0 D8 EB                 BLX     divmodSigned    ; make nature
    RAM_ARM9:02030EDA 09 06                       LSLS    R1, R1, #0x18
    RAM_ARM9:02030EDC 28 1C                       MOVS    R0, R5
    RAM_ARM9:02030EDE 09 0E                       LSRS    R1, R1, #0x18
    RAM_ARM9:02030EE0 EC F7 94 FB                 BL      setNatureResetStats ; set nature
    

    see where it says "getPkmStat"? the field argument before it is 0, which is the pid. so it gets the pid, does a bit of math, and does %0x19(note the "divmod" right afterward) which is 25 in decimal.

  12. yeah, for trainer pokes the pid is random and then they do pid % 25 to get the nature(like in gen 3/4).

    trainer ai will eventually be editable. that said, it's pretty huge for 1 person to figure out so it'll be awhile for that one. there's quite a few commands aside from the main logic. i might eventually take a stab at making the trainers smarter at some point in the future. the best you can do at the moment is copy from other trainers of the same type. (1 for a normal path trainer, 7 for event trainer, 87 for friendly doubles, etc)

  13. the pids(and thus, natures) are randomly generated.

    i don't think you were understanding me. you don't need to "mod" any move. when the game is creating the trainer's pokes from the provided data, if any of them have frustration their happiness is set to 0 automatically. otherwise it's 255. just give the poke you want to have frustration/return the move you want and the rest is taken care of.

    also, are you using an old version of the tool? it's not "unknown" anymore. he finished the tool after i posted that. you should download the latest ones. that unknown is actually "strength". take the value and multiply by 31 then divide by 255 and you get the iv number to use for all 6 ivs. i think they did that to make it more difficult to modify. they could easily have made it a 0-31 value, but instead added some very needless complexity.

    ex. unkown is set to 255: 255 * 31 / 255 = 31

    so you can see why it's kind of a waste.

    Really? Well, I guess I shouldn't believe everything smogon says then :)

    i found the thread this was from on smogon. all of that is just based on observation without actually knowing how any of it works or looking at any of the code behind the decisions. i'd wager it's wrong just as often as it is right, or worse.

×
×
  • Create New...