Anyway, first off, you must realize that Hex stands for Hexadecimal, which is a base 16 number system. This is similar to decimal, which is a base 10 number system. So let's learn the numbers, shall we?
Decimal: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Hex: 0 1 2 3 4 5 6 7 8 9 A B C D E F 10
As you can see, counting to 16 in decimal is equvelant to counting to 10 in hex. Hex is pretty much decimal with six extra values tacked on to it.
Now, how do we hack Sonic with hex?
Well, as you may or may not know (hopefully may), everything on a computer is represented by binary code (AKA 001010101110, etc). Of course, editing and viewing ROMs -- or ANYTHING -- in binary alone is extremely impractical (unless you're dealing with bit-based compression algorthms and opcodes...). So as us humans oh-so-hate things being complicated when they don't have to be, we found a way to simplify binary; Using hexadecimal.
Hex is dealt with by the byte in most operations. In case you don't know your terminoligy, let's fix that right now:
Nybble - Half a byte, or a single digit. "A" would be a good example.
Byte - Full hexadecimal value, equal to 8 bits, and two digits. Something like "01" or "1C".
Word - Two bytes, or 16 bits. Need I really explain this more? "010A" or "1550" would be good examples.
Long(word) - Two words, or 4 bytes, or 32 bits. "00012345' would be a good example.
FYI, byte types are advanced in powers of 1,024. 1,024 bytes makes a kilobyte, 1,024 kilobytes makes a megabyte... etc etc down the whole damn chain.
Now that you know your basics, we can start editing and move on to pointers and such.
So first off, what is a pointer? Well, a pointer is pretty much what it's called -- a pointer. It's a hexadecimal string that lists an offset in ROM in which to locate data. (BTW, an offset is just the current byte in ROM that you're at. $012345 [out of $200000, though that bt's redundant] would be an offset.) There are little endian and big endian processors, and the Megadrive happens to use a big endian processor. This means addresses are read as is, so things are a bit easier to deal with. For example, if my pointer read 00123456, first I'd split that into bytes. This becomes 00 12 34 56, which is the address at which the pointer wants to locate data.
Let's make a practical example. Let's say you wanted to edit Sonic's art to add more frames to some animations (which you should edt mappings for later, but :P). You can't add them to the current location because there is vital data after Sonic's art. So what we should do is expand our ROM and add Sonic's art to the end so we can add as many frames as we want.
We'll say (it isn't really) that the location for Sonic's art is at offset $55439. However, we don't know where the pointer to his art is! So guess what? We're gonna find it. Remember how I said pointers are byte seperated offsets in ROM? Well, take the offset of Sonic's art and extend it to a longword. Originally, $55439, it becomes 00 05 54 39. Run a search for this in the ROM and you should get at least one result. We found our pointer!
Now, let's say the end of the ROM is at offset $100000. First we take Sonic's art and stick it at the end of the ROM. Now all we have left to do is to change our pointer to locate our new art set, rather than the old one. So we take our pointer -- currently 00 05 54 39 -- and change it to the correct offset, $100000. So take our offset and extend to a longword and seperate into bytes. This gives us 00 10 00 00. We then replace our pointer with this new value, and viola! Our new art is fully working and intact. You can even delete the old art and it'll still work!
Hope this helps some people understand how to use a hex editor better. I may add more examples if requested, but this should be enough to get you going on your own as a better hacker overall.