Jump to content

Kaphotics

Helpful Member
  • Posts

    6895
  • Joined

  • Last visited

  • Days Won

    323

Posts posted by Kaphotics

  1. But why would you use the public computers to edit save files or generate AR codes? You can't install programs on them to get codes/saves transferred...

    slightly related to ibac's statement: In my university's engineering computer lab at they all run XP; the computer science facility used XP as well, but I last was there a year ago.

    I say you drop XP support but still have a (stable) version downloadable that works for XP -- just never updated kind of like what was done for vers 2.312 or whatever. If XP is holding you back, drop it!

  2. offset range: 0x76000-0x7C204, checksum at 0x7C208

    unova starter .pds (pokedex skin)

    haven't done anything with it, just noting that when corrupting this region the dex skin is deleted

    if I transplant the data of an active dex skin to another with the data included afterwards, the save file deletes itself, so there's other stuff that has to be overwritten, just like the cgear skin; however I'm not really interested in pursuing this further

    ----

    I should also mention that Musical data is in the 0x56000~0x76000 region of the save file. Pretty much all the DLC including battle videos is at the end of the save file.

    (so far I've seen it as mystery gift -> ??if anything?? -> battle videos -> cgear -> musical -> pdex -> ???)

    ----

    not really dlc, but another observation

    battle competition (wifi/IR tournaments) are in the 0x20100(?)~0x209FF region

    it's easy to find this data in the RAM and re-register for a tournament if you un-register via a one byte AR code (not posting that for obvious reasons)

  3. Map Coordinates

    poslua.png

    White

    while true do
    gui.text(1,184, string.format("Map: %d, X: %d, Y: %d, Z: %d", memory.readword(0x0224F92C), memory.readword(0x0224F932,2), memory.readword(0x0224F93A), memory.readword(0x0224F936)))
    emu.frameadvance()
    end

    Black

    while true do
    gui.text(1,184, string.format("Map: %d, X: %d, Y: %d, Z: %d", memory.readword(0x0224F90C), memory.readword(0x0224F912,2), memory.readword(0x0224F91A), memory.readword(0x0224F916)))
    emu.frameadvance()
    end

    Download Link (English White)

  4. rng helper -- very old version. see first post for most up to date

    PzWXH.png

    -- RNG location for current game (English White)
    local rng=0x02216244
    
    -- setup terminology abbreviations
    local rshift=bit.rshift
    local mdword=memory.readdwordunsigned
    
    -- setup initial variables = 0, rest of script detection will take care of them
    local initl=0
    local inith=0
    local adv=0
    local total=0
    local last=0
    local jump1=0
    
    -- setup frame detection function
    function next(s)
    local a=0x6C07*(s%65536)+rshift(s,16)*0x8965
    local b=0x8965*(s%65536)+(a%65536)*65536+0x00269EC3
    local c=b%4294967296
    return c
    end
    
    -- Lua script begin!
    while true do
    
    -- setup every loop
    seed2=mdword(rng+4)
    seed1=mdword(rng)
    adv=0
    test=last
    
    -- display seeds every loop
    gui.text(1,10,string.format("Current: %08X%08X",seed2,seed1))
    gui.text(1,180,string.format("Initial: %08X%08X",inith,initl))
    gui.text(180,10,string.format("Delay: %d", mdword(0x023FFC3C)))
    gui.text(1,170, string.format("M: %d, X: %d, Y: %d, Z: %d", memory.readword(0x0224F92C), memory.readword(0x0224F932,2), memory.readword(0x0224F93A), memory.readword(0x0224F936))) -- copied from map coord Lua
    
    
    -- check to see if the RNG advanced from the last value
    while seed1~=0 and seed2~=0 do
    	if adv>200 then -- RNG advanced a bunch. Reset script then stop loop.
    		print(""..string.format("Detected a reset or massive advancement. Re-initializing."))
    		adv  =0
    		total=0
    		jump1=0
    		initl=mdword(rng)
    		inith=mdword(rng+4)	
    		print(""..string.format("Session Initial Seed: %08X%08X",inith,initl)) 
    		break 
    
    	elseif test~=seed1 then -- RNG advanced at least once. Lets advance once and repeat the loop.
    		test=next(test)
    		adv=adv+1
    		jump1=adv
    
    	elseif test==seed1 then break -- last frame's advanced RNG value matches the current. Stop loop.
    	end
    end
    
    -- advancement tracking
    total=adv+total
    gui.text(1,19,string.format("Frame: %d", total))
    gui.text(1,28,string.format("Jump: %d", jump1))
    last=seed1
    
    emu.frameadvance() 
    end

    main use is that it tracks RNG frames after keeping the seeds from the moment the script starts.

    it grabs the initial seed when the game is reset, or the first seed it can find and keeps it stored as long as the script runs.

    I may have it write the initial seeds it gets to somewhere so that upon loading a save state it can find and re-determine the frame (session preservation), but this was just for fun

  5. 1) emulators have their own range. expand range drastically

    2) time is the second the game boots. use the Movie function of desmume to specify start time rather than changing your computer time

    3) no, RAM watch is used. you have to make one yourself from known addresses

    4) we don't support gen 5 emu RNG on the grounds that it is pathetically easy on a DS -- no reason to emulate

    5) before the nintendo logo appears right after the boot

    see 4)

  6. Pokemon Emerald (U)

    Emerald Egg Tracking RNG Suite

    rL1a7.png

    local rng
    local timer
    local offset 
    local pidpointer=0x0203BC78
    local pidoffset
    local pid
    local iter=0
    local base=0
    local a
    local timerseed=0
    local stepcounter
    local nature
    local ids
    local tid
    local sid
    local lpid
    local hpid
    local shiny
    local naturename={
    "Hardy","Lonely","Brave","Adamant","Naughty",
    "Bold","Docile","Relaxed","Impish","Lax",
    "Timid","Hasty","Serious","Jolly","Naive",
    "Modest","Mild","Quiet","Bashful","Rash",
    "Calm","Gentle","Sassy","Careful","Quirky"}
    
    while true do 	
    
    a=memory.readdwordunsigned(0x03005D84)
    rng = memory.readwordunsigned(0x020249C0)
    timer = memory.readwordunsigned(0x030022E4)
    offset = math.floor(rng - timer)
    pidoffset = math.floor(memory.readdwordunsigned(pidpointer) + 0x988)
    pid = memory.readdwordunsigned(pidoffset)
    nature = math.floor(pid % 0x19)
    stepcounter = memory.readbyteunsigned(math.floor(pidoffset - 0x4,2))
    ids = memory.readdwordunsigned(0x020244F0)
    sid = math.floor(ids / 65536)
    tid = ids % 0x10000
    hpid = math.floor(pid / 65536)
    lpid = pid % 0x10000
    shiny = bit.bxor(bit.bxor(sid,tid),bit.bxor(lpid,hpid))
    
    gui.text(199,140, string.format("TID: %d", tid))
    gui.text(199,150,string.format("SID: %d", sid))
    gui.text(1,1, string.format("RNG Information:"))
    gui.text(1, 10, string.format("RNG Frame   -  %d", memory.readword(0x020249C0))) 
    gui.text(1, 19, string.format("Timer Value -  %d", memory.readword(0x030022E4)))
    gui.text(1, 28, string.format("Difference  -  %d", offset))
    gui.text(1, 46, string.format("tRNG %08X", memory.readdwordunsigned(0x03005D84)))
    gui.text(1, 55, string.format("pRNG %08X", memory.readdwordunsigned(0x03005D80)))
    
    if a == 0 then 
    	base = offset
    	iter = 0 
    elseif a > 0 then 
    	if base == base and iter < 1 then
    		iter = math.floor(offset - base - 5) 
    	else 
    		base = offset
    	end
    end
    
    if a == 0 then
    	if pid == 0 then
    		gui.text(1, 73, string.format("No Egg."))
    	else
    		gui.text(1, 73, string.format("PID %08X", pid))
    		gui.text(1, 82,"Nature: "..naturename[nature+1])
    	end
    
    elseif a < 65536 then
    	gui.text(1, 73, string.format("Egg Generating... please advance another frame!"))
    	gui.text(1, 82, string.format("tRNG seeded, no temporary PID testing yet..."))
    
    elseif math.floor(memory.readdwordunsigned(0x03007D98)/65536) == math.floor(a/65536) then
    	gui.text(1, 73, string.format("Egg Generating... please advance another frame!"))
    	gui.text(1, 82, string.format("TempPID %08X", memory.readdwordunsigned(0x03007D98)))
    
    else
    	gui.text(1, 73, string.format("PID %08X", pid))
    --		gui.text(1, 91, string.format("loc %08X", pidoffset))
    
    		gui.text(1, 82,"Nature: "..naturename[nature+1])
    	if shiny < 8 then
    		gui.text(1, 64, string.format("SHINY!!!"))
    	end 
    
    	if iter > 1 then
    		gui.text(1, 110, string.format("stone worked!"))
    		gui.text(1, 100, string.format("approx iter: %d", iter))
    	else
    		gui.text(1, 110, string.format("stone failed?"))
    		gui.text(1, 100, string.format("first egg PID result"))
    	end
    end
    
    	gui.text(1,130,string.format("Step Counter: %02X", stepcounter))
    if pid > 0 then
    	gui.text(1,140,string.format("Egg Generated, go get it!"))
    elseif stepcounter == 254 then
    	gui.text(1,140,string.format("Next Step might generate an egg!"))
    elseif stepcounter == 255 then
    	gui.text(1,140,string.format("255th Step Taken."))
    else
    	gui.text(1,140,string.format("Keep on steppin'"))
    end
    
    emu.frameadvance() 
    end
    

    fixed shiny check, fixed walking outside preservation

    • Like 1
  7. other crap not particularly related to savs/structure:

    For the C-Gear skin appearing in the memory, at delay 0x94 when booting the ROM the C-Gear skin's .psk is loaded at location 0x0224A444 in my English White version; but only has the tile building region.

    The final tile of the .psk appears at 0x02150760 as well. That's all of the psk I can find on that delay. It's probably then encrypted away as it's already loaded by the game.

    so, possible to AR a skin in? possible, but not probable. The sheer amount of lines needed to overwrite 9.5KB.. lol

    edit: looks like it processes each tile and then stores it away

  8. .psk Structure:

    Tile Building Region: 0x0-0x1FDFF

    0x20 per tile, referencing a 16 bit color for each pixel. 
    Each tile makes up a 8x8 block of pixels (64 total). 0xFF (255) tiles total.
    
    0x000 - First Tile
    0x020 - Second Tile
    ...
    0x1FB0 - 256th tile
    
    0-F to reference 0-F'th color in the color table, 
    build the 8x8 tile  (color pixel by color pixel) left to right, top to bottom.
    
    Set up the tiles in a 16x16 array, left to right, top down.

    Color Table: 0x1FE0-0x1FFF

    Only 16 different colors allowed, 16 bits (1 word) per color.

    Tile Arrangement: 0x2000-0x25FF

    Choose tile for 8x8 pixel arrangement.
    Move Left to Right, at the end of each line go to the next.
    
    16 bits to choose a tile from the array via (x,y) coordinates, when reading as bytes you would read as big endian (y x) sets.
    
    still not completely sure on the coordinate thing... viewing as 64 bits per line is the way to see it visually under a hex viewer

  9. Intro

    Since there isn't any information posted about how the C-Gear is planted within the save file, I might as well just explain how one would edit it. PokeStock is capable of editing the skin, but it's a pretty weird standalone program -- people may want to have their own program (in english) that can edit it. Plus it's good to know how it works!

    Background Information

    The C-Gear Skin is stored inside the save file as a .psk file ("poké-skin") after it is downloaded or edited. It's a pretty big portion of the save file, coming in at 9.50 KB of data -- that's around 2% of the entire save file's size. Visualizing it as an actual image is different, the .psk file format is not a .bmp or .jpg, and this is beyond me... PokeStock is able to visualize it and save it as a view-able image, however.

    Documentation of Save Structure for C-Gear Skins:

    0x52000-0x545FF 
    Contains the .psk data. 
    Calculate Checksum of this region, call it checksum(1).
    
    0x54603-0x54604
    Contains the checksum of the .psk data.
    Overwrite the current value with checksum(1).
    
    0x1C024-0x1C025 
    This is a Checksum Reference to the .psk checksum. 
    Overwrite the current value with checksum(1).
    
    0x1C02E-0x1C02F
    This is a Region Checksum of the reference checksums, which must be recalculated. 
    Calculate the checksum of the region 0x1C000-0x1C02B, call it checksum(2).
    Overwrite the current value with checksum(2).
    
    0x23F40-0x23F41
    This is a Checksum Reference to the previous reference checksum checksum.
    Overwrite the current value with checksum(2).
    
    0x23F9A-0x23F9B
    This is a Region Checksum of the nearby reference checksums.
    Calculate the checksum of the region 0x23F00-0x23F8B, call it checksum(3).
    Overwrite the current value with checksum(3).
    
    0x54700-0x54702
    This is a Checksum Reference to the previous reference checksum checksum.
    Overwrite the current value with checksum(3).
    
    0x54712-0x54713
    This is a Region Checksum of a dword which comprises of checksum(3) and zeroes.
    Calculate the checksum of the region 0x54700-0x54703, call it checksum(4).
    Overwrite the current value with checksum(4).

  10. The World Tournament feature (that deal with the old gym leaders and champions) has one piece of information on it that all the other fansites seem to have missed. Luckily, I pointed it out to the big guy that everyone copies from (Serebii).

    There is a small blurb saying that you will be able to download more special trainers to battle, so this could mean the trainers we see are special trainers (and the tournament is normally fought against regular trainers), and/or we could be seeing more trainers added to this game mode over time.

    man, that would be a fun thing to hack.

  11. I uploaded this Flying Pikachu i got from my Pokéwalker and it's showing Fly as an hacked move:

    http://www.pokecheck.org/?p=detail&uid=1069993

    Hacked / Event only (19)

    It also says it's an event move; which it is. The only reason certain events are recognized is because we have the wondercards to check against. If it is not normally obtainable in the handheld DS/GBA/GC series then it is not accounted for and is up to the user to check themselves.

    Creating an event moveset table is extremely time consuming, this time is much better spent elsewhere.

×
×
  • Create New...