neilsf / XC-BASIC

A compiling BASIC dialect for the Commodore-64
https://xc-basic.net/
MIT License
74 stars 15 forks source link

MandelBlock - git pushing a new example #136

Closed frenchfaso closed 3 years ago

frenchfaso commented 3 years ago

Hy @neilsf I wrote a little Mandelbrot set "renderer" in XC-Basic and was trying to "git push" it to the develop branch but it gives me a 403 error. I still suck at git, so I don't know if I messed up the creation of the auth token (no more password login through the cmd line...) or if you have to give me access somehow. :-)

Anyway, here it is, in all its big block resolution glory :-P

MandelBLOCK

rem MandelBLOCK - a blocky Mandelbrot set
rem inspired by Matt Hefferman's YT video "8-BIT battle royale" (https://www.youtube.com/watch?v=DC5wi6iv9io&t=1687s)
rem code based on Wikipedia's Mandelbrot set pseudocode (https://en.wikipedia.org/wiki/Mandelbrot_set)

const BORDER = $d020
dim py!
dim px!
dim i!
dim xz%
dim yz%
dim x% fast
dim y% fast
dim xt% fast

poke BORDER, 0
print "{CLR}"
memset 1024, 1000, 160

for py! = 0 to 24
for px! = 0 to 39
xz% = cast%(px!) * 3.5 / 40.0 - 2.5
yz% = cast%(py!) * 2.0 / 24.0 - 1.0
x% = 0.0
y% = 0.0
i! = 0
while x% * x% + y% * y% <= 4 and i! < 16
  xt% = x% * x% - y% * y% + xz%
  y% = 2.0 * x% * y% + yz%
  x% = xt%
  i! = i! + 1
endwhile

poke 55296 + py! * 40 + px!, i!
next px!
next py!

repeat : until inkey!() <> 0
neilsf commented 3 years ago

Hey @frenchfaso

I've given you access, please try again. Another way is to fork the repo and send a pull request.

This looks really great, thanks!

Can I give you some tips to speed it up?

For example the same calculations should not be done multiple times in a loop. You can move this line out of the loop, right before for px! = 0 to 39:

yz% = cast%(py!) * 2.0 / 24.0 - 1.0

It doesn't have to be calculated 40 times, only once!

With the same logic:

poke 55296 + py! * 40 + px!, i!

55296 + py! * 40 should only be calculated once per loop, not in every loop! You can move it in the outer loop.

But it's really cool anyway!

frenchfaso commented 3 years ago

Thanks @neilsf XC-Basic is a joy to use!

something like this? (disabling irq also seems to help a little bit with speed):

rem MandelBLOCK - a blocky Mandelbrot set
rem inspired by Matt Hefferman's YT video "8-BIT battle royale" (https://www.youtube.com/watch?v=DC5wi6iv9io&t=1687s)
rem code based on Wikipedia's Mandelbrot set pseudocode (https://en.wikipedia.org/wiki/Mandelbrot_set)
rem with speed optimizations suggested by Csaba Fekete, creator of XC-Basic

const BORDER = $d020
dim py!
dim px!
dim r
dim i!
dim xz%
dim yz%
dim x% fast
dim y% fast
dim xt% fast

poke BORDER, 0
print "{CLR}"
memset 1024, 1000, 160
disableirq

for py! = 0 to 24
  yz% = cast%(py!) * 2.0 / 24.0 - 1.0
  r = 55296 + py! * 40
  for px! = 0 to 39
    xz% = cast%(px!) * 3.5 / 40.0 - 2.5
    x% = 0.0
    y% = 0.0
    i! = 0
    while x% * x% + y% * y% <= 4 and i! < 16
      xt% = x% * x% - y% * y% + xz%
      y% = 2.0 * x% * y% + yz%
      x% = xt%
      i! = i! + 1
    endwhile
    poke r + px!, i!
  next px!
next py!

enableirq
repeat : until inkey!() <> 0

I've given you access, please try again. Another way is to fork the repo and send a pull request.

Ups.. sorry about that, I think I did the same mistake last time :-P I'll try to fork and pr.

neilsf commented 3 years ago

Yeah it looks really good. Just as a future improvement: I have the feeling that the entire problem can be solved using integers only :-) I can't prove it right now, but I'll think of it later when I have some more time. Thanks again!

frenchfaso commented 3 years ago

Sounds interesting! I'll check if I find some clues on the interwebs :-P

Do You think some kind of low / mid precision float type would be feasable (and faster) on the C64 ? Some kind of apps (and certainly noobs) could perhaps benefit from this additional type in xc-basic.

Thanks for the optimization tips, glad You liked MandelBlock!

neilsf commented 3 years ago

Do You think some kind of low / mid precision float type would be feasable (and faster) on the C64 ?

XC-BASIC 3 will have a less precise but faster 32-bit floating point format. It will offer a numeric precision of 5-6 decimal digits.

In general, fixed point is much faster for demos and games. For example if you have the number 10.5, just store it as integer 105 and divide it by 10 right before drawing. 105 / 10 will be effectively the same as CAST!(10.5) but the intermediate calculations will be magnitudes faster.

For much faster integer calculations, the ratio can be a power of 2 instead of 10. For example 16. So that the number 10.5 is stored as 168 (=10.5 * 16) and when you divide by 16, you do bit-shifting instead of division, e. g RSHIFT(168, 4). Bit shifting is much faster than multiplication or division.

frenchfaso commented 3 years ago

XC-BASIC 3 will have a less precise but faster 32-bit floating point format. It will offer a numeric precision of 5-6 decimal digits.

That's awesome! Cant wait to play with the alpha version :smiley: in the meanwhile I'll give the fixed point version a try.

For much faster integer calculations, the ratio can be a power of 2 instead of 10. For example 16. So that the number 10.5 is stored as 168 (=10.5 * 16) and when you divide by 16, you do bit-shifting instead of division, e. g RSHIFT(168, 4). Bit shifting is much faster than multiplication or division.

Really cooll trick! Thanks for the explanation!