Great video Robin! And thank you for the shout-out! That clear screen trick is really neat :) I would love to make a follow-up video but it will be hard to make any better solution than yours. However, I modified your code a bit to make the ball flicker less and move faster :) (this is not a valid bounce ball program but it's fun!) 0dEfna(b)=aB(ti-int(ti/b)*b-b/2):g=z:z=1024+fna(48)*40+fna(78):pOg,32:pOz,81:gO
@@8_Bit If you look at my comment from yesterday, @caspianmaclean8122 and i found a way to make a one-liner without using FN() and with less flicker by drawing the new location first before deleting the old one. 0 x=1-x*(x
Instead of removing the ball first and then drawing it at the new location, you might want to switch it around and draw the ball at the new location first and then remove it. Instead of flickering it will then have a after image which is much more pleasant on the eyes.
Really cool! I don't think I've seen that trick before. Nice work, I'll keep that in mind next time I need looping numbers. For anyone wanting to try it, here's a version with a couple typos fixed: 0x=1-x*(x
Once again, you're bringing adult recreational thinking to our collective childhood programming experiences. :) It's like "here's your toy from childhood, and look, here's new ways to play with it!". I remember liking that program back in the day because it contained the variable DY, my initials (that's kinda vain, isn't it?). Didja ever submit an entry to the yearly 10-line basic programming competition? You're clearly optimized for such things.
You can get rid of the flicker by drawing the new position first before deleting the old one. You can do that in 2 lines, which also allows you to only call def() once. You could even add a clear screen to that. 0 DEFFNA(B)=ABS(T-INT(T/B)*B-B/2) 1 D=1024+FNA(48)*40+FNA(78):POKED,81:POKEC,32:C=D:T=T+1:GOTO1
@@caspianmaclean8122 Hmmm, it runs for one iteration and then i get a "syntax error" and it actually overwrites the program itself! I also believe you have two typos in your listing above, i think it should be x
I think i found the problem. Since you're starting at the end of the screen memory, you're writing into the basic program at 0x0800 because of the way you're accumulating the x,y location. Going to play with this a bit today.
The one issue with bouncing ball is if you use even numbers X and Y length of the field ball will go in same trajectory. I found out is best to limit like to 39 for example over X. Then ball will cover every position on the screen. You can test that with not clearing the old posiition.
It is not about evenness, strictly speaking. It happens because 40 and 25 have a common divisor, 5. 39 and 25 don't, indeed. 40 and 24 do as well, and so do 39 and 24, so nudging Y doesn't help.
Here's a version that's slightly shorter, and also clears the screen! The ball flickers a little bit more though. 0dEfna(b)=aB(t-int(t/b)*b-b/2):print"(cls)":pO1024+fna(48)*40+fna(78),81:t=t+1:gO While watching the video I was thinking of alternate approaches, such as having an index that starts at 0 and step variable that cycles between 41, 39, -41, and -39 as appropriate, but nothing was more compact than what you came up with.
Nice idea, but I find that inserting that code into the poke like you did (I tried it), results in more flicker where as if you leave it as it was, assigning it to Z and just adding the ?"{CLS}" before the pokez,81, it will almost be flicker free. The reason it flickers more is you clear the screen, than it does the calculations before it pokes which results in a delay that causes the ball to be gone longer before it is redrawn. I wonder if you did it your way, but put the CLS AFTER you poke the ball, which would probably reduce the flickering more as the ball would be on screen longer while your poke does the calculations (which is the slower part of this).
@@NeilRoy Sure, but code golf is about trying to fit as much as possible into one space, not about it necessarily producing the best results. :) Also I totally forgot that print can be abbreviated as ? which would have saved even more space.
Well done, mind melting solution onto one line. This bouncing ball programme (well the vic 20 version) was one that never left my memory since i discovered it all those years ago.
I used to come up to people with an one liner, on the C64, that moved a ball erratically and replaced the old posistion with the reverse circle. Looked hilarious and I had to resort to two lines to make it also move diagonally. I called it the miner.
Man this took me back. In the 80s we used to have 1 liner, 5 liner and 10 liner programming challenges. It really is incredible what people came up with. Simple text editors, databases, even a few games. I miss the ingenuity of the 8 bit days.
Just got a pristine copy of the PRG after nearly 40 years. Looking forward to reacquainting myself with its contents. That’s a delightful solution to clearing the screen.
This "all these lines into one line" thing never gets old. Seriously. It's always amazing to watch the process. I think by now, you might showcase "it can't be done" examples and let's see if your audience will participate in trying and presenting their results to you somehow. You're so good at what you do, but I'm curious if there are things you can't do?!
Love your investigations and experiments Robin! Thank you so much for taking the time for us :D (if you can guarantee that the ball won't be in the same place, drawing the new position then erasing the old position will look far less flickery (a ball will always be visible) and look smoother (as the moment where two balls are visible will act as an intermediate frame of animation))
I’m assuming this raises the issue of needing another variable to track the old position. Definitely good for a longer version. And even having a trail of a few balls (“snake”) would be cool.
@@andrewgillham1907 - If there's a smaller circular character, that could be written over the old position, and then blanked on the next frame - that would play into the 'ghosting' effect - although does mean an additional trailing-blanking write - so would be slower
@@andrewgillham1907 I could be wrong, but a new variable should not be required. Robin just needs to display then erase, rather than erase then display. I'm not entirely clear on what the pokes do, so I could very wrong. I just know that from my own experience of moving a dot in Atari BASIC, it was relatively smooth compared to this. Then again, I never it down to 1 line of code.
I used that Bounding Ball program and made it into a breakout game. I managed to get it to run very well considering it was all in basic. I later got it to run better and with redefined characters by using Simons' Basic cartridge and improved the overall programming. I was 13 at the time and it was 1984. Just wish I had the cassette it was saved on today.
Yeah, back in the day, some friends of mine wanted us to create a similar Breakout game that we called "Beat The Wall" (basically me telling them what to type in)... based on this bouncing ball program. On the first test run there was a bug in the bit that was supposed to detect the block and bounce it back so the ball just ripped through all the blocks. They all laughed, got bored and gave up, so we never got to fix it. To this day they are still making fun of me for my crappy "Beat The Wall" game!
0:26 My first programming experience was with the VIC-20 User's Guide. 14:16 The program didn't change the cursor color. By default, on newer C64s, it'd be light blue, which would probably be worse. 18:42 There'd be more variety to the bouncing pattern if the numbers of rows and columns were primes. 19:37 The relative flicker is also reduced by keeping the ball on the screen much longer than it's turned off. 28:26 Should start malfunctioning after T reaches 4.2-billion. 36:01 The abbreviations would be more clear if the character set were lowercase. 39:10 I get 2.10 seconds for T to increment 40 times, meaning it will take 7.1 years to overflow the integer range of floating-point numbers. Slowing the program down by re-executing the DEF FN helps to avoid this! It should never "overflow" the floating-point range since after passing the 32-bit mantissa range, T=T+1 will effectively round down to T=T+0.
That's very interesting about the width and height affecting the bouncing pattern; that's configurable on the VIC-20. Maybe a one-line VIC-20 version could also set the screen to 29x23 to make it more interesting. Or if 29 is too wide, 23 by 19 or something. Good point about T=T+1 rounding down to T=T+0! So I suppose the ball would just freeze once the 7+ years or whatever had passed. It would appear to have crashed, but it's really just adding (effectively) zero each step.
I'm so glad I finally watched this. I'm usually not a big fan of "code golf" and I thought 40m seemed long for "one line". But, wow, I have never seen anyone give such a lucid step-by-step process of transforming a program. Amazing job in story telling, giving the motivation before each change. For me, it was like clues so I could pause the video and try to guess what's coming next instead of being told the answer outright. (For example, when you showed how the numbers oscillate.) I also love that you explained everything at the perfect level, not skipping over things a C64 expert might forget to mention, like G shift+O is shorthand for GOTO. You didn't dwell on anything too long, either, or overexplain. In fact, I feel guilty now with this comment because I've clearly gone on far too long just to say "THUMBS UP! You've got a new subscriber."
Nice work Robin. It is definitely fun to “re-experience” the joy you got as a kid going through the C64 User Guide. 😀 The bouncing ball is neat and cramming it into one line is impressive. I would say another feature people could try to add is some way to get more randomness as the ball is clearly only following a few paths over and over. With some randomness it should eventually clear the whole screen not just certain paths. Anyway keep up the good work. I’m amazed (& entertained) by how far “10 PRINT” and/or one-liners can go and still be fairly comprehensible. And look cool.
Yes, it would be more interesting if it somehow followed a more varied path. As csbruce noted, if the width and height of the screen were prime numbers, such as 41x23, then the same logic would allow it to cover the whole screen.
@@kernelramdisk3348 They don't have to be primes, just relatively prime (i.e. not sharing any common factors other than 1). It's because then the wavelengths wouldn't match up so frequently.
I think the early days of the C64 were the best. Those programs were just a nice way to get to know the computer. Although I I always sucked at programming.
Robin, thanks for the screen clear idea. It's very counter intuitive way of thinking, because we have to add something to it to make it not be active, as opposed to doing something to it to make it active...or something like that. I just know that some vehicle braking systems require power to male them be released, rather than requiring power to make them work. It seems like there are more opportunities to use math to control things on the screen. By the way, I really appreciate the oscillator info. I watched portions several times, and learned a lot over the last 24 hrs. Thank you so much.
Three decades late, but I’m finally into a little CBM programming myself, and these videos helps me a lot. Thank you! I bought a second hand C64 manual. It’s printed in the UK and less fancy than the one you showed. The code examples are just plain text on paper, not with a black background. The horrible color green in the bouncing ball code is however replaced by blue. The music chapter is totally different than the US version. Strange. Perhaps you can spend a whole episode on the different versions C64 User Guide……
I altered it slightly. I removed the pokez,32 and put a ?"{CLS}" just before the pokez,81 so the screen is cleared, then the ball is drawn and the ball stays on screen most of the time during code execution and is only momentarily cleared before redrawn and this clears the screen of course. It's almost flicker free this way. I tried adding the Z calculation within the poke but I find it flickers much more that way because the ball is gone longer while it calculates the position before poking where as calculating that ahead of time means the ball is on screen during calculations and only moved once they are complete resulting in almost no flicker at all except to move it.
Alternate bouncing ball: 0D=-(X=0)+(X=39)+D:E=-(Y=0)+(Y=24)+E:X=X+D:Y=Y+E:POKEA,32:A=1024+Y*40+X:POKEA,81,GOTO Still 79 characters crunched. Once difference though, it takes two loops to reverse direction, because the D/E calculations only add or subtract 1. So D/E end up zero at the first boundary check, then will be +/-1 the next.
I think there are a few mistakes like; Y=Y+D => Y=Y+E 1024+Y*40 => 1024+Y*40+X Copy & paste ready version is below: 0d=-(x=0)+(x=39)+d:e=-(y=0)+(y=24)+e:x=x+d:y=y+e:pOa,32:a=1024+y*40+x:pOa,81:gO
I realized I can save 2 characters: 0d=d-(x=0)+(x=39):e=e-(y=0)+(y=24):x=x+d:y=y+e:pokea,32:a=1024+y*40+x:pokea,81:goto Or you can reduce the flicker by moving the *40: 0d=d-(x=0)+(x=39):e=e-(y=0)+(y=960):x=x+d:y=y+e*40:pokea,32:a=1024+y+x:pokea,81:goto
From time to time I enjoy working on one-liners to learn from other programmers, and I try to improve them. I do not know if you are interested or if you care at all, but I managed to get your code a bit faster. Thank you for your interest, and maybe a friendly comment. Best, Holger 0 D=D-(X=.)+(X=39):E=E-(Y=.)+(Y=24):X=D+X:Y=E+Y:P🭽A,32:A=Y*4E1+X+1024:P🭽A,81:G🭽 0 D=D-(X=.)+(X=39):E=E-(Y=.)+(Y=24):X=D+X:Y=E+Y:POKEA,32:A=Y*4E1+X+1024:POKEA,81:GOTO
Very clever techniques indeed, anyways, 35:18 for a second I thought why not we pass T as argument along with B and then we can goto 1 and eliminate the time needed to redefine the function, but then I realized that only one argument is supported. If I remember correctly MSX supports multiple arguments per function and one line of code can be 255 characters, it also has a LOCATE command to print at specific x,y coordinates, which gives you more room for one-liner programs (not so challenging for you, I know😎). anyways, commodore is more capable graphic wise I believe. Thanks Robin!
I had never noticed the screen colors of the 'bouncing ball' program. I went to pick up my 1986 manual and in fact... POKE 53280,7:POKE 53281,13 ... At the time I was using the C64 with a Mivar (Italian brand) 17 inches black and white 😁👍🏻
Commodore's sample code has lots of computation occurring between the time the ball is erased and once again redrawn. While certainly not compact, I think there is value in having some time delay leaving the ball visible versus hidden (call it the visible duty cycle, if you like). Here's one idea of how it might be coded... 10 poke53280,11:poke53281,0:poke646,7 20 dx=1:dy=1:printchr$(147); 30 a=1024+40*y+x:ifb=0thenb=a 40 pokeb,32:pokea,81:fort=1to10:next 50 b=a:x=x+dx:y=y+dy 60 ifx38thendx=-dx 70 ify23thendy=-dy 80 goto30
Your 'bouncing ball' has elements of 'Breakout' about it. It is slowly removing the white text but it ends in a repeating loop following determined paths.
Fun video to watch. It brings back memories when I had to crunch code. Thanks for the video. I suppose the next step would be to execute this in machine language? But that is another video...!!! LOL!
I would suggest starting an IOC64BCC but let's face it, it's hard not to write obfuscated C64 BASIC. Although, you might be able to compete in the IOCCC if you know C. I am curious if you could implement a real time flight sim on the C64, as that is definitely the most impressive entry I've seen. Check out Banks' entry in 1998, even shaped the source code to look like an airplane.
Fascinating use of the DEF FN there. I remember typing this in and making small changes - removing the space so you get a trail, starting at different points and getting rid of those awful colours!
Well done. I wonder how this could be adapted for the VIC-20. I think I preferred the 2-line version. You've optimized for space at the expense of efficiency. The division operations are expensive. Fun video. Thanks Robin
14:35 My first two thoughts as a developer immediately after I saw this code for the very first time: 1024+X+40*Y should be stored to a variable, so it doesn't have to be calculated twice and lines 60 and 70 should come after line 110, so the ball is constantly visible on screen during all the other code lines that also take time to execute, probably reducing the flickering a lot (and as the address is cached, it's okay to change X and Y, clearing is done via the cached address). So with zero C64 programming experience, I'd suggest the following optimization: 10 PRINT CHR$(147) 20 POKE 53280,7 : POKE 53281,13 30 X=1 : Y=1 40 DX=1 : DY=1 45 ADDR=1024+X+40*Y 50 POKE ADDR,81 80 X=X+DX 90 IF X=39 THEN DX=-DX 100 Y=Y+DY 110 IF Y=24 THEN DY=-DY 115 FOR T=1 TO 10 : NEXT 116 POKE ADDR,32 120 GOTO 45
@@BikeAreaBut would that make a performance difference? As if not, source code is written for human beings, computers (and also interpreters) would be fine with just hex digits (much easier to process, even for an interpreter).
For anyone who doesn't know what a fortnight is that the program could run for ~55 of them... They are about equal to 6 7/8 stone or 4.9 decibushels. Total run time is a little over two years.and one month.
Great ... Here the MM Basic Version for the Raspberry Pi Pico (PicoMite VGA) in MM-Basic ____ Do :D=12*A(78):E=8*A(158):Text E,D,"0":Inc T:Pause 20:Text E,D," ":Loop Function A(B):A=Abs(T-Int(T/B)*B-B/2):End Function ___ 🙂
my lazy bouncing ball in 79 standard character input. Amiga demo scene eat ur heart out lol: 2 pokes,46:s=1024+40*sin(t/40)^2+int(25*sin(t/25)^2)*40:pokes,81:t=t+1.5:goto 2
From time to time I enjoy working on one-liners to learn from other programmers, and I try to improve them. I do not know if you are interested or if you care at all, but I managed to get your code a bit faster. Thank you for your interest, and maybe a friendly comment. Best, Holger 0P🭽S,46:S=S╮(T/4E1)↑2*4E1+INT(25*S╮(T/25)↑2)*4E1+1024:P🭽S,81:T=T+1.5:G🭽 0 POKES,46:S=SIN(T/4E1)↑2*4E1+INT(25*SIN(T/25)↑2)*4E1+1024:POKES,81:T=T+1.5:GOTO
Hey, Robin, what are some of your favorite clever code snippets in C64 BASIC? For me, when I saw this particular one in a magazine listing once it stuck with me to this day for its simplicity and usefulness: A = 1 - A Very useful for alternating between 0 and 1 (or any two values with some slight modification). Another I like, which I believe only works on 8 bit Commodore computers, is for multi-loading: 10 If A = 0 Then A = 1: Load "part 1",8,1 20 If A = 1 Then A = 2: Load "part 2",8,1 etc. This was a mystery to me until I found out why it works.
On the AMSTRAD CPC you could use the CRTC to synchronise to frame flyback so that the program could synchronise to each frame on the display with a single CALL instruction. This way you'd get rid of the flickering. Surely there is a poke on the C64 for this?
Haha, I wondered about _that_ color combination too! Wouldn't exactly be even worse on a B/W TV or other monitor, since it seems to have low contrast? Wouldn't a grayscale screen make it even lower contrast? Yeah, I would definitely like to see this with a dark background and a light ball or vice versa.
I know that code! I made a rudimentary brickout game with it when I first got my C64!! Semirelated, but I recently tried porting Steve Wozniak's Little Brickout to C64 BASIC. The original version relies heavily on Integer BASIC draw commands so it's a really interesting challenge trying to get it working and playable on the C64. The only way I found it could be done was if I used print commands to draw the paddle instead of pokes to screen memory. Unfortunately that also meant having the game play lopsided, with the paddle moving horizontally at the top of the screen. I'm not a BASIC pro, though, so I'd be really interesting in seeing what techniques you might use to get it working!
Robin did an assembly-language version of the maze not that long ago. I recall it being about 100x faster than the BASIC implementation. That's a lot faster but not blindingly fast. It's still calling the BASIC functions to print and scroll. Further optimization could be done, but that would be an unfair comparison.
That was fun! I was wondering why, in your two line version before the final, why did you choose to GOTO 0 (where the function was defined) instead of GOTO 1? Very clever optimizations!
From time to time I enjoy working on one-liners to learn from other programmers, and I try to improve them. I do not know if you are interested or if you care at all, but I managed to get your code a bit faster. Thank you for your interest, and maybe a friendly comment. Best, Holger 0X=X+1+78*(X=39):Y=Y+1+48*(Y=24):P🭽A,32:A=A🭲(Y)*4E1+A🭲(X)+1024:P🭽A,81:G🭽 0 X=X+1+78*(X=39):Y=Y+1+48*(Y=24):POKEA,32:A=ABS(Y)*4E1+ABS(X)+1024:POKEA,81:GOTO
in the 2 line bouncing ball, what if line 0 had the x and y drawing of a blank space happen before the coordinates being calculated with a line separator with the colon between the action to clear the coordinate and the coordinate calculation of line 0? is that possible in that method? If so, shouldn't most of the flicker of the drawing be negated?
I was wondering, what's the name of the "Island " demo Robin mentioned in some videos which he described as "has a lot of moving objects on the screen at once"? I can't seem to find, so let's see if someone can help. :)
From time to time I enjoy working on one-liners to learn from other programmers, and I try to improve them. I do not know if you are interested or if you care at all, but I managed to get your code into one line. Thank you for your interest, and maybe a friendly comment. Best, Holger 0D🭶FNA(B)=A🭲(T-INT(T/B)*B-B/2):X=4↑5+FNA(48)*40+FNA(78):P🭽Z,0:Z=X:P🭽Z,8:T=T+1:G🭽 0 DEFFNA(B)=ABS(T-INT(T/B)*B-B/2):X=4↑5+FNA(48)*40+FNA(78):POKEZ,0:Z=X:POKEZ,8:T=T+1:GOTO
True, but on the bright side, it introduced many of us to the lower-level workings of the computer and made assembly language that much more attractive.
@@8_Bit Of course, you can still do that on many other computers if you want to, but you don't _need_ to. Somewhere I have a dot matrix printed list of Apple II BASIC commands and their PEEK/POKE/CALL equivalents.
Yes, I'm mainly saying it gave us some extra motivation to learn assembly. It'd be interesting to see if Commodore machines in particular produced more assembly language programmers per capita than those with friendlier BASICs. On the flip side, the TI-99/4a had a PRINT AT like feature (CALL HCHAR, I believe) but no POKEs or SYS at all, completely preventing the user from dabbling with any feature (such as sprites) that weren't built into the language, and even preventing machine language programs from being loaded from tape. The only solution is to buy the Extended BASIC cartridge for extra money to unlock those features.
@@8_Bit Probably most TI owners had the Extended BASIC cartridge, because the built-in BASIC is so slow and limited, and lots of software on cassette required it. TI did have an assembly language cartridge for it, too, although that required a 32K disk system to run.
@@vwestlife _Beagle Bros_ *Peeks, Pokes, and Pointers* chart was super popular back in the day. Also _S-C DocuMentor Applesoft Disassembly_ is a reversed engineered listing of Applesoft by Bob Sander-Cederlof.
Maze/like pattern: The whole screen clearing is unnecessary: Just doing print and jump makes the program so fast that the screen will quickly fill up with pattern anyway.
Hey ....how do u input user definable graphics...its easy on the BBC...u know we're you add the squares together that are numbered 1 2 4 8 16 32 64 128 in any combination
Great video Robin! And thank you for the shout-out! That clear screen trick is really neat :)
I would love to make a follow-up video but it will be hard to make any better solution than yours.
However, I modified your code a bit to make the ball flicker less and move faster :)
(this is not a valid bounce ball program but it's fun!)
0dEfna(b)=aB(ti-int(ti/b)*b-b/2):g=z:z=1024+fna(48)*40+fna(78):pOg,32:pOz,81:gO
Nice work Josip, thanks for your interesting posts and videos!
@@8_Bit
If you look at my comment from yesterday, @caspianmaclean8122 and i found a way to make a one-liner without using FN() and with less flicker by drawing the new location first before deleting the old one.
0 x=1-x*(x
Nice one, Cyb! That's a really cool trick.
Both your channels are great, nice to see you both shouting each other out. :)
@@HAGSLAB Thank You :)
Instead of removing the ball first and then drawing it at the new location, you might want to switch it around and draw the ball at the new location first and then remove it. Instead of flickering it will then have a after image which is much more pleasant on the eyes.
If you check out the pinned post comments someone actually implemented exactly what you are saying.
Exactly what I was thinking.
YES!!! New 8-bit S&T Episode!!! Heck yes. Robin your channel seriously rocks.
heck. lol.
@@endoflevelboss didn't want my comment o get blocked :p
I found x=1-x*(x
Really cool! I don't think I've seen that trick before. Nice work, I'll keep that in mind next time I need looping numbers.
For anyone wanting to try it, here's a version with a couple typos fixed:
0x=1-x*(x
Had a blast with this one. Setup my "The C64" (no old hardware anymore. :( ) and typed along. I liked the seeing a good use of DEF FN.
Once again, you're bringing adult recreational thinking to our collective childhood programming experiences. :) It's like "here's your toy from childhood, and look, here's new ways to play with it!". I remember liking that program back in the day because it contained the variable DY, my initials (that's kinda vain, isn't it?).
Didja ever submit an entry to the yearly 10-line basic programming competition? You're clearly optimized for such things.
Thanks, I still haven't tried the 10-line compo. I really should sometime. That's funny about the DY! :)
Wow, Robin, that clear-screen-only-once trick is pretty clever! I don't think I would have ever thought of that on my own in my whole life!
You can get rid of the flicker by drawing the new position first before deleting the old one. You can do that in 2 lines, which also allows you to only call def() once. You could even add a clear screen to that.
0 DEFFNA(B)=ABS(T-INT(T/B)*B-B/2)
1 D=1024+FNA(48)*40+FNA(78):POKED,81:POKEC,32:C=D:T=T+1:GOTO1
I found enough space to draw before erase on one line:
0x=1-x*(y
@@caspianmaclean8122 Hmmm, it runs for one iteration and then i get a "syntax error" and it actually overwrites the program itself!
I also believe you have two typos in your listing above, i think it should be x
I think i found the problem. Since you're starting at the end of the screen memory, you're writing into the basic program at 0x0800 because of the way you're accumulating the x,y location. Going to play with this a bit today.
Yes!
0 x=1-x*(x
Saved another 2 chars:
0 x=1-x*(x
The one issue with bouncing ball is if you use even numbers X and Y length of the field ball will go in same trajectory. I found out is best to limit like to 39 for example over X. Then ball will cover every position on the screen. You can test that with not clearing the old posiition.
It is not about evenness, strictly speaking. It happens because 40 and 25 have a common divisor, 5.
39 and 25 don't, indeed.
40 and 24 do as well, and so do 39 and 24, so nudging Y doesn't help.
Never touched a C64, I'm more savvy in C, but I love watching your videos because they bring so much wisdom about the fundamentals of programming! ❤
Here's a version that's slightly shorter, and also clears the screen! The ball flickers a little bit more though.
0dEfna(b)=aB(t-int(t/b)*b-b/2):print"(cls)":pO1024+fna(48)*40+fna(78),81:t=t+1:gO
While watching the video I was thinking of alternate approaches, such as having an index that starts at 0 and step variable that cycles between 41, 39, -41, and -39 as appropriate, but nothing was more compact than what you came up with.
Nice idea, but I find that inserting that code into the poke like you did (I tried it), results in more flicker where as if you leave it as it was, assigning it to Z and just adding the ?"{CLS}" before the pokez,81, it will almost be flicker free. The reason it flickers more is you clear the screen, than it does the calculations before it pokes which results in a delay that causes the ball to be gone longer before it is redrawn.
I wonder if you did it your way, but put the CLS AFTER you poke the ball, which would probably reduce the flickering more as the ball would be on screen longer while your poke does the calculations (which is the slower part of this).
@@NeilRoy Sure, but code golf is about trying to fit as much as possible into one space, not about it necessarily producing the best results. :)
Also I totally forgot that print can be abbreviated as ? which would have saved even more space.
@@fluffycritter You still want it to run reasonably well, and having the delay while the screen is blank is not good. And it already fits on one line.
I'd like to challenge all you real experts to come up with a version of the CLS-inclusive 1-liner that takes inspiration from The Story of Mel.
I wonder if the color choice was because it most closely resembles a tennis court (when played on grass).
Or maybe a pool table.
Well done, mind melting solution onto one line. This bouncing ball programme (well the vic 20 version) was one that never left my memory since i discovered it all those years ago.
I used to come up to people with an one liner, on the C64, that moved a ball erratically and replaced the old posistion with the reverse circle. Looked hilarious and I had to resort to two lines to make it also move diagonally. I called it the miner.
I remember writing my own version of Arkanoid on the C64 from scratch with multiple levels/patterns of blocks. Wish I still had it
Man this took me back. In the 80s we used to have 1 liner, 5 liner and 10 liner programming challenges. It really is incredible what people came up with. Simple text editors, databases, even a few games. I miss the ingenuity of the 8 bit days.
Just got a pristine copy of the PRG after nearly 40 years. Looking forward to reacquainting myself with its contents. That’s a delightful solution to clearing the screen.
Thanks Robin, you really have a gift of making programming fun and interesting. Another great video.
This "all these lines into one line" thing never gets old. Seriously. It's always amazing to watch the process. I think by now, you might showcase "it can't be done" examples and let's see if your audience will participate in trying and presenting their results to you somehow.
You're so good at what you do, but I'm curious if there are things you can't do?!
Love your investigations and experiments Robin! Thank you so much for taking the time for us :D (if you can guarantee that the ball won't be in the same place, drawing the new position then erasing the old position will look far less flickery (a ball will always be visible) and look smoother (as the moment where two balls are visible will act as an intermediate frame of animation))
I’m assuming this raises the issue of needing another variable to track the old position. Definitely good for a longer version. And even having a trail of a few balls (“snake”) would be cool.
@@andrewgillham1907 - If there's a smaller circular character, that could be written over the old position, and then blanked on the next frame - that would play into the 'ghosting' effect - although does mean an additional trailing-blanking write - so would be slower
@@andrewgillham1907 I could be wrong, but a new variable should not be required. Robin just needs to display then erase, rather than erase then display.
I'm not entirely clear on what the pokes do, so I could very wrong.
I just know that from my own experience of moving a dot in Atari BASIC, it was relatively smooth compared to this. Then again, I never it down to 1 line of code.
I used that Bounding Ball program and made it into a breakout game. I managed to get it to run very well considering it was all in basic. I later got it to run better and with redefined characters by using Simons' Basic cartridge and improved the overall programming. I was 13 at the time and it was 1984. Just wish I had the cassette it was saved on today.
Yeah, back in the day, some friends of mine wanted us to create a similar Breakout game that we called "Beat The Wall" (basically me telling them what to type in)... based on this bouncing ball program.
On the first test run there was a bug in the bit that was supposed to detect the block and bounce it back so the ball just ripped through all the blocks. They all laughed, got bored and gave up, so we never got to fix it. To this day they are still making fun of me for my crappy "Beat The Wall" game!
0:26 My first programming experience was with the VIC-20 User's Guide.
14:16 The program didn't change the cursor color. By default, on newer C64s, it'd be light blue, which would probably be worse.
18:42 There'd be more variety to the bouncing pattern if the numbers of rows and columns were primes.
19:37 The relative flicker is also reduced by keeping the ball on the screen much longer than it's turned off.
28:26 Should start malfunctioning after T reaches 4.2-billion.
36:01 The abbreviations would be more clear if the character set were lowercase.
39:10 I get 2.10 seconds for T to increment 40 times, meaning it will take 7.1 years to overflow the integer range of floating-point numbers. Slowing the program down by re-executing the DEF FN helps to avoid this! It should never "overflow" the floating-point range since after passing the 32-bit mantissa range, T=T+1 will effectively round down to T=T+0.
That's very interesting about the width and height affecting the bouncing pattern; that's configurable on the VIC-20. Maybe a one-line VIC-20 version could also set the screen to 29x23 to make it more interesting. Or if 29 is too wide, 23 by 19 or something.
Good point about T=T+1 rounding down to T=T+0! So I suppose the ball would just freeze once the 7+ years or whatever had passed. It would appear to have crashed, but it's really just adding (effectively) zero each step.
I'm so glad I finally watched this. I'm usually not a big fan of "code golf" and I thought 40m seemed long for "one line". But, wow, I have never seen anyone give such a lucid step-by-step process of transforming a program. Amazing job in story telling, giving the motivation before each change. For me, it was like clues so I could pause the video and try to guess what's coming next instead of being told the answer outright. (For example, when you showed how the numbers oscillate.)
I also love that you explained everything at the perfect level, not skipping over things a C64 expert might forget to mention, like G shift+O is shorthand for GOTO. You didn't dwell on anything too long, either, or overexplain.
In fact, I feel guilty now with this comment because I've clearly gone on far too long just to say "THUMBS UP! You've got a new subscriber."
Nice work Robin. It is definitely fun to “re-experience” the joy you got as a kid going through the C64 User Guide. 😀
The bouncing ball is neat and cramming it into one line is impressive. I would say another feature people could try to add is some way to get more randomness as the ball is clearly only following a few paths over and over. With some randomness it should eventually clear the whole screen not just certain paths.
Anyway keep up the good work. I’m amazed (& entertained) by how far “10 PRINT” and/or one-liners can go and still be fairly comprehensible. And look cool.
Yes, it would be more interesting if it somehow followed a more varied path. As csbruce noted, if the width and height of the screen were prime numbers, such as 41x23, then the same logic would allow it to cover the whole screen.
First a "10 PRINT" to fill the screen and then a bouncing ball to clear it! A two line program :-P
Sorry for for being an idiot but can you explain why if the width and height were primes the trajectory of that ball would be more variable?
@@kernelramdisk3348 They don't have to be primes, just relatively prime (i.e. not sharing any common factors other than 1). It's because then the wavelengths wouldn't match up so frequently.
I think the early days of the C64 were the best. Those programs were just a nice way to get to know the computer. Although I I always sucked at programming.
I kind of started to miss you ;) thank you very much for that new video. I will enjoy it, for sure!
The Amstrad CPC 464 book was amazing. Would love to see an analysis
Robin, thanks for the screen clear idea. It's very counter intuitive way of thinking, because we have to add something to it to make it not be active, as opposed to doing something to it to make it active...or something like that. I just know that some vehicle braking systems require power to male them be released, rather than requiring power to make them work.
It seems like there are more opportunities to use math to control things on the screen.
By the way, I really appreciate the oscillator info.
I watched portions several times, and learned a lot over the last 24 hrs. Thank you so much.
Another great one. I think I will have a go at this. Also, my favourite song so far, at the end.
Three decades late, but I’m finally into a little CBM programming myself, and these videos helps me a lot. Thank you!
I bought a second hand C64 manual. It’s printed in the UK and less fancy than the one you showed. The code examples are just plain text on paper, not with a black background. The horrible color green in the bouncing ball code is however replaced by blue.
The music chapter is totally different than the US version. Strange. Perhaps you can spend a whole episode on the different versions C64 User Guide……
Roll the clock back 45 years, I wish you would have been my computer science teacher! You have an amazing mind!
Soooo many memories back...thank you so much for your video and your passion. 🙂🙂🙂
So satisfying when the "ball" hits the corner perfectly. Reminds me of DVD players.
I altered it slightly. I removed the pokez,32 and put a ?"{CLS}" just before the pokez,81 so the screen is cleared, then the ball is drawn and the ball stays on screen most of the time during code execution and is only momentarily cleared before redrawn and this clears the screen of course. It's almost flicker free this way. I tried adding the Z calculation within the poke but I find it flickers much more that way because the ball is gone longer while it calculates the position before poking where as calculating that ahead of time means the ball is on screen during calculations and only moved once they are complete resulting in almost no flicker at all except to move it.
If this one-liner were sent via time machine to an early 80s Commodore/computer magazine...
Alternate bouncing ball:
0D=-(X=0)+(X=39)+D:E=-(Y=0)+(Y=24)+E:X=X+D:Y=Y+E:POKEA,32:A=1024+Y*40+X:POKEA,81,GOTO
Still 79 characters crunched. Once difference though, it takes two loops to reverse direction, because the D/E calculations only add or subtract 1. So D/E end up zero at the first boundary check, then will be +/-1 the next.
I think there are a few mistakes like;
Y=Y+D => Y=Y+E
1024+Y*40 => 1024+Y*40+X
Copy & paste ready version is below:
0d=-(x=0)+(x=39)+d:e=-(y=0)+(y=24)+e:x=x+d:y=y+e:pOa,32:a=1024+y*40+x:pOa,81:gO
@@c64skate Thanks - I fixed typo in original.
I realized I can save 2 characters:
0d=d-(x=0)+(x=39):e=e-(y=0)+(y=24):x=x+d:y=y+e:pokea,32:a=1024+y*40+x:pokea,81:goto
Or you can reduce the flicker by moving the *40:
0d=d-(x=0)+(x=39):e=e-(y=0)+(y=960):x=x+d:y=y+e*40:pokea,32:a=1024+y+x:pokea,81:goto
From time to time I enjoy working on one-liners to learn from other programmers, and I try to improve them.
I do not know if you are interested or if you care at all, but I managed to get your code a bit faster.
Thank you for your interest, and maybe a friendly comment. Best, Holger
0 D=D-(X=.)+(X=39):E=E-(Y=.)+(Y=24):X=D+X:Y=E+Y:P🭽A,32:A=Y*4E1+X+1024:P🭽A,81:G🭽
0 D=D-(X=.)+(X=39):E=E-(Y=.)+(Y=24):X=D+X:Y=E+Y:POKEA,32:A=Y*4E1+X+1024:POKEA,81:GOTO
Wow clever method. And really well explained by using the print statements!
Very clever techniques indeed,
anyways, 35:18 for a second I thought why not we pass T as argument along with B and then we can goto 1 and eliminate the time needed to redefine the function, but then I realized that only one argument is supported.
If I remember correctly MSX supports multiple arguments per function and one line of code can be 255 characters, it also has a LOCATE command to print at specific x,y coordinates, which gives you more room for one-liner programs (not so challenging for you, I know😎).
anyways, commodore is more capable graphic wise I believe.
Thanks Robin!
It’s always a highlight when Robin upload a new video.
I had never noticed the screen colors of the 'bouncing ball' program. I went to pick up my 1986 manual and in fact... POKE 53280,7:POKE 53281,13 ... At the time I was using the C64 with a Mivar (Italian brand) 17 inches black and white 😁👍🏻
Miss this computer. Was so much fun with the overlay on the keyboard for gaming.
This is so damn clever. I love it!!
So that's just brilliant! Nice work!
Great to have you back.
Commodore's sample code has lots of computation occurring between the time the ball is erased and once again redrawn. While certainly not compact, I think there is value in having some time delay leaving the ball visible versus hidden (call it the visible duty cycle, if you like). Here's one idea of how it might be coded...
10 poke53280,11:poke53281,0:poke646,7
20 dx=1:dy=1:printchr$(147);
30 a=1024+40*y+x:ifb=0thenb=a
40 pokeb,32:pokea,81:fort=1to10:next
50 b=a:x=x+dx:y=y+dy
60 ifx38thendx=-dx
70 ify23thendy=-dy
80 goto30
So glad to see Josip mentioned!
The ball seems to move in the same path all the time 🥺
That's because of the relationship between the X and Y values
So user-friendly. Completely understandable by someone who really didn't have a clue about computing .
Your 'bouncing ball' has elements of 'Breakout' about it. It is slowly removing the white text but it ends in a repeating loop following determined paths.
Fascinating. Nice to see C64 coding videos.
The bouncing ball was my first program I typed in on my c64.
I was 8 years old.
Fun video to watch. It brings back memories when I had to crunch code. Thanks for the video. I suppose the next step would be to execute this in machine language? But that is another video...!!! LOL!
I would suggest starting an IOC64BCC but let's face it, it's hard not to write obfuscated C64 BASIC. Although, you might be able to compete in the IOCCC if you know C. I am curious if you could implement a real time flight sim on the C64, as that is definitely the most impressive entry I've seen. Check out Banks' entry in 1998, even shaped the source code to look like an airplane.
Fascinating use of the DEF FN there. I remember typing this in and making small changes - removing the space so you get a trail, starting at different points and getting rid of those awful colours!
Great video Robin :) ... Josip does some great stuff :) ....
Well done. I wonder how this could be adapted for the VIC-20.
I think I preferred the 2-line version. You've optimized for space at the expense of efficiency. The division operations are expensive.
Fun video. Thanks Robin
14:35 My first two thoughts as a developer immediately after I saw this code for the very first time: 1024+X+40*Y should be stored to a variable, so it doesn't have to be calculated twice and lines 60 and 70 should come after line 110, so the ball is constantly visible on screen during all the other code lines that also take time to execute, probably reducing the flickering a lot (and as the address is cached, it's okay to change X and Y, clearing is done via the cached address). So with zero C64 programming experience, I'd suggest the following optimization:
10 PRINT CHR$(147)
20 POKE 53280,7 : POKE 53281,13
30 X=1 : Y=1
40 DX=1 : DY=1
45 ADDR=1024+X+40*Y
50 POKE ADDR,81
80 X=X+DX
90 IF X=39 THEN DX=-DX
100 Y=Y+DY
110 IF Y=24 THEN DY=-DY
115 FOR T=1 TO 10 : NEXT
116 POKE ADDR,32
120 GOTO 45
(Just a little note: C64-Basic only cares for the first two characters of a variable, so ADDR could be reduced to AD.)
@@BikeAreaBut would that make a performance difference? As if not, source code is written for human beings, computers (and also interpreters) would be fine with just hex digits (much easier to process, even for an interpreter).
One can spare 1 char bei using 4↑5 instead of 1024
Nothing is slower in Basic than calculating the power function. 😉
“…does it work? Ship it!” Hahahahahaha. I laughed and laughed.
Really liked this episode!
I have a suggestion for the bouncing ball. How about using SIN. Then you don't need that function. I suspect it would be a lot shorter as well.
I was thinking about using the trig functions but none of them are linear so the ball would look like it's speeding up and slowing down, probably?
@@8_Bit yeah it would look different possibly. But technically it would work
@@8_Bit Could you somehow use the Triangle waveform from the SID chip? I dunno, just spitballing
I was thinking that A mod B equals A AND (B-1) if B is a power of 2, so that might work for a 33x17 screen, but it doesn't really gain much.
C64 was awsom for kids as you could program your own game , you got a book of games learned how it all worked and then create your own game.
19:15 you also notice that the bounce is very regular... it follows the same path
24:00 which you will take advantage of eventually.
2:28 i startet laughing so hard, i nearly lost consciousness
One BASIC line is not the same as one screen line, so yes, your program is one BASIC line.
Code golfing on a C= 64, this video is the cutest.
For anyone who doesn't know what a fortnight is that the program could run for ~55 of them... They are about equal to 6 7/8 stone or 4.9 decibushels.
Total run time is a little over two years.and one month.
Great ...
Here the MM Basic Version for the Raspberry Pi Pico (PicoMite VGA) in MM-Basic
____
Do :D=12*A(78):E=8*A(158):Text E,D,"0":Inc T:Pause 20:Text E,D," ":Loop
Function A(B):A=Abs(T-Int(T/B)*B-B/2):End Function
___
🙂
I always look forward to the end credits music
my lazy bouncing ball in 79 standard character input. Amiga demo scene eat ur heart out lol:
2 pokes,46:s=1024+40*sin(t/40)^2+int(25*sin(t/25)^2)*40:pokes,81:t=t+1.5:goto 2
From time to time I enjoy working on one-liners to learn from other programmers, and I try to improve them.
I do not know if you are interested or if you care at all, but I managed to get your code a bit faster.
Thank you for your interest, and maybe a friendly comment. Best, Holger
0P🭽S,46:S=S╮(T/4E1)↑2*4E1+INT(25*S╮(T/25)↑2)*4E1+1024:P🭽S,81:T=T+1.5:G🭽
0 POKES,46:S=SIN(T/4E1)↑2*4E1+INT(25*SIN(T/25)↑2)*4E1+1024:POKES,81:T=T+1.5:GOTO
Incredible, very nice :)
Hey, Robin, what are some of your favorite clever code snippets in C64 BASIC? For me, when I saw this particular one in a magazine listing once it stuck with me to this day for its simplicity and usefulness:
A = 1 - A
Very useful for alternating between 0 and 1 (or any two values with some slight modification). Another I like, which I believe only works on 8 bit Commodore computers, is for multi-loading:
10 If A = 0 Then A = 1: Load "part 1",8,1
20 If A = 1 Then A = 2: Load "part 2",8,1
etc.
This was a mystery to me until I found out why it works.
On the AMSTRAD CPC you could use the CRTC to synchronise to frame flyback so that the program could synchronise to each frame on the display with a single CALL instruction. This way you'd get rid of the flickering. Surely there is a poke on the C64 for this?
Yes, that could be done with a PEEK or WAIT command if there were room to fit it in the single line of code.
I like the non flickering version and it is only 5 characters too long... :)
@7:00 Very clever!
Haha, I wondered about _that_ color combination too! Wouldn't exactly be even worse on a B/W TV or other monitor, since it seems to have low contrast? Wouldn't a grayscale screen make it even lower contrast?
Yeah, I would definitely like to see this with a dark background and a light ball or vice versa.
Considering it emanated from the 80's, it makes perfect sense.
@@TheUtuber999: Not really. We were already well into color TV by then.
I thought it was supposed to represent a tennis court with grass.
I know that code! I made a rudimentary brickout game with it when I first got my C64!! Semirelated, but I recently tried porting Steve Wozniak's Little Brickout to C64 BASIC. The original version relies heavily on Integer BASIC draw commands so it's a really interesting challenge trying to get it working and playable on the C64. The only way I found it could be done was if I used print commands to draw the paddle instead of pokes to screen memory. Unfortunately that also meant having the game play lopsided, with the paddle moving horizontally at the top of the screen. I'm not a BASIC pro, though, so I'd be really interesting in seeing what techniques you might use to get it working!
Amazing and amusing
I'd love to see something like this or the maze written in assembly on thr C64 to see how much faster it goes.
Robin did an assembly-language version of the maze not that long ago. I recall it being about 100x faster than the BASIC implementation.
That's a lot faster but not blindingly fast. It's still calling the BASIC functions to print and scroll. Further optimization could be done, but that would be an unfair comparison.
@@Starchface Nice- that's good to know :D
That was fun! I was wondering why, in your two line version before the final, why did you choose to GOTO 0 (where the function was defined) instead of GOTO 1?
Very clever optimizations!
I hated programming that, and that balloon 😬 it was the promise to learn coding that got me a c64 aged 8.. all downhill from there 😂
Great video
0 x=x+1+78*(x=39):y=y+1+48*(y=24):pOa,32:a=1024+aB(y)*40+aB(x):pOa,81
From time to time I enjoy working on one-liners to learn from other programmers, and I try to improve them.
I do not know if you are interested or if you care at all, but I managed to get your code a bit faster.
Thank you for your interest, and maybe a friendly comment. Best, Holger
0X=X+1+78*(X=39):Y=Y+1+48*(Y=24):P🭽A,32:A=A🭲(Y)*4E1+A🭲(X)+1024:P🭽A,81:G🭽
0 X=X+1+78*(X=39):Y=Y+1+48*(Y=24):POKEA,32:A=ABS(Y)*4E1+ABS(X)+1024:POKEA,81:GOTO
We did this in elementary school how awesome!!
You made a one-line bouncing ball in elementary school?
in the 2 line bouncing ball, what if line 0 had the x and y drawing of a blank space happen before the coordinates being calculated with a line separator with the colon between the action to clear the coordinate and the coordinate calculation of line 0? is that possible in that method? If so, shouldn't most of the flicker of the drawing be negated?
I was wondering, what's the name of the "Island " demo Robin mentioned in some videos which he described as "has a lot of moving objects on the screen at once"? I can't seem to find, so let's see if someone can help. :)
I see C64 BASIC does not have REPEAT/UNTIL, but will it let you use FOR A=0 TO 1 STEP 0 to create an infinite loop without GOTO?
Yes. That is an working loop.
Only way to improve the yellow/green screen colors would have been to keep the light-blue text color: All The Pastels FTW!
Very interesting video! I'm guessing the program for the Patreon credits uses a similar oscillator function perhaps?
clear:for i=1 to 2:do something:i=i-1:next i
0 DEFFNA(B)=ABS(T-INT(T/B)*b-b/2):X=1024+FNA(48)*40+FNA(78):POKEZ,32:Z=X:POKEZ,81:T=T+1:GOTO
WOULD THAT WORK?
From time to time I enjoy working on one-liners to learn from other programmers, and I try to improve them.
I do not know if you are interested or if you care at all, but I managed to get your code into one line.
Thank you for your interest, and maybe a friendly comment. Best, Holger
0D🭶FNA(B)=A🭲(T-INT(T/B)*B-B/2):X=4↑5+FNA(48)*40+FNA(78):P🭽Z,0:Z=X:P🭽Z,8:T=T+1:G🭽
0 DEFFNA(B)=ABS(T-INT(T/B)*B-B/2):X=4↑5+FNA(48)*40+FNA(78):POKEZ,0:Z=X:POKEZ,8:T=T+1:GOTO
Have you done 10 print in 6502 Assembly yet?
Yes he has: th-cam.com/video/IPP-EMBQPhE/w-d-xo.html
Yes he did
have you seen the c64 demos with wavy scrolling text ?.. can you do a basic version of the sin scrolling version so i can convert it to C# ?
Write it in machine code then 1 sys call in basic. Job done.
Yeah, I know it’s a bit of a cheat, but different route same outcome.
All this POKEing faff because Commodore didn't bother to implement a LOCATE command (or equivalent, like PRINT AT).
True, but on the bright side, it introduced many of us to the lower-level workings of the computer and made assembly language that much more attractive.
@@8_Bit Of course, you can still do that on many other computers if you want to, but you don't _need_ to. Somewhere I have a dot matrix printed list of Apple II BASIC commands and their PEEK/POKE/CALL equivalents.
Yes, I'm mainly saying it gave us some extra motivation to learn assembly. It'd be interesting to see if Commodore machines in particular produced more assembly language programmers per capita than those with friendlier BASICs.
On the flip side, the TI-99/4a had a PRINT AT like feature (CALL HCHAR, I believe) but no POKEs or SYS at all, completely preventing the user from dabbling with any feature (such as sprites) that weren't built into the language, and even preventing machine language programs from being loaded from tape. The only solution is to buy the Extended BASIC cartridge for extra money to unlock those features.
@@8_Bit Probably most TI owners had the Extended BASIC cartridge, because the built-in BASIC is so slow and limited, and lots of software on cassette required it. TI did have an assembly language cartridge for it, too, although that required a 32K disk system to run.
@@vwestlife _Beagle Bros_ *Peeks, Pokes, and Pointers* chart was super popular back in the day.
Also _S-C DocuMentor Applesoft Disassembly_ is a reversed engineered listing of Applesoft by Bob Sander-Cederlof.
Would be great to see some sort of random bounce (but maybe 2 line)
Maze/like pattern: The whole screen clearing is unnecessary: Just doing print and jump makes the program so fast that the screen will quickly fill up with pattern anyway.
Would you be interested to Reverse engineering of the Rambo First Blood Part II Ocean cassette loader to show how it works?
Hey ....how do u input user definable graphics...its easy on the BBC...u know we're you add the squares together that are numbered 1 2 4 8 16 32 64 128 in any combination
i wish this video was available in 82