Monday, February 6, 2012

Gradius 3's hi-oam management

From using a debugger on Gradius 3, the oam buffer is stored at $7e3c00 (or was it $7f3c00? Got to double check), and it manages the top 32 bytes of the oam like this:

First it sets the first word of the hi-oam 32 bytes to #$0001. Then, for every sprite it shifts the x and size bits into the word. When it shifts the "1" from the #$0001 into the carry bit, it knows it's time to set up the next word in the hi-oam.

This method is really inefficient. A much swifter way to do this is to temporarily store the x and size bits separate from the oam, and do all the hi-oam processing at the end of the main loop. It is a lot easier for the 65816 to do one job individually at a time, instead of going back and forth between many different jobs.

Sunday, February 5, 2012

32-bit instructions are for losers.

Guess what, your college professors lied to you. 32-bit instructions are completely worthless. They are purely a marketing gimmick. I understand that programmers use 32-bit instructions all the time, my point is that programmers don't need to.

Think about this:

8-bit gives you numbers 0-255
16-bit gives you numbers 0-65535
32-bit gives you numbers 0-4294967295

8-bit is plenty enough for simple game logic, such as decrementing lives and going into game over mode when the number of lives is zero, or counting how many coins Mario has, since Mario never has more than 256 lives or 256 coins at once. Now calculating Marios actual gameplay physics requires numbers larger than 256.

16-bit is enough for level coordinates because one screen is 256 pixels long, and most games have levels that take up 16-32 screen legnths. 65536 is more than enough.

NES programmers were smart. Instead calculating game physics entirely using 16-bit values, they calculated the x and y velocity in 8-bit, and added the 8-bit velocity to 16-bit world coordinates. Like this:

lda y_velocity
clc
adc gravity
sta y_velocity
bpl negative_velocity
dec y_coordinate_hi
negative_velocity:
clc
adc y_coordinate_lo
sta y_coordinate_lo
bcc carry_bit
inc y_coordinate_hi
carry_bit:

SNES with it's 16-bit instruction set, doesn't have to do all this crap.

lda y_velocity
clc
adc gravity
sta y_velocity
clc
adc y_coordinate
sta y_coordinate

But here is the issue. The people who programmed SNES, unlike the NES, were stupid. They did EVERY LITTLE THING WITH 32-bit values. So instead of the example above, SNES programmers did this:

lda y_velocity_lo
clc
adc gravity_lo
sta y_velocity_lo
lda y_velocity_hi
adc gravity_hi
sta y_velocity_hi
lda y_velcoity_lo
clc
adc y_coordinate_lo
sta y_coordinate_lo
lda y_velocity_hi
adc y_coordinate_hi
sta y_coordinate_hi

Then there were programmers who were even stupider, who not only use 32-bit math, but left the 65816 in 8-bit mode!!!