Main Menu
Main Page
Forums
New pages
Recent changes
Random page
Help

Glitches
Arbitrary code execution
Pokémon cloning
Pomeg glitch and Glitzer Popping
Tweaking and voiding
Glitches by generation
Glitch categories

References/Resources
Databases
Disassembly projects
The Big HEX List
Pokémon cheat codes
Pokémon glitch terminology
Useful tools
More

Affiliates
Legendary Star Blob 2 (Hakuda)
Pokémon Speedruns wiki
PRAMA Initiative
Become an affiliate!

Technical
Site source code

Search Wiki

 

Search Forums

 

Author Topic: My New Pokemon ROM Hacking Tool!  (Read 127 times)

0 Members and 1 Guest are viewing this topic.

OldNewComputers

  • GCLF Member
  • Offline Offline
  • CHARIZRAD 'M ROXORX or is it.
    • View Profile
My New Pokemon ROM Hacking Tool!
« on: January 22, 2019, 06:28:13 pm »
As a test of my programming skill, I wrote a basic ROM hacking tool for Pokemon Generation 1 (well, I've only tested it with Yellow version) in Python. You can edit basic info about Pokemon such as types, base stats, basic attacks (not yet but soon), catch rate, growth rate (not yet but soon), etc., as well as sprite pointers (not yet but soon). So there are a number of features I plan, and I might even add some Gen 2 compatibility.

A few major features I want to add too but I don't have enough info for I'm listing below and I hope you can help me find the information. The first two below are my main priorities but the latter two would be nice too.

1.) Edit Moves (Move data structure gen 1? Where do the moves begin? How large is a move in bytes?)
2.) Edit Trainers (Trainer data structure gen 1? Where do the trainers begin? How large is a trainer in bytes?)
3.) Edit Map (Map data structure gen 1? What offset do the maps start at? How large is a map in bytes?)
4.) Edit Sprites (Sprite structure gen 1? Where do the Pokemon sprites begin? How large is each?)

BTW a couple bugs -- I only have a few moves programmed in -- trying to print out moves it doesn't understand as base moves causes a key error.
Code: [Select]
"""
pokereader v1
Allows you to read and edit Pokemon base stats.
"""

#constants
START_ADDRESS = 0x383DE
FILE = "DEBUGYELLOW.GBC"
typeDict = {0: "NORMAL", 1: "FIGHTING", 2: "FLYING", 3: "POISON", 4: "GROUND",
            5: "ROCK", 6: "BIRD", 7: "BUG", 8: "GHOST", 0x14: "FIRE",
            0x15: "WATER", 0x16: "GRASS", 0x17: "ELECTRIC", 0x18:"PSYCHIC",
            0x19: "ICE", 0x1A: "DRAGON"}
growthDict = {0: "MEDIUM FAST", 3: "MEDIUM SLOW", 4: "FAST", 5: "SLOW"}
attackDict = {1: "POUND", 2: "KARATE CHOP", 3: "DOUBLE SLAP",
              33: "TACKLE", 45: "GROWL"}

reverseTypeDict = {v: k for k, v in typeDict.items()}
reverseAttackDict = {v: k for k, v in attackDict.items()}
reverseGrowthDict = {v: k for k, v in growthDict.items()}

menuString = """Pokemon Editor Menu
1. Edit Pokedex Number
2. Edit Base HP
3. Edit Base Attack
4. Edit Base Defense
5. Edit Base Speed
6. Edit Base Special
7. Edit Type 1
8. Edit Type 2
9. Edit Catch Rate
A. Edit Base EXP
B. Edit Base Attack 1
C. Edit Base Attack 2
D. Edit Base Attack 3
E. Edit Base Attack 4
F. Edit TM/HM Flags
10. Edit Dimensions of Frontsprite
11. Edit Pointer to Frontsprite
12. Edit Pointer to Backsprite
13. Edit Growth Rate
14. Exit"""


#functions
def calcPkmnOffset(pokedexNum, gen=1):
    return START_ADDRESS + (28 * (pokedexNum - 1))

def printReport(pokedexNum):
    offset = calcPkmnOffset(pokedexNum)
    fil = open(FILE, "rb")
    file = fil.read()

    print("Pokedex Number: " + str(file[offset + 0]))
    print("Base HP: " + str(file[offset + 1]))
    print("Base Attack: " + str(file[offset + 2]))
    print("Base Defense: " + str(file[offset + 3]))
    print("Base Speed: " + str(file[offset + 4]))
    print("Base Special: " + str(file[offset + 5]))

    try:
        print("Type 1: " + str(typeDict[file[offset+6]]))
    except: print("Type 1: GLITCH")

    try:
        print("Type 2: " + str(typeDict[file[offset+7]]))
    except: print("Type 2: GLITCH")

    print("Catch rate: " + str(file[offset+8]))
    print("Base EXP Yield: " + str(file[offset+9]))
    ##### insert attacks known at lv1 here -- 0x0f-0x12
    if file[offset+0x0f]:
        print("Lv1 Attack #1: {}".format(attackDict[file[offset+0x0f]]))

    if file[offset+0x10]:
        print("Lv1 Attack #2: {}".format(attackDict[file[offset+0x10]]))

    if file[offset+0x11]:
        print("Lv1 Attack #3: {}".format(attackDict[file[offset+0x11]]))

    if file[offset+0x12]:
        print("Lv1 Attack #4: {}".format(attackDict[file[offset+0x12]]))

    print("Growth Rate: " + growthDict[file[offset+0x13]])

    tms = input("Show TM/HM Learnset? (Y)es or (N)o? ").upper()

    """if tms == "Y" or tms == "YES":
        for i in range(55):
            off = offset + 0x14 + int((i / 8))
            n = bool(off & (2 ** (i % 8)))
            if n: print("TM" + str(i-1)) #very buggy"""

    fil.close()
   
    return

def editStats(pokedexNum):
    offset = calcPkmnOffset(pokedexNum)

    review = input("Review old stats? (Y)es or (N)o? ").upper()

    if review == "Y" or review == "YES":
        printReport(pokedexNum)

    file_ = open(FILE, "rb")
    file_old = list(file_.read())
    file_.close()
    open(FILE,"wb").close()
    file = open(FILE, "wb")
   

    while True:
        print(menuString)
        choice = input("? ")

        if choice == "1":
            num = int(input("Enter New Pokedex Number: "))
            file_old[offset] = num

        if choice == "2":
            stat = int(input("Enter New HP Basestat: "))
            file_old[offset+1] = stat

        if choice == "3":
            stat = int(input("Enter New Attack Basestat: "))
            file_old[offset+2] = stat

        if choice == "4":
            stat = int(input("Enter New Defense Basestat: "))
            file_old[offset+3] = stat

        if choice == "5":
            stat = int(input("Enter New Speed Basestat: "))
            file_old[offset+4] = stat

        if choice == "6":
            stat = int(input("Enter New Special Basestat: "))
            file_old[offset+5] = stat

        if choice == "7":
            typ = reverseTypeDict[input("Enter New Type 1: ").upper()]
            file_old[offset+6] = typ

        if choice == "8":
            typ = reverseTypeDict[input("Enter New Type 2: ").upper()]
            file_old[offset+7] = typ

        if choice == "9":
            stat = int(input("Enter New Catchrate: "))
            file_old[offset+8] = stat

        if choice == "A":
            stat = int(input("Enter New EXP Yield: "))
            file_old[offset+9] = stat
           
        if choice == "14": break

    file_old = bytearray(file_old)
    file.write(file_old)
    file.close()

    return