Difference between revisions of "Pointer"

From Data Crystal
Jump to: navigation, search
(GameBoy Pointers -- wrote information about 3 byte pointers)
Line 21: Line 21:
 
<li>Take the last four digits of the offset, and cut off the rest</li>
 
<li>Take the last four digits of the offset, and cut off the rest</li>
 
<li>The most significant bit will always be 0, and the second most significant bit will always be 1. In other words:</li>
 
<li>The most significant bit will always be 0, and the second most significant bit will always be 1. In other words:</li>
* If the offset is from 0000-3FFF, add 4000 to the offset.
+
* If the offset is from <tt>0000-3FFF</tt>, add <tt>4000</tt> to the offset.
* If the offset is from 4000-7FFF, do not add anything to the offset.
+
* If the offset is from <tt>4000-7FFF</tt>, do not add anything to the offset.
* If the offset is from 8000-BFFF, subtract 4000 from the offset.
+
* If the offset is from <tt>8000-BFFF</tt>, subtract <tt>4000</tt> from the offset.
* If the offset is from C000-FFFF, subtract 8000 from the offset.
+
* If the offset is from <tt>C000-FFFF</tt>, subtract <tt>8000</tt> from the offset.
 
<li>Because Game Boy is little endian, switch the first two digits with the last two.</li></ol>
 
<li>Because Game Boy is little endian, switch the first two digits with the last two.</li></ol>
  
Example: $1201FA is the offset you wish to point to.
+
Example: <tt>$1201FA</tt> is the offset you wish to point to.
<ol><li>Take the offset $1201FA</li>
+
<ol><li>Take the offset <tt>$1201FA</tt></li>
<li>Take the last four digits: $01FA</li>
+
<li>Take the last four digits: <tt>$01FA</tt></li>
<li>Since $01FA is between 0000-3FFF, you add 4000, so you get $41FA</li>
+
<li>Since <tt>$01FA</tt> is between <tt>0000-3FFF</tt>, you add <tt>4000</tt>, so you get <tt>$41FA</tt></li>
<li>Because Game Boy is little endian, you take the <span style="color:#FF0000;">41</span><span style="color:#0000FF;">FA</span>, switch the <span style="color:#FF0000;">41</span> and <span style="color:#0000FF;">FA</span> around to get <span style="color:#0000FF;">FA</span><span style="color:#FF0000;">41</span></li></ol>
+
<li>Because Game Boy is little endian, you take the <tt><span style="color:#FF0000;">41</span><span style="color:#0000FF;">FA</span></tt>, switch the <tt><span style="color:#FF0000;">41</span></tt> and <tt><span style="color:#0000FF;">FA</span></tt> around to get <tt><span style="color:#0000FF;">FA</span><span style="color:#FF0000;">41</span></tt></li></ol>
  
 
== 3 Byte Pointers ==
 
== 3 Byte Pointers ==
Line 54: Line 54:
  
 
An easy way to calculate addresses or pointer values would be to use a pointer calculator.
 
An easy way to calculate addresses or pointer values would be to use a pointer calculator.
 +
 +
= Game Boy Advance Pointers =
 +
 +
Game Boy Advance Pointers are typically four bytes long, and therefore can point to anywhere in the ROM. Compared to other systems, Game Boy Advance is less complicated when calculating pointers. To calculate a pointer from a Game Boy Advance game:
 +
 +
<ol>
 +
<li> Take the offset that you wish to point to</li>
 +
<li> Add <tt>$08000000</tt> to the offset</li>
 +
<li> For some games (such as Telefang 2), pointers are little endian, so take the four bytes and reverse them. Some other games are big endian, so you do not need to reverse the pointers. Whether a game is big endian or little endian varies from game to game.</li>
 +
</ol>
 +
Example: You want to point to offset <tt>$123456</tt>, and the game's pointers are little endian.
 +
<ol>
 +
<li> Take the offset <tt>$123456</tt></li>
 +
<li> Add <tt>$08000000</tt> to get <tt>$08123456</tt></li>
 +
<li> Since the pointers in this particular game happen to be little endian, you take <tt>$<span style="color:#FF0000;">08</span><span style="color:#008000;">12</span><span style="color:#0000FF;">34</span><span style="color:#808080;">56</span></tt> and reverse the bytes to get <tt><span style="color:#808080;">56</span><span style="color:#0000FF;">34</span><span style="color:#008000;">12</span><span style="color:#FF0000;">08</span></tt></li>
 +
</ol>
 +
  
 
[[de:Pointer]]
 
[[de:Pointer]]
  
 
[[Category:General Terms]]
 
[[Category:General Terms]]

Revision as of 02:31, 6 March 2009

