pmgraphics Posted May 8, 2019 Share Posted May 8, 2019 I have a game program using graphics mode1. I want to check after each level is there are less than 35 blank spaces on the screen. My code below works but it is slow. Is there a quicker way in basic to do the same thing? 500 SPC=0:WIN=0 510 FOR RD=1 TO 18:FOR RB=1 TO 22 515 SETCOLOR 0,1+RD/2,1+RB/2 520 CHK=SCREEN+RD+20*RB:IF PEEK(CHK)=0 THEN SPC=SPC+1 530 NEXT RB:NEXT RD 540 IF SPC<35 THEN WIN=1:GOTO 800 Thanks Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted May 8, 2019 Share Posted May 8, 2019 It's difficult to perform iterations like these quickly in BASIC. Can you not keep a running tally of blank spaces rather than counting them up at the end? Presumably you know how many spaces exist at the start of a level, so when a space is revealed or overwritten, you could update the running total. 1 Quote Link to comment Share on other sites More sharing options...
NuY Posted May 8, 2019 Share Posted May 8, 2019 (edited) No idea if speed will increase with these but the code will be shorter: 1. This can be done in one FOR loop and line 520 simplified: 510 FOR RD=SCREEN+1 TO SCREEN+496 520 IF PEEK(RD)=0 THEN SPC=SPC+1 530 NEXT RB:NEXT RD 2. Use Boolean expression to increment the counter, so the IF in line 520 becomes: SPC=SPC+1*(PEEK(CHK)=0) 3. POP the FOR loops if the count reaches 35 or more, seeing as less than 35 is the win condition - if more are counted then there's no need to count the rest (unless you use that count elsewhere). All the above can be combined of course. Edited May 8, 2019 by NuY 1 Quote Link to comment Share on other sites More sharing options...
pmgraphics Posted May 9, 2019 Author Share Posted May 9, 2019 It's almost working. When I know there is only 34 blank spaces on the screen. The code reports that SPC = 51 crating an infinite loop elsewhere in the code since there are only 34 spaces and it is trying to do something with 35 spaces that it thinks are on the screen. 500 SPC=0:WIN=0 510 FOR RD=SCREEN+1 TO SCREEN+496 515 REM SETCOLOR 0,1+SPC/3,10 520 SPC=SPC+1*(PEEK(RD)=0) 530 NEXT RD 540 IF SPC<34 THEN WIN=1:GOTO 800 Quote Link to comment Share on other sites More sharing options...
pmgraphics Posted May 9, 2019 Author Share Posted May 9, 2019 (edited) I got it working. I changed SCREEN+496 to SCREEN+458 and using your code seems made it about 3 seconds quicker. I don't know why not including the screen border, which has no spaces and calculating the following SCREEN+(18+20*22) works. Thanks. >flashjazzcat: I can't explain it but tracking the spaces wouldn't work well. Edited May 10, 2019 by pmgraphics Quote Link to comment Share on other sites More sharing options...
Rybags Posted May 10, 2019 Share Posted May 10, 2019 Already mentioned but - You have a SETCOLOR with embedded calculations inside the loop - that alone is adding heaps of overhead. Rule #1 is keep unnecessary stuff out of such loops, do precalculations once wherever possible. The logic method you have there is almost right. No need to multiply by 1. 520 SPC=SPC+(PEEK(RD)=0) 2 Quote Link to comment Share on other sites More sharing options...
pmgraphics Posted May 10, 2019 Author Share Posted May 10, 2019 (edited) I have the setcolor in the loop to give the player some feedback, while the game searches for blank spaces, opposed to an apparent frozen screen. I removed the 1* thanks. Prior to removing 1* and setcolor it took 12-13 seconds to search for the blank spaces Removing the 1* saved 1 second Removing the setcolor saved almost 6 seconds, but then the player is staring at a non-responsive screen for about 7 seconds. It's a toss up to have something to look at over saving 6 seconds before the next level starts. Edited May 10, 2019 by pmgraphics Quote Link to comment Share on other sites More sharing options...
danwinslow Posted May 10, 2019 Share Posted May 10, 2019 It's been a long time since I did any BASIC, but I think you can dim a string and then go into the symbol table and mess with the address such that BASIC thinks it is at the screen data location. Maybe that would allow faster processing, but not sure. I do think it would be pretty easy to have a small USR routine (with or without the string manipulation above) that would be REALLY fast. Quote Link to comment Share on other sites More sharing options...
Rybags Posted May 11, 2019 Share Posted May 11, 2019 You could save a bit more time by putting the entire loop within a single Basic line - there's a bit of processing overhead every time a new line starts. Also, there's plenty of saving by having the loop near the beginning of your program instead of in the middle. In fact, with Atari Basic it's good practice to put all loops and subs that need extra speed help near the start of program, and just put a GOTO at the start to skip over them. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted May 11, 2019 Share Posted May 11, 2019 (edited) USR routine: pla lda #0 sta $D4 sta $D5 ldx #$E4 loop: lda screen,x bne notblank inc $D4 bcc notblank inc $D5 notblank: lda screen+$E4,x bne notblank2 inc $D4 bcc notblank2 inc $D5 notblank2: dex bne loop rts Just POKE in the 16 bit values for screen and screen+$E4. You can execute it right from a string (does not need DIMensioning). The value returned is the number of spaces. Note: if that number will always be less than 256, the bcc/inc$D5 lines can be removed. Edited May 11, 2019 by Nukey Shay 3 Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted May 11, 2019 Share Posted May 11, 2019 (edited) Creating a USR routine within an undimensioned string: Just run a short program that prints the CHR$ translation of the opcodes... Position the cursor on the printed text and hit enter to add the line to the program. Lines 200 - 240 would be what you use in your actual program (or wherever you initially set the GFX mode). Useage from then on: SPC=USR(A) It'll count them in a flash, so you can kill time with a loop with your setcolor instruction if you want a moment or three to pass. Edited May 11, 2019 by Nukey Shay Quote Link to comment Share on other sites More sharing options...
danwinslow Posted May 11, 2019 Share Posted May 11, 2019 Nice ^ Quote Link to comment Share on other sites More sharing options...
ricortes Posted May 11, 2019 Share Posted May 11, 2019 Fairly easy to return the value too if you are up for it i.e. X=USR... X can and ~does return an integer. Usually just a zero unless you specifically stuff a value to it. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted May 11, 2019 Share Posted May 11, 2019 The above routine does. The value returned for USR is whatever exists at $D4/$D5 (decimal 212 & 213). USR routines can also pass 16 bit arguments the other way. That is why they require a PLA instruction to start out...that is the number of arguments used in the USR command being pulled off the stack. The rest are pulled off in reverse order (MSB first, then LSB). Quote Link to comment Share on other sites More sharing options...
pmgraphics Posted May 12, 2019 Author Share Posted May 12, 2019 USR routine: pla lda #0 sta $D4 sta $D5 ldx #$E4 loop: lda screen,x bne notblank inc $D4 bcc notblank inc $D5 notblank: lda screen+$E4,x bne notblank2 inc $D4 bcc notblank2 inc $D5 notblank2: dex bne loop rts Just POKE in the 16 bit values for screen and screen+$E4. You can execute it right from a string (does not need DIMensioning). The value returned is the number of spaces. Note: if that number will always be less than 256, the bcc/inc$D5 lines can be removed. I never got beyond basic as a kid. It would be great to learn how and what to do with the above. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted May 12, 2019 Share Posted May 12, 2019 The Basic routine in the screenshot above puts it in memory. It is relocatable, so you can POKE it into page 6 if you want to. "Page 6"...i.e. the 256-byte area of memory starting at hex address $600 (1536 decimal), is left alone by Atari Basic and DOS...so you can place small machine-language programs there without worry of corruption. To use page 6 instead, change the following lines: 5 A = 1536 30 POKE 1535+I,J Erase lines 50 and 60, and there you go. You can still call the routine via SPC=USR(A) Or just use SPC=USR(1536) if you don't want to burn a variable name in the main program. There's a thread around here someplace that has a disk image with a lot of small USR routines like these you can use to *drastically* speed up Basic bottlenecks (like moving P/M stuff around and such). Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted May 12, 2019 Share Posted May 12, 2019 Found it http://atariage.com/forums/topic/220899-basic-turbocharger/ The author used character codes in strings tho, which are really hard to make out in print. The disk images of all the routines were included in the Holmes archives...MrFish reposted them here (reply 14) http://atariage.com/forums/topic/116887-basic-subroutines/ Quote Link to comment Share on other sites More sharing options...
pmgraphics Posted May 13, 2019 Author Share Posted May 13, 2019 I created line 200 with the ADR string. Do I replace line 520 with your lines 200 - 240? What if I want to make a change in the number of spaces to find (as in line 540) or find a different character? 500 SPC=0:WIN=0 510 FOR RD=SCREEN+1 TO SCREEN+458 515 SETCOLOR 0,SPC/3,9 520 SPC=SPC+(PEEK(RD)=0):IF SPC>35 THEN 610 530 NEXT RD 540 IF SPC<=34 THEN WIN=1:GOTO 2000 Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted May 13, 2019 Share Posted May 13, 2019 "Do I replace line 520 with your lines 200 - 240?" Pay no attention to the line numbers I used...those were there just to keep the instructions sequential. If you are using the string, you need to add a line (or lines) containing those POKE instructions -after- you set the graphics mode. Those 4 POKE instructions set the screen address that the string uses to check for characters. Once that is set up, your line 500 should read as follows: 500 WIN=0:SPC=USR(A) Lines 510, 515, 520, and 530 are no longer needed. The machine-language USR routine is replacing the job that loop was doing. "What if I want to make a change in the number of spaces to find (as in line 540)" Just change the 34 in line 540 to whatever the WIN condition is. The USR routine is just counting the total. "or find a different character?" That would need a different routine...this is just checking for zeros (spaces). pla lda #0 sta $D4 sta $D5 ldx #$E4 loop: lda screen,x cmp #char bne notblank inc $D4 bcc notblank inc $D5 notblank: lda screen+$E4,x cmp #char bne notblank2 inc $D4 bcc notblank2 inc $D5 notblank2: dex bne loop rts 4 bytes longer. Notice the difference? Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted May 13, 2019 Share Posted May 13, 2019 (edited) Better yet, you could make a generic routine so you can use the USR command a bunch of times to check for different types of characters... pla lda #0 sta $D4 sta $D5 pla pla ldx #$E4 loop: cmp screen,x bne notblank inc $D4 bcc notblank inc $D5 notblank: cmp screen+$E4,x bne notblank2 inc $D4 bcc notblank2 inc $D5 notblank2: dex bne loop rts That routine is adding an argument to the USR routine. You'd use the PEEK value of whatever character you are searching for within the USR command itself. To search for ! characters, you'd do this: TOTAL=USR(A,1) Checking for spaces in this case would be: SPC=USR(A,0) Do you want to see a string to use that method instead? Edited May 13, 2019 by Nukey Shay 1 Quote Link to comment Share on other sites More sharing options...
pmgraphics Posted May 13, 2019 Author Share Posted May 13, 2019 (edited) It would be great to have a routine that could search for any character. Thanks. BTW: I added the string line and the four POKE instructions after my GR.17 at the top of my program. I get an ERROR 3 (Global variable symbol table full) when I run the program. Prior to it being run is my GOSUB to my character redefining instructions. Update to Error 3: I removed the +228 from line 230. I don't know what it means but it seemed out of place. Doing so resulted in no error 3 and the blank spaces were tallied very fast. Edited May 14, 2019 by pmgraphics Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted May 14, 2019 Share Posted May 14, 2019 Similar oddities on this end...for some reason, branching instruction BCC refused to work properly. No matter...I'll work around it! Generic screen check program: This uses 4 zero-page locations...203/204 to save the base address, 205/206 for the number of bytes to check The program got a little longer due to the BCC problem, but it works (52 bytes total). You can put it in a string or wherever you want. No additional POKEs needed, so you can throw those lines away. pla ;pull # of arguments pla ;set start address sta 204 pla sta 203 pla ;set # of bytes sta 206 pla sta 205 pla ;set char to look for pla ; (LSB only) ldy #0 ;clear counter sty 212 sty 213 ldx #255 ;used for rollover check loop cmp (203),y ;current pos = character bne nomatch ;branch if no inc 212 ;increase counter bne nomatch ;branch if no rollover inc 213 ;increase counter*256 nomatch: inc 203 ;move to next byte to check bne bumpindex ;branch if no rollover inc 204 ;bump MSB of next byte to check bumpindex dec 205 ;decrease the number of bytes left cpx 205 bne loop dec 206 cpx 206 bne loop rts ;no bytes left, return ;52 bytes total DATA 104,104,133,204,104,133,203,104,133,206 DATA 104,133,205,104,104,160,0,132,212,132 DATA 213,162,255,209,203,208,6,230,212,208 DATA 2,230,213,230,203,208,2,230,204,198 DATA 205,228,205,208,234,198,206,228,206,208 DATA 228,96 Usage: var=USR(ProgramAddress,StartAddress,NumberOfBytes,Char) as in... SPC=USR(1536,SCREEN,458,0) if the program is in page 6, SCREEN=PEEK(88)+256*PEEK(89), check 458 bytes total, look for character 0 (spaces) 3 Quote Link to comment Share on other sites More sharing options...
pmgraphics Posted May 14, 2019 Author Share Posted May 14, 2019 (edited) After I create the string do I assign it to a variable like the first example as in A=ADR(" ...the new string.. ") just after the graphics mode set? In the usage example how do I then include the string in the SPC=USR(1536,SCREEN,458,0) line? PS: I did not thoroughly test the first routine that only tallies spaces. When I knew there was about 90 spaces, SPC=USR(A) returned a value under 10. To test I created a scenario where there was 329 spaces each time, and SPC=USR(A) returned only 50, then 48, then 46, then 46, then 54. It seems the first routine is not calculating the correct number of blank spaces, or I have done something wrong. My code is below Edited May 14, 2019 by pmgraphics Quote Link to comment Share on other sites More sharing options...
pmgraphics Posted May 14, 2019 Author Share Posted May 14, 2019 (edited) I used the any character method in my code as follows, by replacing the 1536 in the USR statement with the variable A (seemed most logical to do). 5 GR.17:SCO=0:LI=6:GARD=0:SPC=0:ME=0 7 A=ADR("...the new string for any character...") 10 POKE 756,CH/256:SCREEN=PEEK(88)+256*PEEK(89):GOTO 600 500 SPC=USR(A,SCREEN,458,0):WIN=0 505 POSITION 0,23:? #6;SPC 510 FOR COL=0 TO 35:SETCOLOR 0,COL/3,9:NEXT COL 540 IF SPC<=34 THEN WIN=1:GOTO 2000 550 GOTO 610 Running the similar condition of 319 blank spaces, SPC=USR(A,SCREEN,458,0) always returns a count of 319. Looks like this method is working. Edited May 14, 2019 by pmgraphics Quote Link to comment Share on other sites More sharing options...
sanny Posted May 14, 2019 Share Posted May 14, 2019 ...for some reason, branching instruction BCC refused to work properly. No matter...I'll work around it! BCC probably works as it should, but INC doesn't change the carry flag... 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.