Hexadecimal basics - pk-hack/CoilSnake GitHub Wiki

You're familiar with numbers that go like 0, 1, 2, 3, 4, ... 8, 9, 10, where there are ten unique digits 0 through 9 before we start double-digits. But for various computer reasons you'll occasionally be dealing with other types of numbers while hacking EB. These numbers go 0, 1, 2, 3, ... 8, 9, A, B, C, D, E, F, 10. In all, that makes sixteen unique digits before double-digits start.

This is called hexadecimal (literally six-ten) and it's something that you should try to get familiar with. Hexadecimal notation is useful because it's what the SNES hardware works with.

Underlying hexadecimal is binary, which only has two unique digits, so it goes 0, 1, 10... You probably won't be writing raw binary at all, but it can help to understand the concept. Each hexadecimal digit is made up of four binary digits, called bits, which can represent sixteen unique values.

It'll take a while to get used to using hexadecimal, so you can use a converter if it's confusing. On Windows, the calculator app has a "Programmer Mode" which lets you do this.

Some examples:

Decimal Hexadecimal Binary
1 1 1
5 5 101
10 A 1010
200 C8 11001000
255 FF 11111111

Notation

You can recognise hexadecimal being written because it will be prefixed with 0x or $, eg. 0x86 or $86. In CCScript files, only 0x can be used. In YML files, 0x can be used anywhere a decimal number can, and $ can be used anywhere a pointer is necessary. In EBMusEd, all numbers in the tracker input box are hexadecimal with no prefix. In EBME, values are decimal by default, but if you go View -> Use hexadecimal, hex values will be the method of input instead.

Bytes, words, etc

Every two digits of hexadecimal is called a byte, which is an 8-bit value. Bytes can represent 256 unique values, from 0 to 255 (or -128 to 127 if it is used to store a number that can be treated as negative). You'll frequently see leading zeroes on hexadecimal and binary values to pad them out to the "shape" of a byte. It has no effect apart from looking a bit nicer.

Two bytes together is called a word or a short, which is a 16-bit value. This can store 0-65535 (or -32768-32767). Three bytes is a 24-bit value that doesn't really have a specific name, and four bytes is a 32-bit value.

Three-byte values are special to us because they are usually representing a pointer to some location in the game's ROM. This is why you see three-byte values in text pointer fields in the YML files in projects where you haven't decompiled the script. In YML files, such pointers should always use the $ prefix.

Signedness

Briefly mentioned in the previous section is that the value range that is available in a byte changes if the byte needs to represent a negative number. This is known as signedness. The majority of values you'll be dealing with are unsigned, meaning you get the full 0-255 range, but no negatives. Occasionally, such as when setting the stat increase/decrease of an equippable item, signed values are used, which have the -128 to 127 range. There's no inherent difference, it's just up to how the game code chooses to read the value.

In the case of a signed value, 0x00, 0x01, 0x02, 0x03... etc are positive as usual. 0xFF, 0xFE, 0xFD, ... are negatives, -1, -2, and -3 respectively. In other words, you count backwards. The reason for this is that, for example, if you add 0xFF to some value that's only a byte in size, it wraps around and amounts to one less than it was to begin with.

CoilSnake does not offer a way to represent these with the standard negative sign, and it gets a little weird in places like the item config table. For example, the Diamond band specifies a defense increase for Poo of 216. This is one of the items that actually decreases his stats, so how do we recognise and convert it?

To recognise signed values when they're in decimal, check if they're 128 or higher (that's for bytes, for shorts you'll want 32768). In hexadecimal, check if they're 0x80 (0x8000 for shorts) or greater. This is the point where you'll probably want to pull out the hex calculator to convert things.