RevEng Posted August 20, 2011 Share Posted August 20, 2011 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! 8 Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted August 20, 2011 Share Posted August 20, 2011 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. Quote Link to comment Share on other sites More sharing options...
RevEng Posted August 20, 2011 Author Share Posted August 20, 2011 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) Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted August 21, 2011 Share Posted August 21, 2011 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? Quote Link to comment Share on other sites More sharing options...
RevEng Posted August 21, 2011 Author Share Posted August 21, 2011 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 Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted August 21, 2011 Share Posted August 21, 2011 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. Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted August 21, 2011 Share Posted August 21, 2011 I wasn't sure where to put a link to this thread, so I just put it here: http://www.randomterrain.com/atari-2600-memories-batari-basic-commands.html#memory If you think it should go somewhere else or in more than one place, let me know. Thanks. Quote Link to comment Share on other sites More sharing options...
RevEng Posted August 21, 2011 Author Share Posted August 21, 2011 Seems like a good spot to me. Thanks for the link! 1 Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted August 25, 2011 Share Posted August 25, 2011 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? Quote Link to comment Share on other sites More sharing options...
RevEng Posted August 25, 2011 Author Share Posted August 25, 2011 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. Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted August 25, 2011 Share Posted August 25, 2011 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. Quote Link to comment Share on other sites More sharing options...
disjaukifa Posted August 25, 2011 Share Posted August 25, 2011 (edited) 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 August 25, 2011 by disjaukifa Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted August 25, 2011 Share Posted August 25, 2011 . . . 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.randomterrain.com/atari-2600-memories-batari-basic-commands.html#dataarrays Quote Link to comment Share on other sites More sharing options...
disjaukifa Posted August 25, 2011 Share Posted August 25, 2011 . . . 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.randomterrain.com/atari-2600-memories-batari-basic-commands.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 Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted August 29, 2011 Share Posted August 29, 2011 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 )? Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted August 29, 2011 Share Posted August 29, 2011 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. Quote Link to comment Share on other sites More sharing options...
RevEng Posted August 29, 2011 Author Share Posted August 29, 2011 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 )? 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! 1 Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted August 29, 2011 Share Posted August 29, 2011 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! Thanks. Quote Link to comment Share on other sites More sharing options...
disjaukifa Posted October 5, 2011 Share Posted October 5, 2011 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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.