Honestly, my guess is that this is just a stupid, nasty glitch by someone writing one of their first games on target. Pokemon Red/Blue were the first of the series and had so many other glitches that Nintendo would normally kick out of lot-testing, that I wonder how it got through. The scroll screen shift issue is the one that gets me. Anyways, who knows what they were thinking. Perhaps this area was written to via script and therefore stored things differently. Perhaps the bit pattern 0x0101
was used to show memory was freed and that code accidentally goes bonkers in weird places. I could pour over the Z80 code and relive my own game development time on that platform, but meh. Too much work to try and decrypt what the blazes they were thinking.
It sure made a ton of money though…
Edit 1:
Ok, you bountied it. I spent a bit more time pouring over my memory and found a tidbit for you. The GBC/DMG has an opcode called DAA
. Decimal Adjust Accumulator (A). What this does is convert a value in the accumulator into BCD
format. The areas in memory you are seeing are already in BCD
format: http://en.wikipedia.org/wiki/Binary-coded_decimal
Now I can tell you, in the 4 years or so when I was hand coding Z80 assembler for games, I never once had a need for this opcode, and only seen it used once in a baseball game we made for displaying some scores. While it is a 1 cycle arithmetic instruction, I could never really find a good use for it in normal coding. Hmm. I actually still have the DMG tech docs from Nintendo. Go figure 😉 Anyways, nothing exciting there about it either except that it messes with a number of flags in funky ways.
My guess is that table is assumed to be in BCD
format. Changing it to something outside of that format causes the internal math to go extremely haywire – Carry and Zero flags set when they aren’t supposed to be. This causes overflow from one column to the next, causing very large numbers to be calculated. Without looking directly at the opcodes in question that read this area, I can’t say for certain, but my guess is there is a catch all check here that says if carry is still set upon completion of the BCD
math, set a max value instead of storing a negative or out of bounds value. That or the DAA
instruction, when receiving garbage data is returning 0x99
for it return value, though I’m less sure about that.
Hope this helps…