Jump to content

Photo

Squeezing the bBytes


18 replies to this topic

#1 RevEng OFFLINE  

RevEng

    River Patroller

  • 3,298 posts
  • bit player
  • Location:Canada

Posted Sat Aug 20, 2011 11:45 AM

There comes a time in the development of most games when the rom starts to get tight; when no additional features can be added until you figure out a way to squeeze the bytes and free up more space.

I haven't seen this information gathered in one place before, so I thought I'd kick off this thread to share some of the techniques I've used to save rom space. So with no further adieu, here they are...


  • keep same-value variable assignments on the same line when possible.

    •   rem ***** do this...
      
          timer=0:level=0:deathflag=0:soundindex=0
      
        rem ***** instead of this...
      
          timer=0
          level=0
          deathflag=0
          soundindex=0
      

      Since they're on the same line, bB knows it doesn't need to keep loading the 0 value for each assignment.

      The savings is fairly minimal (2 bytes for each variable after the first one) but this is an easy technique to use and the savings can add up quickly!

      (NOTE: the current version of bB seems to max out at 12 assignments per line. If you use more than that you may run into compile errors. :( )

  • when using bankswitching, try to reduce the number of bankswitching gosubs and gotos.


    A regular gosub takes 3 bytes. A bankswitching gosub takes 24 bytes.
    A regular goto takes 3 bytes. A bankswitching goto takes 18 bytes.

    You should avoid having small utility routines that are bankswitch-gosub'ed from many places. Either move the utility into the same bank as the calls, or change all the bankswitching gosubs to a local gosub that has a common bankswitching goto routine...

     rem ***** do this...
    
       if lives=1 then gosub utilityjump
       health=1
       gosub utilityjump
       goto mainloop
    utilityjump
       goto utility bank3
    
     rem ***** instead of this...
    
       if lives=1 then gosub utility bank3
       health=1
       gosub utility bank3
       goto mainloop
    

    If there's a bank with a lot of utility functions, you can save rom by using on...goto and a temp variable...

     rem ***** use this...
    
       if lives=3 then temp1=0:gosub enterbank2
       if enemies=0 then temp1=1:gosub enterbank2
       if gold=1 then temp1=2:gosub enterbank2
       goto mainloop
    
    enterbank2
       goto dispatcher2 bank2
    
       bank 2
    dispatcher2
       on temp1 goto routine1 routine2 routine3
    routine1
       rem do stuff
       return otherbank
    routine2
       rem do stuff
       return otherbank
    routine3
       rem do stuff
       return otherbank
    
     rem ***** instead of this...
    
       if lives=3 then temp1=0:gosub routine1 bank2
       if enemies=0 then temp1=1:gosub routine2 bank2
       if gold=1 then temp1=2:gosub routine3 bank2
       goto mainloop
    
       bank 2
    routine1
       rem do stuff
       return otherbank
    routine2
       rem do stuff
       return otherbank
    routine3
       rem do stuff
       return otherbank
    

  • In a bank-switched game, if you're sure a return is always going to be within the same bank, use "return thisbank" instead of "return". If the return will always be to another bank, use "return otherbank" instead of "return".


    In a bank-switched game...

    A "return otherbank" statement takes 3 bytes.
    A "return" statement takes 13 bytes.
    A "return thisbank" statement takes 1 byte.

    'nuff said.

  • If you have a large amount of data with values less than 16, Use nibbles and hex notation to stick the data together


    
     rem ***** use this...
       channel=songvolumechannel[i]&15
       volume=songvolumechannel[i]/16
       data songvolumechannel
       $86, $48, $84, $86
    end
    
     rem ***** instead of this...
       channel=songchannel[i]
       volume=songvolume[i]
       data songchannel
       6, 8, 4, 6
    end
       data songvolume
       8, 4, 8, 8
    end
    

  • pick variable locations consecutively so you can operate on many objects using a loop


    If you're doing a lot of the same operation to a bunch of variables, often it's better to pick the position of variables carefully and use loops...

     rem ***** use this...
       dim monster1x=g
       dim monster2x=h
       dim monster3x=i
       dim monster4x=j
       for temp1=0 to 3
       if monster1x[temp1]>25 then monster1x[temp1]=1
       if monster1x[temp1]<0 then monster1x[temp1]=24
       next
    
     rem ***** instead of this...
       if monster1x>25 then monster1x=1
       if monster1x<0 then monster1x=24
       if monster2x>25 then monster2x=1
       if monster2x<0 then monster2x=24
       if monster3x>25 then monster3x=1
       if monster3x<0 then monster3x=24
    

I've also been able to squeeze a fair bit of ROM through algorithmic improvement and judicious assembly code rewrites, but those techniques aren't really suited to a simple tips thread. I figured I'd still mention it, so you can keep them in mind.

Please post any techniques you've discovered!

#2 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • 24,819 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Sat Aug 20, 2011 5:30 PM

If you're doing a lot of the same operation to a bunch of variables, often it's better to pick the position of variables carefully and use loops...

 rem ***** use this...
   dim monster1x=g
   dim monster2x=h
   dim monster3x=i
   dim monster4x=j
   for temp1=0 to 3
   if monster1x[temp1]>25 then monster1x=1
   if monster1x[temp1]<0 then monster1x=24
   next

 rem ***** instead of this...
   if monster1x>25 then monster1x=1
   if monster1x<0 then monster1x=24
   if monster2x>25 then monster2x=1
   if monster2x<0 then monster2x=24
   if monster3x>25 then monster3x=1
   if monster3x<0 then monster3x=24

I don't understand the use of monster1x[temp1]. I thought square brackets were only used when reading data. Can you explain more about this other use of square brackets?

Thanks.

#3 RevEng OFFLINE  

RevEng

    River Patroller

  • Topic Starter
  • 3,298 posts
  • bit player
  • Location:Canada

Posted Sat Aug 20, 2011 5:46 PM

I don't understand the use of monster1x[temp1]. I thought square brackets were only used when reading data. Can you explain more about this other use of square brackets?

Thanks.

Your little gray cells just need a jump start. :)

