Optimisation - Falmouth-Games-Academy/comp310-wiki GitHub Wiki

Optimization

Types of optimization [1]

  • Speed optimization(code executes in fewer cycles)
  • Size optimization(code takes up fewer bytes)
  • Constant-executing-time optimization (code executes in a constant number of cycles no matter what it has to do)
  • RAM usage optimization (See Fixed Bit Length Encoding)

Zero Page[2]

Every memory address from 0000 to 00FF is called the Zero-page and Is where all of your variables are placed. The 6502 has a special addressing mode for this memory area.

Example code

6 bytes, 8 clock cycles:

300:AD 80 03    LDA $380 ;get value  
303:8D 81 03    STA $381 ;store it elsewhere

4 bytes, 6 clock cycles:

300:A5 80       LDA $80 ;get Zero-page value  
302:85 81       STA $81 ;store it elsewhere

The Stack[2]

Memory addresses 0100 to 01FF are the location of 6502 stack. The entire stack can be addressed in 9 bits, the stack pointer is 8 bits, you can only set this 8-bit stack pointer using the X register and transfer it using TXS opcode. However, the stack pointer does automatically move items are pushed or popped from the stack. The stack grows downward so it is a good practice to initialize the stack pointer to the top of the stack during reset time. You can do this with this code:

300:A2 FF     LDX #$FF ;set pointer to very top of stack
302:9A        TXS

code from 4(https://wiki.nesdev.com/w/index.php/Stack)

And to read the stack pointer you also use the X register with the TSX opcode. The stack never grows so low that it goes into the Zero page, instead, the stack pointer wraps from 0100 back up to 01FF

Creating a game in 40KB [5]

This is a great video showing you how a two-person team from Berlin, optimized a game they made to fit into a 40Kb NES cartridge, which was the limitations that Super Mario Bros had when it was first released.

Techniques Used [5]

Sprite Optimisation

The player character was made up of just one individual sprite, this allowed for a greater range of movement animations. The boss character consisted of 16 sprites, so it wasn't possible to save every frame of the animation. Because of this, each frame of the animation was split into individual tiles and any tiles that remained unchanged from one frame to the next could be reused and only appear once in the spritesheet.

Map Optimisation

  • Grouping together tiles into meta tiles and meta-meta tiles: Instead of making levels out of 8 by 8 pixel tiles (960 bytes per screen), small level tiles were grouped together into 16 by 16 pixel tiles (240 bytes per screen) and then once more into 32 by 32 pixel tiles, which used only 60 bytes for a screen of tiles.
  • Level symmetry: Further optimisation was attempted by making the levels symmetrical, requiring only 30 bytes per screen, however, this was found to make the game less interesting to play.
  • Unused bit and tile mirroring: Because there were a limited number of meta-meta tiles (32 by 32-pixel tile groupings) in the tile-set, a spare bit was left on the tile. This unused bit was used to shift the axis of where each individual row was mirrored, essentially allowing the row to be shifted along like a conveyor belt to any position.
  • Hard mode levels: Changing the palette allowed the player to distinguish the harder levels with little extra data. The majority of the level was kept the same, but several key tile locations were updated in order to create a harder level. Overall around 200 extra bytes were used to create these extra hard mode levels.

Game features [3]

  • Up to 4 simultaneous players
  • 8 worlds spanning a total of 26 levels (normal + hard mode)
  • Dangerous traps, monsters and bosses
  • Secrets!
  • Password function
  • 40 Kilobytes, fully optimized
  • and more...

References