• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.
M
Reaction score
0

Profile posts Latest activity Postings About

  • I can only pick what effect I want to use in an attack in Stadium 2, I can't make new effects and adding a modern PSS split is borderline suicidal. GSC simply doesn't have enough moves. You'd have things like Grass being only a special type because there simply wasn't any moves that could reasonably changed to a Physical Move. And Fire type would give you the same issues Electivire had in DP because Flare Blitz doesn't exist.

    And it's not like we can just add moves in, unless you know how to do 3d effects and insert them in the rom.

    Having things like a 90BP, Fighting-type, with 20% Flinch chance Mega Punch is really easy though, just change some bytes and you're done.

    I actually changed Ember into a modified Zap Cannon clone with 80BP, 100% accuracy and 100% burn rate.
    The main drawback is that you only get 5PP and Heal Bell users are more common due to it being a TM, so you gotta make your shots count.

    If you want to help me redesign the movepools to add things like moves that the Pokémons learn in later gens (Like Dodrio learning Jump Kick in SM but not GSC) or generally declone them so they fit their new stats better, (Like Dodrio doing every thing Fearow could possibly do but better.)
    I can share everything I know about Stadium 2 and the latest build with all the changes made to it.

    By the way, just to give you an idea of how things are currently playing out, here's a video of a full battle against R1 Red I made. This is probably his final R1 team, but of course it might change.

    https://www.youtube.com/watch?v=SwqhBCjcHiE
    Great to hear you got the hack working and also learned about asm hacking while at it :)
    In case you're sure you didn't do anything except for moving the code around like you showed me, this won't affect the functionality of the game at all unless a part of that routine is accessed from elsewhere.

    How you generally want to make changes to some routine(s) is to try to find exactly what to change so that you won't break anything when you write the change. Disassembly is better in this case as it's much more readable. I personally dislike hacking some existing routines especially for the fact that the routine cannot be just written without knowing exactly where to write it so that no original functionality is broken at the same time, or the routine won't lead into odd side-effects.

    I for example added a new asm hack for randomizing the level of wild pokemon a little bit based on its "base level" that you can set by editing wild pokemon data. When the battle starts, it called my new asm routine that drew a random number and based on what the value of this random number is and what was the level of wild pokemon, it either changed the level a little bit or left it unchanged. Naturally small-leveled pokemon shouldn't have their level being changed - at least not drastically while the same thing can surely be applied for high-leveled pokemon.
    Anyway, I thought it worked just fine after testing some encounters. I even caught a pokemon or two and they seemed alright so I was fine with it. Much later on in development I noticed that the offset where my routine was called from was accessed both during the start of the battle, and the end of the battle in case the pokemon is caught (for getting the level of the encountered pokemon again? maybe - this should be in ram so I don't know why is this). Anyway, had to figure out where to move the call "new asm routine" instruction so that it was only called upon start of the battle and things finally worked the way I intended.

    I don't remember what the solution to the problem was exactly, but because the "main routine" where the call "new asm routine" was executed in both cases, the solution was probably to follow the main routine and see how it continues from this point until it "branches" into "start of the battle" and "end of battle if pokemon caught" parts, and next I just wanted to add the call in "start of the battle" code branch.

    For following the code like this I used both asm editor, but also emulating & debugging tool called BGB. It's a gbc emulator designed for hacking so that it possibly shows some things related to ram more conveniently than VBA, but it also allows debugging. Debugging practically means that you can pre-determine an offset that is either accessed or read or wrote into during the execution of the game. That's probably a bit confusing notation, but reading or writing practically means accessing to some offset in rom or ram. You could for example set a breakpoint to offset 23:6A74 (Iconpointers address) and the game should stop executing at the address where we have "ld de, Iconpointers" instruction. Likewise you could set a breakpoint to address 23:678C where we have "call ReadMonMenuIcon" instruction which is executed when the game is run. For some reason bgb doesn't allow you to stop executing at any point in code, but rather only at an instruction that has a 2-byte pointer as its parameter (here we have "ld, de" instruction with 2-byte parameter). I don't know why is that.

    Anyway, you can test with bgb that your own code is run during the gameplay by setting a breakpoint to that address 23:678C and see what happens next when you start executing code one instruction after another. You should also test the same functionality in an unedited rom file if you're unsure what should happen. Also keep this first line I commented in mind "this won't affect the functionality of the game at all unless a part of that routine is accessed from elsewhere.".

    Also one thing that comes into my mind is that in case you're not planning to remove all the code starting at 23:678B, you should only move one instruction and not the whole routine to the blank space area. That way you can easier avoid bugs that could occur on accessing this routine from various places and not just one (which would mean that your code should work just fine). So in case it doesn't matter where you write your own new 3 bytes, you could for example replace the instruction "CD 74 6C" with "CD A0 6A", and in $8EAA0 write that CD 74 6C in the beginning followed by your own code. Also here I just noticed that in the code you provided you had moved the routine into $8ECA0 where "CD A0 6A" doesn't point into. Is this also the case inside the rom file?
    One more thing is that you can try to look at what I have written myself. I think I have changed this same routine in DE myself :)
    Also, sometimes it's possible to quite easily just copy paste asm code back- or forward. If you do this though, you may have to change some relative jump codes (jrs) along with making sure no other routine accesses parts of this code you moved and if some do, change those pointers of course.
    If there is no room for adding new stuff, you can for example replace one 3-byte instruction (= 1 byte -instruction with two 1-byte parameters) with a call command. Now you can write your own stuff along with that instruction you replaced in the subroutine you called.

    You could also do the same thing for sets of instructions. If you for example move 2 2-byte instructions, just add one nop-command after the call code.
    Apparently there was something wrong with the patch I used and the one you have works properly then.

    IPS Peek is simply an editor that is designed for viewing what IPS patches do. You can view them with a hex editor, but that is not a very user-friendly thing to do. You could somewhat compare viewing contents of IPS files with both IPS Peek and a general hex editor to mapping the data of some map with a map editor or a hex editor. Both can be done but mapping with a hex editor isn't just really convenient at all. You can find IPS Peek in romhacking.net.

    As for what goes to comparing changes between rom banks of my hack and yours, you could for example copy the data of those rom banks from my hack to an unmodified pokemon silver (u) rom file (which you must have a backup of) and then make an ips patch between the unmodified one and this modified one (with only parts of rom banks 5 and 23 changed then). Now you can view with IPS Peek what this patch file does and in other words, what I have written in those two rom banks.

    P.S
    You can also use IPS Peek for checking what that minisprites patch file does exactly.
    I took a look at the notes and the coding related to the minisprites is simply horrible... but it somehow works though.

    There are quite a lot of changes involved in getting this to work properly. Apart from making the minisprites to work in the menu it involves:
    1) Adding my horrible coding hack that makes it possible for menu sprite pokemon to appear properly on maps, and at least
    2) Making a hack for the poke dolls in player's room to appear properly after my horrible hack is inserted.

    I could try copying those changes I have done to a clean Gold rom file, check that it works properly and just hand an ips patch over to you. But I'm not doing that :P Instead, I can give some guidance and you're going to write the required (very simple!) asm routines in your own for making it possible for the sprites to function in the menu. After that is done, I can try to make an ips patch which you can use to apply that horrible hack for making it possible to see the pokemon on maps.

    First of all, if you haven't taken a look at the asm video tutorial of mine yet, do that before trying to apply the first change. If you have, you should be able to accomplish this with a little bit of guidance and hints :) Before doing anything, make a copy (or several copies) of your rom file at this current state though. Use Gameboy Assembly Editor for the following task:

    Starting at 23:6894 we have a routine that is accessed only for loading the picture of a pokemon. First it loads register a with value in C5BE. In C5BE we have an index that refers to a graphics pointer in following pointer table.
    Next in the routine it loads de with 6A56 which tells where the graphics pointers of pokemon are located. The first pointer is for example A4 6A which points to 23:6AA4 (8EAA4). If you open that offset with TLP you can see the graphics of pokemon menu sprites there. The first 0x80 byte graphics entry is used for Poliwag (along with Poliwhirl, Poliwrath, Politoed and maybe other pokemon as well), second is picture of Jigglypuff which is also used for several pokemon and so on.

    Now what happens here is that if register a had value 00, it would load the graphics of Poliwag. If it was 01, it would load graphics of Jigglypuff and so on. The logic for getting the graphics pointer for the pokemon based on the value in C5BE is between 23:6898 and 23:68A2. Following that logic we have two interesting instructions: "ld bc, 2308" and "call 0DFE". "ld bc, 2308" loads the rom bank where the graphics are stored (= the same rom bank we're in), 08 refers to "how many bytes to load" multiplied by 0x10 (0x8 * 0x10 = 0x80) and thus it simply contains the functionality of using that graphics and telling each graphics entry is 0x80 bytes of length. Following that we call 0DFE where is the actual routine for getting the graphics based on values of bc and hl (in hl we now have the pointer to the graphics based on value of C5BE while in de we only have the pointer to the table of graphics pointers).

    Now what you can do is to get the graphics data from the patch in Skeetendo Inc., copy them somewhere in the rom (they take 252 * 0x80 = 0x7E00 bytes of room, so you want to reserve 2 consecutive empty rom banks for them), and hack this routine so that....

    Ah - scrap that. The value in C5BE is actually the pokemon number instead of graphics pointer index value which it happens to be in the original game actually. Chamber's original minisprites hack changed that. I'm not sure where C5BE gets its new value and trying to follow this routine already took way longer than I wanted to.
    The thing is that this kind of stuff isn't easy and Chamber has also wrote a bad solution to the problem in terms of being able to follow as an outsider what is going on with it. Also the ips patch he gave doesn't work 100% properly but has wrong addresses in it although the data seems to be correct when you just insert it into the right place for yourself.

    You could try checking with IPS Peek for instance, what kind of changes I have done in Dark Energy to rom banks 0x5 and 0x23 and try to implement those changes into your own hack as well. They should be enough for using minisprites hack in your hack as well although you may have to work something out (especially if you have written new data in those rom banks).
    CSUBP from Route 18 to Fuchsia City is 6641 because it happens to point to the block that is located 3 blocks above player when he enters through the upper-right most tile from Route 18 to Fuchsia City. The "reason" (maybe not but my intuition is the following) for CSUBP taking those 3 blocks into account is that when you play the game, you can see 4 tiles from each side of player but to the right you see 5 (= so 3 blocks).

    P.S
    I meant you should follow the connection between Fuchsia City and Route 15 (didn't check the number of this one earlier) because there Fuchsia City is "above" Route 15 and you're aiming to the same thing by connecting Route 32 to the new sea route right? There you for example see that CSUBP from Route 32 to Fuchsia City is calculated as the block where you would end up if you entered Fuchsia City from the upper-left most block of Route 32, and to that, it goes 3 blocks to both left and up (because that is as far as the game loads the blocks away from the player, and 5 tiles is seen to the right after all).
    If you're confused with Width and Height values, I think Width is the actual width (= X size) of the connected map and Height is not the Y size but rather the width of the connection (in blocks).
    In this case since Route 32 is above the sea route where you connect it to, you want to set the Height value to the Y size of the sea route if Route 32 still "continues" (in Y size) after the connection to the sea route ends. If it doesn't, the Height can be at maximum the "Y size of Route 32 - 12" (where minus 12 comes from starting the connection in Y block 12).

    I'm not totally sure about this though so don't take that as absolute truth about connecting the maps. If it doesn't work like this, try to test what kind of Height gives the right result. I usually have an idea of which values could work and then simply test whether they do or not. There are often a couple of errors there, but if I for example see that some block that is supposed to be above the player is instead 4 blocks to the left, I try the connection by changing X alignment by 8 (2*4) or X Movement of Connection Strip by 4.
    I used to remember this better but I haven't worked on connections much lately.
    I'm not really interested in taking a look at the connection myself and figure out what values to put where and so on because it would take me a long time. Usually I mess around with one side of a connection for half an hour if it is a difficult one to get right. What I do is to put a warp point close to the connection, and save somewhere where I can warp there easily so that I can make the map load properly before trying out if the connection works or not. Once one side seems to work properly, I try the other one.
    Anyway, since Route 32 is "above" the connected map between Route 32 and Cherrygrove City, you probably want to take a look at an original example where the game has this kind of a connection. The ones from Vermilion City and Fuchsia City to the right are probably like this (although I'm just guessing here without taking a look with Johtomap).
    I have recorded some video tutorials in youtube. Not sure how much it helps but you can try looking at video tutorials part 6 which covers asm hacking - at least sort of. I don't remember what I talk about in that video exactly, but taking a look wouldn't hurt :)
    And yeah - you're definitely going to have to learn how to both read and write code in GB/C asm. Without knowing to, all you can do is to map new areas and script events (pretty much). If you want the game to have some new functionality, the only possible way is to code it in your own.

    Not sure how much better I can explain the way to edit HM moves than what I already did, but try to delve into that post and understand what I meant. In case you need help with something in particular with it, feel free to ask though. But the stuff in it is pretty simple to understand once you know what different GB/C cpu instructions do.

    Connecting maps isn't easy, but it's not undoable either :) Practise by taking a look at existing map connections and try to figure out why different numbers are what they are. After you feel like you've at least somewhat got it, you're ready for trying to make your own map connections. Left <--> Right connections which both have their uppermost block on the same Y "level" (take a look at Route 29 <--> New Bark Town connection for instance) are "easy" to make and the same goes for Up <--> Down connections which start at the same X level. The ones that don't (for example Cherrygrove City <--> Route 30) are "difficult", and for example that one has non-zero "X alignment" and "X movement of connection strip" values because it's an connection between Up <--> Down (and the maps don't start at the same level of X).

    I applied the minisprites routine the way it is, but hacked the routine that loads the image of a person event depending on the picture number. The routine in my hack works so that if I set the picture number of a person event to be of type 1xxx xxxx (= highest bit is 1, and thus byte value 0x80 or larger) it loads an image of a pokemon instead of a normal person event. I don't remember what (if anything) I did with the daycare but that also works properly in DE. I do have some notes lying around of these changes though and making them is similar (if not identical) in Gold although I'm hacking Silver.

    The whole map data is loaded into ram when you enter the map so there is indeed a limit. However, the limit is very large and it's actually 0x400 (= 1024) bytes (http://datacrystal.romhacking.net/wiki/Pok%C3%A9mon_Gold_and_Silver:RAM_map#Misc) as the map data is loaded starting at $C700. This means that you can have any kind of a map where the multiplication of X and Y sizes is at most 1024. What probably happened with you there is that if you changed the size of the map data, that probably broke the map connection to that map (and possibly out of it as well).
    Well first of all, that 'RAM Map' just stands for the documentation of what's stored in ram and where during the executing of (= playing) the game. When you for example write neat new scripts, you sometimes need to play around with the contents of ram (more than by for example checking whether the player selected Yes or No from a "yes or no box").

    I just noticed that I actually have a good and funny example as my profile video of what you can do by playing around with contents of ram so go and check it out if you have a little bit of spare time. What I do there is to make the player select a pokemon from party menu that refers to Super Onix. This operation happens to store the "slot" of Super Onix somewhere starting at ram address D000+ (some of the addresses starting at D000 - for example D002, D004, D005, D007 (I think?) are used for return values of different operations. Here selecting the pokemon (which is a predefined in-game script) stores the return value (= party slot) in one of those addresses if I remember right). Once the party slot is stored in ram, the value at DA22 (= party pokemon count) is changed into 01, and the original amount is stored somewhere safe so that party can be returned back to normal later on after the battle ends. Next since Super Onix was in slot 5, it has to be moved to slot 1 for the battle. This is done by swapping the datas of slot 1 and slot 5 pokemon. If you look at the ram map, you can find the information of each pokemon as 0x30-byte data structure (= Pokemon Settings) + Pokemon name + OT name data. Their addresses are known because we know the other pokemon to swap is in party slot 1 (obviously) and Super Onix in party slot 5 (as the predefined menu selecting script told us). Based on this information we can use a "magic trick" (= asm script) to swap their datas around. Next the battle begins and after the battle ends (before blacking out), the party count is returned to what it was before. :)

    What comes to trigger table problem, if you repoint the table elsewhere, you only need to use one more byte of ram for a trigger flag. You should be able to put it in address DEFF for instance. Like I mentioned in my previous message, there should be free space before DF00 which you can use. Not sure how much though if you plan on keeping the functionality that's in upper floor of every pokemon center. Those things (link battles and trades) use wram (= work ram) starting at DEC0 or so and I don't know where their usage of wram ends. Between DF00 and DFFF we have ram area reserved for a thing called stack. It's something you want to be familiar with when you start to do some recoding of the game (using assembly).

    Anyway, you indeed have to change where the game stores some information in ram in case you want to make the item pocket of general items larger than what it is right now. You could possibly make the key item pocket smaller and give yourself some room that way for instance. That would involve at least changing the start address of key item pocket, but that probably won't be enough.
    Take a look over here (https://hax.iimarck.us/topic/541/) or here (https://hax.iimarck.us/topic/6422/) where we have discussed this "issue".
    Also noticed your last message here just now. You have written it in your own Visitor Messages list so I was no way notified about it.

    I haven't used pokecrystal either, but I know how it works in general as I have been doing programming for a couple of years now (and have plenty of repositories in Github myself). You basically fork the repository, clone it to your PC and make changes with a text editor that you like. I might use SublimeText or a similar tool if I was editing with OSX. *haven't done much text editing with Windows, but you ought to find a good editor for doing that if you take a look.

    Basically, you write changes to the code and data with a text editor and then compile a rom out of the asm files. All the data for building a rom file that matches the contents of "Pokemon - Crystal Version (UE) (V1.0)" is there as described in README.md. For compiling process you use a tool called rgbds I believe (not really sure about this). It's made to recognize the "text" you write into those asm files and knows how to handle it so that it can build a GB/C rom file out of that text code. Some programming languages work in a similar way; you write readable program code (in textual format) with them, click "Compile" button, "magic" happens and a runnable program (for example .exe file) comes out.

    To expand the trigger table you have two options:
    1) repoint the table elsewhere, or
    2) repoint the data following the trigger table elsewhere. Both should be totally doable yet it's impossible to say which process is easier without taking a look at the code using the trigger table, or the code accessing the data/code following the trigger table at first. If the case is simple, all you have to do is change one asm instruction like "ld hl, 4000" where 4000 would refer to the start of the trigger table (in 0x94000) in option 1. Along with that there would be some code telling which rom bank to look for the table in. Also, it's practically possible to code for accessing the table is in the same rom bank with the table, but this is hardly the case. Compilers happens to work so that situations like this just don't seem to come up and thus most references (= pointers) point to addresses following the pointer and not backwards. There are exceptions to this as well, but not in situations as we have here. It would be pointed from the same rom bank if for some reason it would be accessed from another rom bank, but also from the same rom bank which doesn't seem a probable case.

    Nevertheless, what you really want to do is to replace some existing map's script so that it doesn't need an entry in this trigger table. That makes it possible for you to not only have a free slot in the trigger table but also have a free ram address where to store the "trigger flag". You have probably noticed that trigger tiles have flag/number attached to them. These are used for letting the game know whether or not the event attached to the trigger tile should be executed when you step on the trigger tile. The entries in the trigger table consist of both map information (bank, number) but also a ram address. This address is the place where the information about the trigger flag is stored so it basically takes one byte for each entry. If you wanted to expand the table, you would have had to reserve one byte of ram for a new flag (which isn't really so bad - there is free space before address $DF00 in WRAM).

    I was planning to link you to Pokemon Gold RAM Map from datacrystal, but it looks like they have removed that resource completely :/ You wouldn't happen to have it in your PC, would you? Luckily I do and I should probably spend some time uploading it for others to be accessable as well :)
    Anyway, I took a look at its contents and the items are stored starting at $D5B8 (and the value in $D5B7 tells the amount of items, or practically, where is the position of CANCEL in the item pocket :D ). That data continues all the way till D5E0, and starting at D5E1 we have a similar list of key items (where D5E1 is the key item count). Following that we have ball pocket (starting at D5FC), and following that the stored items (starting at D616). You can have up to 50 items stored in PC, so you could make more room by for example swapping the addresses for PC storage and item pocket. That way you could have 50 items in pocket and 20 in storage. If you want to have more items without doing tricks such as this, you could try moving some data around starting at the key item pocket.
    Thanks for all the responses!

    I'll try the Sprite for JohtoMap again soon.

    I've posted in Skeetendo. I set up pokecrystal disassembly thanks to a YouTube video but I have no idea how to use it...I won't ask you to explain it to me but it's been a struggle to find any resources on it...I might just have to scrap waiting a day.

    For the trigger table, would extending the trigger table he as easy as repointing the table to have more free space?....though as I think about this I imagine that it would involve repointing every map to the new trigger table?

    I might write up a guide to map script headers with all this help you've given me.

    Do you have any idea where to increase maximum inventory space and/or create a new pocket?

    It looks like the last thing I'll need to learn after triggers is map editing which I'll attempt more research again before I ask you questions about that.
    "A third question. I have a great script going using Kurt's Daughter to make my own Celebi event. I have her making a ball (Currently master ball since premier ball isn't programmed in Gold). Anyway it works great except I can't figure out how to make her wait a day. I saw Kurt's script use Flags 00 00 and 4F 00 but neither of them work. 00 00 resets when the map does but not for Kurt some reason. 4F 00 has a better effect because it stops Kurt's offering to make Balls but doesn't reset after a day. I cannot figure out what flag resets after a day."

    Haven't paid any attention to this, and I don't know myself either. You could ask for help in Skeetendo, try to track down the "same" code in pokecrystal disassembly or find the solution straight in the rom file.
    "A second quick question is that adding a trigger in JohtoMap does not appear to correctly change the map header/add it into the right table? So I'll have to manually do more work on that?"

    Yes, you will have to work it out. Either get rid of something that is originally in the game, or expand the trigger table to have more room. You could probably make room for a new entry by trying to find an original entry that only uses a map script from the first part of the script header (and doesn't have any trigger tiles on the map) which could as well be executed from the second part of it. I don't know if an entry like this exists in the trigger table or not, but if it does, it can be changed.
    The problem you're having with Articuno and Moltres sprites is that Johtomap shows the spritesheet incorrectly. You can have 9 movable person events and 2 that just stand still (= trees, item balls, rock smash rocks etc.). I think Johtomap shows there are 12 slots for person events while there are actually only 11 (9 + 2).
    Alright - got back to you there :)
    If this solution doesn't work out I could test a similar thing myself. I don't see what's going wrong though.

    You could also try to do something else in the script called from the script header to see if the script is executed at all.
    These are something I picked up from notes I have written (years ago):
    Surf ASM: $03:4A40 -->
    ASM script for HM Cut: $03: 5190 -->
    Script for HM Strength: $CD4C

    Edit:
    These addresses seem to be a bit off, but for example at 03:4A1E it loads de with $001D which stands for badge of Morty as seen here: http://www.pokecommunity.com/showthread.php?t=127374
    Following that we have call $4764 which most likely checks whether bit $001D in bit table 2 is set. These two instructions you would want to replace with a check whether you have item HM03 in your inventory or not. You may also have to change following instruction jr c, 4A47 to something else depending on what kind of result you want your routine to give (depending on whether the player has item HM03 or not).

    This kind of check is easy to implement. According to ram map (http://datacrystal.romhacking.net/wiki/Pok%C3%A9mon_Gold:RAM_map), HM03 seems to be stored in address $D5B2 so you can replace

    ld de, 001D
    call 4764
    jr c, 4A47

    with

    ld a, $D5B2
    and a, a
    jr z, 4A47
    (+ two nop codes to match the same amount of bytes for instructions in both cases)

    to make it possible to surf without having Morty's badge.

    Edit2:
    Figured you might not even be interested in removing this functionality and what's more, the game still checks whether some of your pokemon knows the move. This checks follows the badge check as you can see by taking a look at the code. "ld d, 39" instruction seems to load the move (Surf = 39) into register d and then it calls a subroutine at 4785 which probably checks whether some of your pokemon knows the move which register d refers to. So get rid of this check instead and replace it with that HM03 item check.

    All the other routines are similar, but I haven't taken a look at where they are exactly. I found these by backtracing code, but you can try looking for other usages with "ld de, [badgeBit (here 001D)] + call 4764" because that check is probably used in other situations as well. Same most likely goes for "ld d,[moveNo (here 39)] + call 4785".
  • Loading…
  • Loading…
  • Loading…
Back
Top