![]() |
ASM Workshop
IntroductionHey, I decided to make a thread for ASM workshops and such. Hopefully we can get this thing rolling and help people who are interested in ASM hacking to learn how. In the early phases of this thread, the problems and discussion will likely be basic. However, in a couple of weeks, I hope to touch on topics of much more complication. We'll be running this thread in a combination of a Skype Room and thread, so posting on whichever you're comfortable with is fine. Some things you'll need to get the best benefit from this room: - Skype. Add fbi.agent7 - VBA-SDL-H - IDA (I'll link you if you ask me on skype) - Knizz's idb (see his signature) So far ...Week One: Spoiler:
Posting rulesI'd just like to impose a few rules about posting your solutions here or on the Skype chat. Basically I don't want people openly posting their solutions on this thread and spoiling the fun for others who are still working on it. So if you've finished any of the above routines (fully or partially) and feel like sharing, go ahead and post them, but put spoiler tags. I'd also like posted routines to be of this format: Quote:
That's all for the rules. Oh, don't break any PC rules of course :P People ParticipatingMentors: FBI, ...maybe more soon? Students: -a lot, removed names because FBI is lazy to maintain :) |
Do I need to ask permission to sign up, too? :P
|
Quote:
Send them to his skype at fbi.agent7 |
Quote:
ex: What is a pointer, basic hex editing, how to insert a routine, ect. Quote:
We're going to be starting the workshops now. Lets try task #1-2 first. Task #1 1) Give the slot number of first Pokemon who isn't full HP First of all, each Pokemon is stored in the RAM. There's a specific data structure in which they're stored in. Here's a picture I took from Bulbapedia of how it looks like in RAM: http://i.imgur.com/kgsnGjw.png The above is obviously the structure for a single Pokemon. There will be six in your party and their data will be stored in succession. Like this [0x64 bytes (First Pokemon data)] [0x64 bytes (Second Pokemon data)] [0x64 bytes (Third Pokemon data)] [0x64 bytes (Fourth Pokemon data)] [0x64 bytes (Fifth Pokemon data)] [0x64 bytes (Sixth Pokemon data)] If you have less than 6 Pokemon in your party, say you have five, then the last 64 bytes will be zeros. Getting back to the above picture of the data structure, you'll notice that Code:
The Pokemon Data structure for the first Pokemon starts at 0x2024284.So if we add 86 bytes (0x56 in hex) to 0x2024284, we get the current HP of the first Pokemon at 0x20242DA. Add 2 more bytes to the address to get the total HP of course. Here's a screen shot of the Current HP and Total HP highlighted in RAM of my Anorith: http://i.imgur.com/I6YGDMS.png Now, we know how to get the current HP and Max HP of the first Pokemon, but what about the rest? Well, you just add 0x64 to the address 0x2024284. Since they're right beside each other and the size of each Pokemon is 0x64 bytes. Here's some basic starter code you can use to help ease the process: Code:
|
MAGIC TASK 1
Give the slot number of first Pokemon who isn't full HP Partial Solution: Spoiler:
|
Quote:
Code:
Magic's Routine /w comments: Spoiler:
Pretty close Magic! There's a few things with the algorithm that can use improvement, but the gist of it is good. |
MAGIC TASK 1
Give the slot number of first Pokemon who isn't full HP Partial Solution/Final Solution?: Spoiler:
|
Task #2
2) Make the Player's name "Baka-san" First of all, like the Pokemon data structure the Player also has it's own data structure. Here's something from HackMew's knowledge tutorial: Code:
However, the game itself needs retrieve things like the player's name, gender, ID ect, all the time. So then, the game needs a way to keep track of where it even put this data. This offset is at 0x300500C. At 0x300500C, the game stores a pointer to where the player's data is currently located. You will need to go to 0x300500C, and load the 4 byte address. From there, go to that address, and insert: "BCD5DFD5FF" - which is Baka in hex. You'll notice that "Baka" is 4 letters, but it's taking 5 bytes. That is because every string (i.e words) in FR/LG/R/S/E are 0xFF terminated. So you need to add that "FF" ending to tell the game that this is the end of the name. Here's some starter code: Code:
3) Make all Pokemon Shiny -Task removed- I now see that this is more complicated than what should be covered this week. In time, we'll come back to the famous, "Shiny Pokemon" problem :) Challenge task: 4) Can you delete a Pokemon? Recall from task #1's hint, that I said if a Pokemon slot is empty, then that 0x64 chunk of RAM will be set to 00s. Basically all we want to do is set an 0x64 block of RAM to 0x0s. No more hints on this one. I think I've made it super easy now. Anyways, there will be a bug, when you open the Pokemon Menu, the missing slot will look weird. We'll fix this problem in a coming session. For now, just try and set the RAM byte using the str command. |
Quote:
Spoiler:
Some things to keep in mind: Code:
Code:
Code:
Alright Magic, I approve you to move on to the next task. Also, if you don't mind, I'd like to use your solution for a solutions post I'll make in the future. Yours is a good example of a do while loop, I hope someone makes one of a regular while loop soon too. EDIT: I've added some links to some heavy hint posts in the first post~ Is this week a little too hard? I think it might be, we are doing RAM pointer handling, looping, and writing to RAM. |
MAGIC TASK 2
Make the Player's name "Baka" Partial Solution: Spoiler:
|
Quote:
Code:
|
UPDATED
TASK 3 MAKE POKEMON SHINY This is an uncomplete solution because I haven't done the trainer and egg part (I really don't have much time). I have only shinyzed wild pokemon. Solution so far tested: (If you want it to activate in game, I think it's possibly simple because you can use a variable to do conditional branch, to either run the function or not) Spoiler:
The new solution which also work for givepokemon: Spoiler:
Reference: Hackmew |
Sorry, I can't see anything. I'll come back tomorrow when this website becomes browsable again.
|
Alrighty, this is happening, thanks FBI firstly. Here I go:
Spoiler:
I tried to get maximum efficiency for these routines and minimal register use. Any comment on deletion strategy? May I ask: - When do we need to push lr and pop pc? It is taught in most tutorials but I never have used them. - Also I pushed r2 and assumed this register was 0. Is this correct to assume so or would I have to mov r2, #0x0 at the start? |
Quote:
Remember, that if a Pokemon is not full HP, we return their slot number. Here, you're jumping to the end if they are full HP. Instead of: Code:
Finally, the last thing to think about in your solution for task one is this part: Code:
Task number 2 looks very well done. Good job. But you're forgetting to push {lr} and pop {pc}. This routine is going to be called by another routine using bl or a linker. So you need to push the link register and pop pc. Otherwise, as it is now, it will not return and instructions in the next line (beyond this routine) will continue to execute until the whole thing crashes. There some things wrong with task 3 in your solution while I will address now. First of all, when you're storing bytes in RAM, you need to use str or strb. In both of your solutions you are trying to load 4 bytes at a time from pkmnData, then you're setting the register to 0 (by using lsl and bit shifting all 32 bits), but you could use mov instead. Anyways, the point is, you're setting the register to zero, not the actual RAM at the offset. You'd need to use str/strh/strb for this. I recommend using strb first, and then expanding your solution. Again like the last routine you've forgotten to push/pop lr and pc. Look at the explanation I gave for your task 2 for more info. Finally, like Magic had, you also have double branching statements. Note that: Code:
Code:
Quote:
Quote:
|
Quote:
|
Quote:
|
Quote:
|
Alright, that was week one. Last week we didn't really need to do much "finding", debugging or searching. I tried to keep stuff simple, if you knew the OP codes and how to use them, last weeks tasks should've been rather simple. In the case you were unable to finish, and would like more time, then go ahead and try finishing. There's really no due date, as everything is archived so you can attempt/look at hints/solutions whenever you need to.
Moving on, I will now post solutions of last weeks tasks. Explanations will follow some time tomorrow when I have time for breaking and analyzing thought processes for writing these. Task #1: Slot number of a Pokemon who isn't full HP Spoiler:
Task #2: Setting the Player's name Spoiler:
Challenge task: Spoiler:
Challenge task stmia/ldmia edition: OK, you don't need to do it this way, and this way is slightly more complicated too. Though faster. We'll look at memcpy, memset, strcpy and such at a later time. Code:
|
So I practice at task 1 all night (literally haven't went to sleep).
To no avail I still can't seem to figure out how you would loop it and do the comparison of 6 possible Pokemon's CHP and THP. Nor could I understand just how to keep track of the slot of the Pokemon ergo 0-5. Here is what I came up with Partial Routine(if it can be called even that) Spoiler:
I tested it in a clean rom as well and it does not work in any sense... I couldn't even get the game to bug out or freeze >_< sadly hahahaha Well any advice and help is much appreciated an thank you for your time Ps also thank you FBI Agent for this thread |
Quote:
Speaking of solution videos, I made a solution video for task #1. I'm thinking the video is too long, and too indept. Would you guys prefer briefer and less detailed versions for the rest of the tasks? |
Quote:
Also, some life advice: sleep. A good night's rest can make the solution yesterday's impossible problem clear. The same goes for taking regular breaks - your mind works out solutions even when you're not actively thinking about something. Now, lets get onto your problem. From glancing at your code, it's clear you are missing the point of task one, which I'm guessing was to teach you how to use a loop. You are just copying and pasting code for each of the 6 Pokemon. A loop is perfect for this kind of problem, as you just reuse code perform one action to perform that action multiple times. Below is the anatomy of a basic loop to help you understand the concept. Code:
Quote:
|
Quote:
|
This thread seems very promising. Thanks FBI!
Earlier, I did two first tasks, but I made some mistakes in them and looked up solutions. That's why I tried to do the challenge task on my own and I think I got it right. I tested my routine and it works fine but after deleting a pokemon weird things happen. I can't do anything about it though. My code: Spoiler:
I know that my code could be smaller but I don't have any idea how that could be done without messing it up. |
Quote:
What weird things happen? To make your code neater (and more maintainable) you can calculate the amount to add to the party address instead of the whole "check_which_one" thing. Since you have the slot number in r1 and r0 is free: Code:
Code:
Other optimizations include:
EDIT: I noticed one error: At the top you do: Code:
|
| All times are GMT -8. The time now is 2:31 AM. |
![]()
© 2002 - 2018 The PokéCommunity™, pokecommunity.com.
Pokémon characters and images belong to The Pokémon Company International and Nintendo. This website is in no way affiliated with or endorsed by Nintendo, Creatures, GAMEFREAK, The Pokémon Company or The Pokémon Company International. We just love Pokémon.
All forum styles, their images (unless noted otherwise) and site designs are © 2002 - 2016 The PokéCommunity / PokéCommunity.com.
PokéCommunity™ is a trademark of The PokéCommunity. All rights reserved. Sponsor advertisements do not imply our endorsement of that product or service. User generated content remains the property of its creator.
Acknowledgements
Use of PokéCommunity Assets
vB Optimise by DragonByte Technologies Ltd © 2023.