It's how you access RAM arrays which are read-write. (scroll down to the RAM array info, near the end of that section)

#4 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • 24,819 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Sat Aug 20, 2011 6:00 PM

Your little gray cells just need a jump start. :)

It's how you access RAM arrays which are read-write. (scroll down to the RAM array info, near the end of that section)

Thanks. So to be clear and without using dim for my simple examples here, a[0] is the variable a, a[1] is the variable b, a[2] is the variable c, and so on. Is that correct?

#5 RevEng OFFLINE  

RevEng

    River Patroller

  • Topic Starter
  • 3,298 posts
  • bit player
  • Location:Canada

Posted Sat Aug 20, 2011 6:05 PM

Thanks. So to be clear and without using dim for my simple examples here, a[0] is the variable a, a[1] is the variable b, a[2] is the variable c, and so on. Is that correct?

Completely correct

#6 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • 24,819 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Sat Aug 20, 2011 6:09 PM


Thanks. So to be clear and without using dim for my simple examples here, a[0] is the variable a, a[1] is the variable b, a[2] is the variable c, and so on. Is that correct?

Completely correct

Thanks.

#7 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • 24,819 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Sun Aug 21, 2011 1:05 AM

I wasn't sure where to put a link to this thread, so I just put it here:

http://www.randomter...nds.html#memory


If you think it should go somewhere else or in more than one place, let me know.


Thanks.

#8 RevEng OFFLINE  

RevEng

    River Patroller

  • Topic Starter
  • 3,298 posts
  • bit player
  • Location:Canada

Posted Sun Aug 21, 2011 7:19 AM

Seems like a good spot to me.

Thanks for the link!

#9 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • 24,819 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Thu Aug 25, 2011 6:46 AM

  • keep same-value variable assignments on the same line when possible.

      rem ***** do this...
    
        timer=0:level=0:deathflag=0:soundindex=0
    
      rem ***** instead of this...
    
        timer=0
        level=0
        deathflag=0
        soundindex=0
    

    Since they're on the same line, bB knows it doesn't need to keep loading the 0 value for each assignment.

    The savings is fairly minimal (2 bytes for each variable after the first one) but this is an easy technique to use and the savings can add up quickly!


I was wondering . . . if you are clearing/setting up variables that aren't using the same value, is it better to have them on separate lines by themselves?

#10 RevEng OFFLINE  

RevEng

    River Patroller

  • Topic Starter
  • 3,298 posts
  • bit player
  • Location:Canada

Posted Thu Aug 25, 2011 7:08 AM

I was wondering . . . if you are clearing/setting up variables that aren't using the same value, is it better to have them on separate lines by themselves?

When they have different values, putting the assignments on the same line produces identical assembly to putting the assignments on separate lines.

If the variables are related I like to put them on the same line to make the source code easier to read.

#11 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • 24,819 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Thu Aug 25, 2011 7:28 AM


I was wondering . . . if you are clearing/setting up variables that aren't using the same value, is it better to have them on separate lines by themselves?

When they have different values, putting the assignments on the same line produces identical assembly to putting the assignments on separate lines.

