Jump to content

looking for faster method to check for blank spaces

Recommended Posts

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

Share this post

Share on other sites

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.

Share this post

Share on other sites

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 by NuY

Share this post

Share on other sites

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
```

Share this post

Share on other sites

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 by pmgraphics

Share this post

Share on other sites

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)

Share this post

Share on other sites

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 by pmgraphics

Share this post

Share on other sites

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.

Share this post

Share on other sites

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.

Share this post

Share on other sites

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 by Nukey Shay

Share this post

Share on other sites

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 by Nukey Shay

Nice ^

Share this post

Share on other sites

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.

Share this post

Share on other sites

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).

Share this post

Share on other sites

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.

Share this post

Share on other sites

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).

Share this post

Share on other sites

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/

Share this post

Share on other sites

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
```

Share this post

Share on other sites

"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?

Share this post

Share on other sites

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 by Nukey Shay

Share this post

Share on other sites

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 by pmgraphics

Share this post

Share on other sites

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)

Share this post

Share on other sites

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 by pmgraphics

Share this post

Share on other sites

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 by pmgraphics

Share this post

Share on other sites

...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...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

• Recently Browsing   0 members

No registered users viewing this page.

×
×
• Create New...