Synthpopalooza Posted July 29, 2011 Share Posted July 29, 2011 (edited) I have a problem: I have been working on my CIN font editor, and I have found that I am hitting an error-2 before the program can even finish initializing. I am including the basic program on this post and the source code. I am looking for any suggestions as to how I can trim my code, optimise it, and save on RAM. For one thing, I have had to reserve memory for the equivalent of 4 character sets, which is no doubt eating up alot of my ram. I've used alot of variables too, maybe I can eliminate some? I have also tried LIST, NEW, and ENTER to clear up any unused variables, too. One possible savings is in the block font used to display the character grid, I am only really using the first 64 characters of that character set to display the character grid, so I don't need screen codes >65 ... how could I redo this so that I use less memory? the procedure is in CHARINIT where I set up memory for the character sets, icecin2.zip Edited July 29, 2011 by Synthpopalooza Quote Link to comment Share on other sites More sharing options...
snicklin Posted July 31, 2011 Share Posted July 31, 2011 I have a problem: I have been working on my CIN font editor, and I have found that I am hitting an error-2 before the program can even finish initializing. I am including the basic program on this post and the source code. I am looking for any suggestions as to how I can trim my code, optimise it, and save on RAM. For one thing, I have had to reserve memory for the equivalent of 4 character sets, which is no doubt eating up alot of my ram. I've used alot of variables too, maybe I can eliminate some? I have also tried LIST, NEW, and ENTER to clear up any unused variables, too. One possible savings is in the block font used to display the character grid, I am only really using the first 64 characters of that character set to display the character grid, so I don't need screen codes >65 ... how could I redo this so that I use less memory? the procedure is in CHARINIT where I set up memory for the character sets, I'm having some problems viewing the code (due to some end of line characters) so I will just give some advice from memory rather than what I see. Please note that I haven't programmed in Turbo Basic for 15 years now, so I might get the odd thing wrong. 1) Keep variable names short, each extra character is a wasted byte. 2) Keep procedure names short, same reason as above. 3) When using constants, i.e. the number '6', have a variable called 'v6' (set to '6') and reference this instead, I think it uses around 4(?) bytes less. I'm not sure how many variables your program may have. 4) Evaluate every bit of functionality over and over (do I need this?) If I think of anything more, I'll let you know.... Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted July 31, 2011 Share Posted July 31, 2011 (edited) Just fired up The Last Word and had a look at your code: one thing which I'd do straight away is replace all occurences of constants 0, 1, 2 and 3 with %0, %1, %2, and %3 respectively. These built-in integer constants take up less space than a floating point value, and have the advantage of not consuming any more entries in the variable name table. It's a shame that TB doesn't support an actual integer variable type, but all you get are these four hard-coded integer constants. You might find that this alone saves quite a lot of space and solves the problem (snicklin's idea would have done the same, with the overhead of the extra variable definitions). If the constant "0" appears, say, 200 times in the program, replacing each "0" with "%0" will save several hundred bytes. Edited July 31, 2011 by flashjazzcat Quote Link to comment Share on other sites More sharing options...
+therealbountybob Posted July 31, 2011 Share Posted July 31, 2011 Just fired up The Last Word and had a look at your code: one thing which I'd do straight away is replace all occurences of constants 0, 1, 2 and 3 with %0, %1, %2, and %3 respectively. These built-in integer constants take up less space than a floating point value, and have the advantage of not consuming any more entries in the variable name table. It's a shame that TB doesn't support an actual integer variable type, but all you get are these four hard-coded integer constants. You might find that this alone saves quite a lot of space and solves the problem (snicklin's idea would have done the same, with the overhead of the extra variable definitions). If the constant "0" appears, say, 200 times in the program, replacing each "0" with "%0" will save several hundred bytes. Yes I did this on Gwobby Strikes Back and used ? #N6 instead of ? #6 to gain loads of bytes... not that you'll learn much from my code but you could scan over GSB - there is another thread here that I started a while ago on the same subject worth a gander too Quote Link to comment Share on other sites More sharing options...
Synthpopalooza Posted August 1, 2011 Author Share Posted August 1, 2011 (edited) Thanks for that. Also: I am thinking about shortening my variable names (e.g. RV$ instead of REGVAL$) and replacing my EXEC's with GOSUBs. Using an EXEC takes up space in the variable name table, especially more so as the procedure names tend to be longer than most variables. Do you think this will also save memory? I've discovered that shortening the character set really isn't an option. Even though I am only using the first 64 entries in the set, the nature of the character-flip modes I am using requires the whole 2048 bytes for the character set be reserved. I'll go through and redo all the constants and see if there are any other constants I can use. One thing: I hardly ever use ? #6 anymore. I've learned to get by in many cases with POKEs to the screen when it comes to single characters, and just altering the display list from Graphics 0 rather than doing a graphics call. More questions: Instead of using STICK(0) and STRIG(0), would reading the memory locations themselves save any memory in my program? Also, using hex numbers ($00 - $FF and $0000 = $FFFF) for one and two byte values? And how many times does a constant need to be used in a program before it becomes more efficient to replace it with a variable? Edited August 1, 2011 by Synthpopalooza Quote Link to comment Share on other sites More sharing options...
Rybags Posted August 1, 2011 Share Posted August 1, 2011 (edited) Stick/strig use the same memory amount as Peek. RND has a dummy argument, so any variable name will do. Putting more statements per line is another way to save RAM. Each new line is something like 3 extra bytes. Character sets are 1024 bytes not 2048. Gr. 1 and 2 chsets are only 512 bytes. In my experience, biggest memory saver in general is long lines and using constants instead of numerics. Another huge saver is eliminating duplicate data. Assembler routines are a big culprit there. e.g. rather than having DATA lines where essentially 4-5 bytes are consumed per byte of code, have routines in strings. Downside is they have to be relocatable. Advantage is there's no memory waste other than the 7 bytes or so overhead that a string must have. Where Asm stuff has to be location-specific, load it from file rather than embedding in the program. Initialising variables can be done more efficiently in a big block by reading from DATA. e.g. with your constants: 10000 RESTORE 10000:READ V1,V2,V3,V4,V5,V6,V10 100010 DATA 1,2,3,4,5,6,10 Edited August 1, 2011 by Rybags Quote Link to comment Share on other sites More sharing options...
Synthpopalooza Posted August 1, 2011 Author Share Posted August 1, 2011 (edited) Character sets are 1024 bytes not 2048. Gr. 1 and 2 chsets are only 512 bytes. Actually, the block character set I am using is 2048 bytes, as it is a flicker-mode (Super IRG style) double font. I'm actually using 2, one for the block character set, and one for the double-font which is actually being redesigned. 4K required, in total. Another idea: What about using NOT X instead of X=0, or IF X instead if IF X<>0 ... would that also save space? Especially for STRIG(0) which only returns 0 or 1 Edited August 1, 2011 by Synthpopalooza Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted August 1, 2011 Share Posted August 1, 2011 Thanks for that. Also: I am thinking about shortening my variable names (e.g. RV$ instead of REGVAL$) and replacing my EXEC's with GOSUBs. Using an EXEC takes up space in the variable name table, especially more so as the procedure names tend to be longer than most variables. Do you think this will also save memory? Replacing EXECs with GOSUBs will save space in the variable name table (I think I had to resort to this some years back on one project), but naturally it makes the code less readable. In my case, it wasn't so much lack of memory as lack of variable names (since there's a maximum of 256 in TB). I'll echo the point about putting machine code routines in strings. MUCH more space-efficient than using DATA statements. In addition, if the machine code routine is relocatable and is less than about 120 bytes, you can save space by saying: ML_ROUTINE=ADR("<machine code string>") rather than: ML_ROUTINE$="<machine code string>" Using the first method, you're referencing the bytes in the program code directly. If you use the second method (assigning the value to the string), you need a string variable, and twice the storage space. If you embed the code in this way, it's about as compact as loading it from disk (since you need to assign storage for code loaded externally). Quote Link to comment Share on other sites More sharing options...
+JAC! Posted August 1, 2011 Share Posted August 1, 2011 (edited) My Contribution: Remove all "TEST REM" statements like REM DPOKE 1034,560:DPOKE 1036,65535:DPOKE 1038,65535:REM DUMMY VALUES The REM statement will take even more space than the code, because its text, not tokens Replace READ/DATA but BPUT/BGETPut one time initialization like PROC VBISETUP into a separate file which create binary files using "BPUT".In the main program use "BGET" instead or READ. If possible, use fixed memory locations to prevent string creation.This will save of factor 3-5 per number. For lines 9100ff even more. Edited August 1, 2011 by JAC! Quote Link to comment Share on other sites More sharing options...
Rybags Posted August 1, 2011 Share Posted August 1, 2011 (edited) To save even more RAM: Get the user to input the variable values: 10000 INPUT V1,V2,V3,V4,V10 Then have a printed sheet with the values the person has to type in for the program to work properly. Edited August 1, 2011 by Rybags Quote Link to comment Share on other sites More sharing options...
Synthpopalooza Posted August 1, 2011 Author Share Posted August 1, 2011 To save even more RAM: Get the user to input the variable values: 10000 INPUT V1,V2,V3,V4,V10 Then have a printed sheet with the values the person has to type in for the program to work properly. What about inputting the values from disk, instead of from the user? Quote Link to comment Share on other sites More sharing options...
Rybags Posted August 1, 2011 Share Posted August 1, 2011 That "user input" one was a joke. But yes, doing such input from disk would be a memory saver. Another one if the RAM isn't being used could be to have a RAMDisk handler that uses RAM under the OS. Give it NOTE/POINT ability and you can do nice random access. Quote Link to comment Share on other sites More sharing options...
snicklin Posted August 1, 2011 Share Posted August 1, 2011 To save even more RAM: Get the user to input the variable values: 10000 INPUT V1,V2,V3,V4,V10 Then have a printed sheet with the values the person has to type in for the program to work properly. Class! Quote Link to comment Share on other sites More sharing options...
+therealbountybob Posted August 2, 2011 Share Posted August 2, 2011 For GSB I used a loader program (autorun.tbs) which made use of Page 6 and CASBUF. Reading my assembler books (yes I'm still reading and not coding!) they mentioned using bytes towards the end of the stack's page - risky but they might not all get overwritten by a program :!: Check these threads out too: http://www.atariage.com/forums/topic/155003-memory-use-re-turbo-basic-program/ http://www.atariage.com/forums/topic/165281-basic-optimisation/ Quote Link to comment Share on other sites More sharing options...
pseudografx Posted August 2, 2011 Share Posted August 2, 2011 (edited) Another idea: What about using NOT X instead of X=0, or IF X instead if IF X<>0 ... would that also save space? Especially for STRIG(0) which only returns 0 or 1 This one will definitely save some space, exactly 7-8 bytes per every occurence. You can also save 2 bytes when using ON X GOTO Y instead of IF X THEN GOTO Y. Edited August 2, 2011 by pseudografx Quote Link to comment Share on other sites More sharing options...
Synthpopalooza Posted August 5, 2011 Author Share Posted August 5, 2011 (edited) ok, I had an idea: It as suggested that instead of using a string, I use free RAM ... I have an undo buffer of 16 bytes which I had been using as UNDO1$( and UNDO2$(. What I want to do is instead use memory locations 713-728 as this buffer. Mapping the Atari says these are free to use, would this be ok? Are there any other unused locations in memory I can make use of? The cassette buffer is out, because I am already using it for the VBI routine, and page 6 is being used for a DLI routine. A quick look through Mapping the Atari has brought back these possibilities: 906-999: Printer buffer. Since I am not using a printer, maybe I can use this? 1000-1020: Spare buffer area unused by the OS? 1152-1279: 128 spare bytes Edited August 5, 2011 by Synthpopalooza Quote Link to comment Share on other sites More sharing options...
+Stephen Posted August 5, 2011 Share Posted August 5, 2011 ok, I had an idea: It as suggested that instead of using a string, I use free RAM ... I have an undo buffer of 16 bytes which I had been using as UNDO1$( and UNDO2$(. What I want to do is instead use memory locations 713-728 as this buffer. Mapping the Atari says these are free to use, would this be ok? Are there any other unused locations in memory I can make use of? The cassette buffer is out, because I am already using it for the VBI routine, and page 6 is being used for a DLI routine. Are you using PM Graphics? There's always unused space there (384 or 768 bytes depending on single or double line mode - always at the start of PMBASE). Quote Link to comment Share on other sites More sharing options...
Synthpopalooza Posted August 5, 2011 Author Share Posted August 5, 2011 ok, I had an idea: It as suggested that instead of using a string, I use free RAM ... I have an undo buffer of 16 bytes which I had been using as UNDO1$( and UNDO2$(. What I want to do is instead use memory locations 713-728 as this buffer. Mapping the Atari says these are free to use, would this be ok? Are there any other unused locations in memory I can make use of? The cassette buffer is out, because I am already using it for the VBI routine, and page 6 is being used for a DLI routine. Are you using PM Graphics? There's always unused space there (384 or 768 bytes depending on single or double line mode - always at the start of PMBASE). Not using PM graphics at all ... everything in this editor is character mode-driven. Quote Link to comment Share on other sites More sharing options...
Synthpopalooza Posted August 7, 2011 Author Share Posted August 7, 2011 (edited) I seen to have run into a new problem: I am trying to get my font editor to load a special font format I call .ICE, which is made up of the following: Byte #1: Graphics mode (0-19) then a number of bytes which correspond to color registers, the number varies depending on which graphics mode is used (e.g. Super IRG uses only 5 registers, 708-712, while Super IRG 2 will use 9 different color registers). then two font files, each one 1024 bytes. The problem is, when I go to use a get #1,a in my program, I immediately get an error-136. BGET seems to work fine when reading from this file, but get seems to be no good. I am attaching an ATR containing ICE GTIA, plus the font file TEST.ICE which I am trying to get this program to load. It should (if it were working correctly) automatically load the font, then switch the graphics mode to Super 9 and set two color registers. Here is the code I used for creating and saving the font data: 21000 PROC FONTLOAD 21010 EXEC CLEARMENU 21020 POSITION 0,13 21080 EXEC CLEARMENU 21081 POSITION 0,13:? "Load Mask ±, Mask ², ÆN2 or ÉCE file:"; 21082 GET KK 21083 IF KK<>ASC("F") AND KK<>ASC("I") AND KK<>ASC("1") AND KK<>ASC("2") AND KK<>27 THEN 21082 21090 POSITION 0,13:? "œInput filespec:";:INPUT #16,FN$ 21100 REM TRAP 21140 21110 CLOSE #1:OPEN #1,4,0,FN$ 21111 IF KK=49 THEN BGET #1,CHBAS,1024:GOTO 21140 21112 IF KK=50 THEN BGET #1,CHBAS+1024,1024:GOTO 21140 21113 IF KK=ASC("I") 21114 GET #1,A:GRMODE=A-4:EXEC CYCLEGR 21115 FOR I=1 TO 15 21116 IF CREG(A-3,I) THEN GET #1,B:POKE CREG(A-3,I),B 21117 NEXT I 21118 ENDIF 21120 BGET #1,CHBAS,2048 21140 CLOSE #1 21150 TRAP 40000 21160 ENDPROC 21170 PROC FONTSAVE 21180 EXEC CLEARMENU 21181 POSITION 0,13:? "Save Mask ±, Mask ², ÆN2 or ÉCE file:"; 21182 GET KK 21183 IF KK<>ASC("F") AND KK<>ASC("I") AND KK<>ASC("1") AND KK<>ASC("2") AND KK<>27 THEN 21182 21190 POSITION 0,13:? "œInput filespec:";:INPUT #16,FN$ 21200 TRAP 40000 21210 CLOSE #1:OPEN #1,8,0,FN$ 21211 IF KK=49 THEN BPUT #1,CHBAS,1024:GOTO 21240 21212 IF KK=50 THEN BPUT #1,CHBAS+1024,1024:GOTO 21240 21213 IF KK=ASC("I"):TRAP 40000 21214 PUT #1,GRMODE+3 21215 FOR I=1 TO 15 21216 IF CREG(GRMODE,I) THEN PUT #1,CREGVAL(GRMODE,I) 21217 NEXT I 21218 ENDIF 21220 BPUT #1,CHBAS,2048 21240 CLOSE #1 21250 TRAP 40000 21998 MENU=0:EXEC CYCLEMENU 21999 ENDPROC To access the save and load functions, use "S" or "L" from the main menu. Edited August 7, 2011 by Synthpopalooza Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted August 7, 2011 Share Posted August 7, 2011 Attachment? Quote Link to comment Share on other sites More sharing options...
Synthpopalooza Posted August 7, 2011 Author Share Posted August 7, 2011 sorry, thought I had done that ... here it is icegtia.zip Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted August 7, 2011 Share Posted August 7, 2011 The I/O section in the attached program is totally different to the code snippet you posted. Is that intentional? Quote Link to comment Share on other sites More sharing options...
Synthpopalooza Posted August 7, 2011 Author Share Posted August 7, 2011 The I/O section in the attached program is totally different to the code snippet you posted. Is that intentional? Hmm ... I'll check. I think I found my problem anyway. When I tried running this in Atari800Win it worked properly, however for some reason running this with Altirra generates an error 136 everytime I try to use GET #1,A on any open filename. an updated zip with the new code is attached. Idea is: try running this in Altirra and see if there is an error-136, as opposed to Atari800Win. Quote Link to comment Share on other sites More sharing options...
Synthpopalooza Posted August 7, 2011 Author Share Posted August 7, 2011 Sorry, here it is ... icegtia.zip Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted August 7, 2011 Share Posted August 7, 2011 I can't seem to get it to crash in either emulator. 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.