Suppose you have 4 variables:
a = 1
b = 335
c = -16
d = 2004
You could just write all those values as int32s, but you wouldn't be much better off than just using variables as normal. Instead, you could write (a) as a bool, (b) as unsigned 32bit, (c) as a signed 8bit, and d as whatever (without context, an unsigned 16bit would suffice). Now, I think a bool is automatically 8bit in a buffer, but not entirely sure.
Anyway, remember my example about 16 bit consoles like the SNES. The system could write numbers as either 8bit values or 16bit values depending on what the programmer wanted. So the memory could look like:
10 f0 24 28 64 a2 8b 40 24 08 0c
For now, let's just think of that as a buffer. If you wanted to read the 10th byte and just the 10th byte, you'd peek position 9, set the type to either buffer_u8 or buffer_s8, and read the byte there. So far, simple enough. Now let's say instead you want to read the 7th byte. You'd peek position 6, but the buffer type you use depends on what kind of data you want out of it. If you set the buffer type to buffer_u8, then the value you'd peek is 139; however, if you set the type to buffer_s8, the value you'd peek would be -117 because any byte with the highest bit set ($80 or larger) is negative when treated as signed.
Now let's ramp things up a bit. The SNES didn't read 1 byte at a time like the NES did, it read 2 at a time (hence it was a 16bit system). So in buffer terms, the buffer type for peeks was always buffer_u16. So if you wanted to read the 10th byte, the value peeked would be $080C (the system got around this by using 8bit registers, so it would read $080C but the programmer could still work with $08 and $0C separately if needed). When the programmer was ready to write a value back to the "buffer", he could write a single register as u8 or write the whole value as u16.
Now the important stuff. Let's go back to the first set of variables earlier in this post. Suppose you wrote them all as buffer_s16. Then the buffer would look like
01 00 4F 01 F0 FF D4 07
Suppose you wanted to get the value of (c) from the buffer. You remember that you used buffer_s16 as the type, but what position is (c)? It was your 3rd variable, but if you try to peek position 2 in the buffer, you'll get $014F. The position of (c) in the buffer is actually 4.
Now let's say you instead wrote to the buffer where (a) was bool, (b) was u16, (c) was s8, and (d) was we'll say u32. Now the buffer would look like
01 4F 01 F0 D4 07 00 00
Again, if you want to read (c) from the buffer, its position in the buffer this time around would be 3.
What happens if you use the wrong types, though? Suppose you used buffer_u8 for everything.
01 4F F0 D4
As you can see, the values stored in the buffer are quite different than what they should be.
The buffer types (fixed, grow, wrap) should be pretty straightforward, but I'll cover them real quick anyway. To help illustrate them, I'll refer to an emulator like FCEUX.
A fixed buffer is like the RAM - a limited amount is allocated to write values to. Once you filled up that memory, you have to decide when and where to overwrite anything.
A grow buffer is kind of like the game cartridge itself. The original NES games were like fixed buffers, but then companies started adding memory expansion chips to the cartridges to give them more memory to work with. This is kind of like what a grow buffer type is.
A wrap buffer is most easily comparable to a stack - a block of memory allocated for writing data sequentially, but once you reach the limit of the buffer, it resets the position back to 0 and any additional writes will overwrite the oldest entries. This is what happens when a "stack overflow" occurs and games crash.