If the variables are related I like to put them on the same line to make the source code easier to read.

OK, thanks.

#12 disjaukifa OFFLINE  

disjaukifa

    River Patroller

  • 2,125 posts
  • Berzerker In Training
  • Location:Research Triangle North Carolina

Posted Thu Aug 25, 2011 7:52 AM

Fantastic write up, one of the largest problems I ran into with my original game I was programming was I was constantly running out of room, and now I know why, I was doing many things incorrectly that were taking up WAY to many bytes.

Can we make this a sticky? I think this is that important. Also RevEng and Random Terrain, I didn't know we could have arrays in batari Basic! Is that a recent thing? I figure Random probably has a write up on arrays on his site, so I'll have to go check it out later today.

-Disjaukifa

Edited by disjaukifa, Thu Aug 25, 2011 7:53 AM.


#13 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • 24,819 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Thu Aug 25, 2011 7:58 AM

. . . I didn't know we could have arrays in batari Basic! Is that a recent thing? I figure Random probably has a write up on arrays on his site, so I'll have to go check it out later today.

Most of the text on the bB page was written by batari. I think this has been on the bB page for a long time:

http://www.randomter...html#dataarrays

#14 disjaukifa OFFLINE  

disjaukifa

    River Patroller

  • 2,125 posts
  • Berzerker In Training
  • Location:Research Triangle North Carolina

Posted Thu Aug 25, 2011 8:38 AM

. . . I didn't know we could have arrays in batari Basic! Is that a recent thing? I figure Random probably has a write up on arrays on his site, so I'll have to go check it out later today.

Most of the text on the bB page was written by batari. I think this has been on the bB page for a long time:

http://www.randomter...html#dataarrays


Ok I remember reading about that now, I didn't use them because I couldn't modify the content in the arrays easily. I know you can with the code from SeaGruff found here: Read/Write Arrays

-Disjaukifa

#15 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • 24,819 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Mon Aug 29, 2011 3:35 AM

keep same-value variable assignments on the same line when possible.

While experimenting, have you noticed how many variables can be on a single line before bB chokes on it (with and without bankswitching)? If you have found a general limit, have you also noticed if the length of variable aliases changes things (does size matter :D )?

#16 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • 24,819 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Mon Aug 29, 2011 8:27 AM

So to be clear and without using dim for my simple examples here, a[0] is the variable a, a[1] is the variable b, a[2] is the variable c, and so on. Is that correct?

Here's what I'm using in Seaweed Assault at the beginning of the program:


   rem  ****************************************************************
   rem  *
   rem  *  Clears all normal variables and old playfield variables.
   rem  *
   rem  '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
   rem  '
   for temp5 = 0 to 25 : a[temp5] = 0 : next

   for temp5 = 0 to 47 : var0[temp5] = 0 : next

I'm using a modified version inside of the game that avoids clearing out variables that need to keep their values.


Thanks again for the idea.

#17 RevEng OFFLINE  

RevEng

    River Patroller

  • Topic Starter
  • 3,298 posts
  • bit player
  • Location:Canada

Posted Mon Aug 29, 2011 8:52 AM

While experimenting, have you noticed how many variables can be on a single line before bB chokes on it (with and without bankswitching)? If you have found a general limit, have you also noticed if the length of variable aliases changes things (does size matter :D )?


It appears that you can only have 12 assignments on one line. Any more and there's a segfault error.

I think it's due to some of the hardcoded memory limits in the 2600basic binary. (from statements.c)

I'll add that as a note in my first post.

And your looping workaround is a good one! :thumbsup:

#18 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • 24,819 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Mon Aug 29, 2011 8:58 AM

It appears that you can only have 12 assignments on one line. Any more and there's a segfault error.

I think it's due to some of the hardcoded memory limits in the 2600basic binary. (from statements.c)

I'll add that as a note in my first post.

And your looping workaround is a good one! :thumbsup:

Thanks. :thumbsup:

#19 disjaukifa OFFLINE  

disjaukifa

    River Patroller

  • 2,125 posts
  • Berzerker In Training
  • Location:Research Triangle North Carolina

Posted Wed Oct 5, 2011 12:47 PM

I wanted to add onto this a little bit. I just went through a game I'm working on, and was able to save about 60 bytes so far where I was calling rand or setting up values that I would then do again later in the main loop before that sprite was ever used. I have a feeling many of use could save space as well by going through and removing needless code.

You also need to find a balance between using goto statements and if statements. Depending on what you are evaluating one can save you more space than the other. Mostly you want to stick to if statements from my observation except when you get into a serious of very long if statements that has multiple && checks in them.




0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users