PuzZLeR Posted February 13, 2021 Share Posted February 13, 2021 As the title says. I am looking for any tips on writing code that keeps the ROM size as small as possible. Are there good and bad ways to write certain IntyBASIC code, that generates the same result, but adds less size? For example, would better use of constants, functions or procedures, help? What about better placement of if, or nested if, statements? Better use of variables? I can go on, but I know you guys get it. Sure you can play with the ORG statement, but more efficient code will help too. I have another adjacent thread where I now have a ROM that is (in Windows NTSF) over 50kb. I have no music, sound effects, graphics screens yet, and this is concerning as I believe the max size would be about 84kb. Any tips? Thanks! Quote Link to comment Share on other sites More sharing options...
+nanochess Posted February 14, 2021 Share Posted February 14, 2021 There are a few principles to optimize IntyBASIC programs: * If a routine is repeated several times in your program, it qualifies to become a subroutine, just check for the common parameter. * If a semi-long expression is repeated several times in your program, consider replacing it with a subroutine or a DEF FN. * If you have several IF doing comparison with constants, replace with ON GOTO or ON GOSUB * if you have tons of PRINT with strings (for example a text adventure), start considering using DATA PACKED and a printing subroutine. 1 Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 14, 2021 Share Posted February 14, 2021 The IntyBASIC compiler output interlists your original code with the assembly code it generated. It can be rather instructive to write code, compile it, and see what IntyBASIC produces. IntyBASIC doesn't have a general register allocator, but it does try to reuse values it's already loaded in registers within an expression. So, swapping the order of operands in an addition, or placing parentheses creatively can make a difference. 2 Quote Link to comment Share on other sites More sharing options...
PuzZLeR Posted February 15, 2021 Author Share Posted February 15, 2021 Hey guys, thanks. The reason my code is so extensive is also that I may be a bit ambitious. I'm using options to choose a player of different abilities, different code for multiplayer also, animations going E/W and N/S and not moving, different game speeds, different enemy A/Is, etc. You can see how this branches out into many permutations and combinations. It's like a tree. Also, it being a maze game adds some complicated collision detection. At any rate, here's some sample code, which is quite frequent all over my program. It's simplistic and hypothetical. Not asking for any "perfect" answer, but, if there are ideas on how to save space on the following it would be nice. if expr0 then if expr1 then if expr5 then statement01:statement02 else statement03 if expr0 then if expr2 then if expr6 then statement04:statement05 else statement06 if expr0 then if expr3 then if expr7 then statement07:statement08 else statement09 if expr0 then if expr4 then if expr8 then statement10:statement11 else statement12 I recently added some similar code to make one enemy's A/I a bit more sophisticated. It added over 5kb in ROM size - geez, it was only like 4 lines! ? Thanks. Quote Link to comment Share on other sites More sharing options...
+nanochess Posted February 16, 2021 Share Posted February 16, 2021 I see. You can optimize your code this way (notice the nesting): IF EXPR0 THEN if expr1 then if expr5 then statement01:statement02 else statement03 if expr2 then if expr6 then statement04:statement05 else statement06 if expr3 then if expr7 then statement07:statement08 else statement09 if expr4 then if expr8 then statement10:statement11 else statement12 END IF I understand when you say more variations, it means you add a different speed like this (and replicate code): IF speed = 0 THEN enemy_x = enemy_x + 1 enemy_y = enemy_y + 1 ELSEIF speed = 1 THEN enemy_x = enemy_x + 2 enemy_y = enemy_y + 2 END IF This can be optimized this way: enemy_x = enemy_x + speed_table(speed) enemy_y = enemy_y + speed_table(speed) ' In another part for data speed_table: DATA 1,2 5 Quote Link to comment Share on other sites More sharing options...
skywaffle Posted February 17, 2021 Share Posted February 17, 2021 I've had many issues in the past with having bulky code and needing to shrink the footprint some. consider replacing routines like: counter = counter + 1: if counter > 1 then counter = 0 with counter = 1 - counter or counter = counter + 1: if counter > 7 then counter = 0 with counter = (counter + 1) % 8 Those can free a small amount. Everything adds up if you have many routines like that though. Nanochess' example on using DATA routines for tables is incredibly useful. I use tables for just about everything, including movement patterns for enemies, jumping animation, enemy attributes, as well as stage configuration. If you using PRINT commands to place a few GRAMs or characters on screen, it can be leaner to use #BACKTAB instead. DO/LOOP tends to be more wasteful than having a label and a IF THEN GOTO statement. Having subroutines that check enemy backtab collision, updating enemy X or Y position, or changing enemy direction can be useful if you have many different enemy types. Each enemy can call on the same subroutines rather than duplicating the same type of code for each enemy type. I tend to use subroutines for lots of little things as well, like clearing sprites on screen, resetting enemy variables, or time delays (FOR I = 0 to DELAY_TIME: WAIT: NEXT). 3 Quote Link to comment Share on other sites More sharing options...
PuzZLeR Posted February 19, 2021 Author Share Posted February 19, 2021 Hey thanks! I am working on said suggestions right now. I will report back with questions and results. My last contest entry, "Deadly Balls", although only one level was still less than 40kb, and it had sound effects, music, and full game play. I've worked on it since then, added two levels, some different enemies, some extra music, some background, and it's still only around 40kb. My current attempting entry has no music, no sound effects, one level, and game play is still not complete and it's already well over 50kb. It astounds me what's going on this time around. Just thought I'd share that. Anyway, maybe if and when I post source someone can help if needed on that. Thanks for now. ? Quote Link to comment Share on other sites More sharing options...
skywaffle Posted February 19, 2021 Share Posted February 19, 2021 One thing that helped me immensely was developing ways to compress levels down. For Super Mario Bros, fitting 32 stages and all the various secret areas was not going to happen without some kind of compression. The repeating backgrounds are drawn in 1x12 strips that are pulled from a table, and the level objects are drawn over the background as needed, but done with DATA PACKED tables that contain the following: Object type (single backtab tile, tile strip, enemy, warp, etc) Object attribute (tile strip size, warp reference point, etc) Screen X position Screen Y position Two 8 bit values in DATA PACKED are combined into a single 16 bit value. These are decoded back to two separate values by Value / 256 and Value % 256 respectively. I also pack all in game text the same way and try to avoid using PRINT statements all together using a subroutine like this: DISPLAY_TEXT: PROCEDURE FOR I = 0 TO TEXT_LENGTH #BACKTAB(TEXT_POSITION + I * 2) = (GAME_TEXT(I + #TEXT_OFFSET) / 256) * 8 + 7 + #LEVEL_BGCOLOR #BACKTAB(TEXT_POSITION + I * 2 + 1) = (GAME_TEXT(I + #TEXT_OFFSET) % 256) * 8 + 7 + #LEVEL_BGCOLOR NEXT END GAME_TEXT: DATA PACKED "GAME TEXT GOES HERE!" It's certainly not as convenient as using PRINT since you need to keep track of the offset of where to begin reading the text, but it has helped me reduce the footprint of all my game projects. Having a function at the beginning of the program as shown below also helps with more easily using the subroutine: DEF FN DISP_TEXT (A, B, C) = TEXT_POSITION = A: TEXT_LENGTH = B/2: #TEXT_OFFSET = C/2: GOSUB DISPLAY_TEXT 1 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.