A pointer is a number that refers to a specific location in a ROM or memory. They may also be referred to as addresses or offsets. The exact way pointers work vary among different systems, and, in fact, some systems have multiple pointer schemes. It has become convention, at least within the PK Hack Community to use the 0x prefix to indicate a pointer referring to the ROM file and to use the $ prefix to indicate a pointer in the format used by the machine. Both prefixes indicate the following number is in Hexadecimal. Different machines may use different byte orders, be careful.

SNES Pointers

The SNES has serveral different pointer schemes. The main two are #LoROM for smaller ROMs and #HiROM for larger ROMs, but extensions of both of those exist.

SNES pointers are little endian. Therefore, if you find your pointer comes out to $123456, then your pointer will be written to the ROM as 56 34 12 or, more likely, as 56 34 12 00.

LoROM

Some information on LoROM would be nice. No LoROM games are currently in the database. For now, the information can be found at Zophar's Domain. Perhaps the author of the SNES pointer document there should be contacted about the use of that information.

HiROM

Supports games up to 4 megabytes or 32 megabits. An extension called #ExHiROM can be used for ROMs as large as 8 megabytes or 64 megabits. One game which uses HiROM is EarthBound. For pointers to ROM data, just add 0xC00000, but note that most ROMs have a 512 byte header, so you will also have to subtract 0x200 to adjust for the header. So, if we were going to reference the 155,387th byte of the ROM, you would subtract 512 and add 0xC00000, resulting in C25CFB. Finally, a dollar sign is added to the beginning of the pointer to show that it is a SNES pointer: $C25CFB. Remember that will be written to the ROM as FB 5C C2 00, since SNES pointers are little endian.

Game Boy Pointers

2 Byte Pointers

Game Boy (and Game Boy Color) pointers are typically two bytes long. They are often contained in the same bank as the data that it is supposed to point to, and is usually directly above or below the data. To calculate a pointer from a Game Boy game:

  1. Take the offset that you wish to point to
  2. Take the last four digits of the offset, and cut off the rest
  3. The most significant bit will always be 0, and the second most significant bit will always be 1. In other words:
    • If the offset is from 0000-3FFF, add 4000 to the offset.
    • If the offset is from 4000-7FFF, do not add anything to the offset.
    • If the offset is from 8000-BFFF, subtract 4000 from the offset.
    • If the offset is from C000-FFFF, subtract 8000 from the offset.
  4. Because Game Boy is little endian, switch the first two digits with the last two.

Example: $1201FA is the offset you wish to point to.

  1. Take the offset $1201FA
  2. Take the last four digits: $01FA
  3. Since $01FA is between 0000-3FFF, you add 4000, so you get $41FA
  4. Because Game Boy is little endian, you take the 41FA, switch the 41 and FA around to get FA41

3 Byte Pointers

You'll only ever find 3 byte pointers in a GB/C game which has a MBC (Memory Bank Controller), check the ROM header and look at the Pan Docs if it's a game you're unsure about. An MBC is used for accessing more than the default 32K of ROM, by being told to select a bank which the CPU can shove into 0x4000-0x7FFF (RAM).

Sometimes the game programmer might of stored data or code in more than one ROM bank. This might be because they were running out of space in that bank (or at least thought they'd not be able to fit it all in and were utterly wrong). Maybe it's because they wanted to put similar data and/or code into logical groups e.g. putting all of the maps/levels/music from the same general area in the same bank.

Here's how to calculate ROM addresses and bank numbers (you find 2 byte pointers the usual way):

romAddress = (bankNumber * 0x4000) + (twoBytePointer - 0x4000);
bankNumber = (romAddress / 0x4000);

/* by the way, ignore any fractional part */

NOTE: When using these formulas, remember to calculate the answer by switching the 2 byte pointers to big endian first, if it hasn't been done for you, like when you view it in a hex editor.

An easy way to calculate addresses or pointer values would be to use a pointer calculator.

Game Boy Advance Pointers

Game Boy Advance Pointers are typically four bytes long, and therefore can point to anywhere in the ROM. Compared to other systems, Game Boy Advance is less complicated when calculating pointers. To calculate a pointer from a Game Boy Advance game:

  1. Take the offset that you wish to point to
  2. Add $08000000 to the offset
  3. For some games (such as Telefang 2), pointers are little endian, so take the four bytes and reverse them. Some other games are big endian, so you do not need to reverse the pointers. Whether a game is big endian or little endian varies from game to game.

Example: You want to point to offset $123456, and the game's pointers are little endian.

  1. Take the offset $123456
  2. Add $08000000 to get $08123456
  3. Since the pointers in this particular game happen to be little endian, you take $08123456 and reverse the bytes to get 56341208