Jump to content
  • entries
    17
  • comments
    28
  • views
    32,103

Faster Initialization


Omegamatrix

1,629 views

Most (not all) Atari 2600 games use an initialization routine that clears the RIOT ram and sets the TIA registers to a known state. The most optimal code to do this is:

    cld
    ldx    #0
    txa
.loopClear:
    dex
    txs
    pha
    bne    .loopClear
 

Andrew Davie wrote that, I think. Brilliant piece of code really. :) Clears everything and leaves A=0, X=0, and Stack Pointer = $FF. Takes only nine bytes too!

 

 

Sometimes when you are writing a game you switch banks to an entirely new kernel (say from a title screen to the game screen), and you need to run a clear routine once again. You can run into a bit of wall because the code takes 36 scanlines and 22 cycles to execute. You most likely will spend too much time clearing and have a frame that bounces on your TV because it took too many scanlines.

 

 

To claw some cycles back I wrote this routine. It is an attempt to balance the cost of extra bytes vs how much time can be gained.

    cld
    lda    #0
    ldx    #CXCLR
    txs
    ldx    #28
.loopClearFaster:
    pha
    pha
    pha
    pha
    pha
    pha
    dex
    bpl    .loopClearFaster
    txs
 

This only takes 10 scanlines and 48 cycles. That's pretty good performance for just another nine bytes. You can tweak it more by adding a PHA or taking one away. The six PHA's seemed the most balanced routine for cost vs performance to me. What I also really love about this routine is that it ends with A=0, X=$FF, and SP = $FF. Having X=$FF after the routine is useful most of the time. :) There always seems to be a lot of ram locations that need to get populated with $FF such as high pointers to the $FF page.

 

 

If you are using the nine byte routine then another trick to set a few registers to $FF is to simply DEC them since you know they are already set to zero. When doing a lot of storing you might be better off with a loop, or a loop with a look up table. If it is just a few then try DEC as it saves a byte over using TSX (SP=$FF at this time) and STX.

    cld
    ldx    #0
    txa
.loopClear:
    dex
    txs
    pha
    bne    .loopClear

    dec    playerGfxPtrHi   ; 0 ---> $FF
    dec    enemyGfxPtrHi    ; 0 ---> $FF
 

Most people will have noticed I didn't use a SEI. That is optional for the 2600 as there is not interrupt line. However, I'm not sure about all the clone systems that were made. Some might have real 6502's in there. At one byte it doesn't really kill a person to include it. If you don't care, then one can also make use of the interupt flag as a 1 bit storage container. I did so in routine for a Sega Genesis Controller conversion of Starmaster.

 

 

  • Like 1

2 Comments


Recommended Comments

The second line of these clears should be "ldx #0" :)

Otherwise you're initialising everything with unknown!!

Quite right, and fixed!! :)

Link to comment
Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...